Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
Manuel Jiménez Friaza 2019-01-20 12:58:27 +01:00
commit 4e8fc6d198
89 changed files with 1329 additions and 638 deletions

View File

@ -11,13 +11,11 @@ variables:
MYSQL_DATABASE: hello_world_test
MYSQL_ROOT_PASSWORD: mysql
services:
- mysql:5.7
before_script:
# prevent error installing buggy postgresql-client package
- mkdir -p /usr/share/man/man1 /usr/share/man/man7
- apt-get update -yqq
- apt-get install -yqq git mysql-server mysql-client libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev
- apt-get install -yqq --no-install-recommends git mysql-client postgresql-client libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libaspell-dev libpcre3-dev libtidy-dev
# Install PHP extensions
- docker-php-ext-install mbstring mcrypt pdo_mysql pdo_pgsql curl json intl gd xml zip bz2 opcache
# Install & enable Xdebug for code coverage reports
@ -25,12 +23,47 @@ before_script:
- docker-php-ext-enable xdebug
# Install and run Composer
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install
# Install dev libraries from composer
- php composer.phar install --no-progress
# Configure PHP values, needed for phpunit code coverage HTML generation
- echo "memory_limit = 256M" > /usr/local/etc/php/conf.d/hubzilla.ini
# We test PHP7 with MySQL, but we allow it to fail
# We test PHP7 with MySQL
test:php:mysql:
services:
- mysql:5.7
script:
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
# test PHP7 with PostgreSQL
test:php:postgres:
services:
- postgres:latest
variables:
POSTGRES_DB: ci-db
POSTGRES_USER: ci-user
POSTGRES_PASSWORD: ci-pass
script:
- export PGPASSWORD=$POSTGRES_PASSWORD
- psql --version
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
# Import hubzilla's DB schema
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
# Show databases and relations/tables of hubzilla's database
#- psql -h "postgres" -U "$POSTGRES_USER" -l
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
# Run the actual tests
- vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
artifacts:
expire_in: 1 week
# Gitlab should show the results, but has problems parsing PHPUnit's junit file.
reports:
junit: tests/results/junit.xml
# Archive test results (coverage, testdox, junit)
name: "$CI_COMMIT_REF_SLUG-$CI_JOB_NAME"
paths:
- tests/results/

View File

@ -1,3 +1,33 @@
Hubzilla 3.8.8 (2018-12-22)
- Fix issue with linkinfo
- Fix cURL with HTTP/2
- Remove scale_external_images()
- Style highlight bbcode via css
- Make mod channel deal with b64 encoded mid's
- Fix email retrieval in OAuth2Storage
- Add reinstall option to util/addons
- Remove deprecated caching protection from mod photo
- Add missing check for observer in mod like
- Articles: default to logged in channel if channel name is not passed
- Wiki: fix preview issue with hyperlinks
- Cart: backport fixes from osada
- Gallery: provide file extensions for better compatibility
- Hsse: fix issue when linkinfo data was inserted
- Diaspora: remove deprecated scale_external_images()
Hubzilla 3.8.7 (2018-12-14)
- Fix issue with linkdropper in comment area
- Fix regression wit app ordering
- Fix return if readImnageBlob() throws an exception
- Introduce photo_view_filter hook
- Fix home notifications not expanding in certain situations
- Fix for dark schema
- Fix total identities restriction
- Fix article page title not updating if article has no title
- Gallery: the gallery app will now act as the full-size photo viewer in /photos if installed
Hubzilla 3.8.6 (2018-12-03)
- Prevent incompatible export files (osada/zap) from being imported
- Catch exception if readImageBlob() receives bogus data

View File

@ -16,8 +16,6 @@ if(array_search( __file__ , get_included_files()) === 0) {
class Master {
static public $queueworker = null;
static public function Summon($arr) {
proc_run('php','Zotlabs/Daemon/Master.php',$arr);
}
@ -25,126 +23,21 @@ class Master {
static public function Release($argc,$argv) {
cli_startup();
$maxworkers = get_config('system','max_queue_workers');
$hookinfo = [
'argv'=>$argv
];
if (!$maxworkers || $maxworkers == 0) {
logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc,$argv);
self::ClearQueue();
} else {
logger('Master: enqueue: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
$workinfo = ['argc'=>$argc,'argv'=>$argv];
q("insert into config (cat,k,v) values ('queuework','%s','%s')",
dbesc(uniqid('workitem:',true)),
dbesc(serialize($workinfo)));
self::Process();
call_hooks ('daemon_master_release',$hookinfo);
$argv = $hookinfo['argv'];
$argc = count($argv);
if ((!is_array($argv) || (count($argv) < 1))) {
return;
}
logger('Master: release: ' . json_encode($argv), LOGGER_ALL,LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc,$argv);
}
static public function GetWorkerID() {
$maxworkers = get_config('system','max_queue_workers');
$maxworkers = ($maxworkers) ? $maxworkers : 3;
$workermaxage = get_config('system','max_queue_worker_age');
$workermaxage = ($workermaxage) ? $workermaxage : 300;
$workers = q("select * from config where cat='queueworkers' and k like '%s'", 'workerstarted_%');
if (count($workers) > $maxworkers) {
foreach ($workers as $idx => $worker) {
$curtime = time();
$age = (intval($curtime) - intval($worker['v']));
if ( $age > $workermaxage) {
logger("Prune worker: ".$worker['k'], LOGGER_ALL, LOGGER_DEBUG);
$k = explode('_',$worker['k']);
q("delete from config where cat='queueworkers' and k='%s'",
'workerstarted_'.$k[1]);
q("update config set k='%s' where cat='queuework' and k='%s'",
dbesc(uniqid('workitem:',true)),
'workitem_'.$k[1]);
unset($workers[$idx]);
}
}
if (count($workers) > $maxworkers) {
return false;
}
}
return uniqid('',true);
}
static public function Process() {
self::$queueworker = self::GetWorkerID();
if (!self::$queueworker) {
logger('Master: unable to obtain worker ID.');
killme();
}
set_config('queueworkers','workerstarted_'.self::$queueworker,time());
$workersleep = get_config('system','queue_worker_sleep');
$workersleep = ($workersleep) ? $workersleep : 5;
cli_startup();
$work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1",
'workitem_'.self::$queueworker,
dbesc('workitem:%'));
$jobs = 0;
while ($work) {
$workitem = q("select * from config where cat='queuework' and k='%s'",
'workitem_'.self::$queueworker);
if (isset($workitem[0])) {
$jobs++;
$workinfo = unserialize($workitem[0]['v']);
$argc = $workinfo['argc'];
$argv = $workinfo['argv'];
logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
//Delete unclaimed duplicate workitems.
q("delete from config where cat='queuework' and k='workitem' and v='%s'",
serialize($argv));
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc,$argv);
//Right now we assume that if we get a return, everything is OK.
//At some point we may want to test whether the run returns true/false
// and requeue the work to be tried again. But we probably want
// to implement some sort of "retry interval" first.
q("delete from config where cat='queuework' and k='%s'",
'workitem_'.self::$queueworker);
} else {
break;
}
sleep ($workersleep);
$work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1",
'workitem_'.self::$queueworker,
dbesc('workitem:%'));
}
logger('Master: Worker Thread: queue items processed:' . $jobs);
q("delete from config where cat='queueworkers' and k='%s'",
'workerstarted_'.self::$queueworker);
}
static public function ClearQueue() {
$work = q("select * from config where cat='queuework' and k like '%s'",
dbesc('workitem%'));
foreach ($work as $workitem) {
$workinfo = unserialize($workitem['v']);
$argc = $workinfo['argc'];
$argv = $workinfo['argv'];
logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc,$argv);
}
$work = q("delete from config where cat='queuework' and k like '%s'",
dbesc('workitem%'));
}
}

View File

@ -625,7 +625,12 @@ class Notifier {
continue;
}
$hash = new_uuid();
// Do not change this to a uuid as long as we have traditional zot servers
// in the loop. The signature verification step can't handle dashes in the
// hashes.
$hash = random_string(48);
$packet = null;
$pmsg = '';

View File

@ -69,7 +69,7 @@ class Onepoll {
return;
}
if($contact['xchan_network'] !== 'zot')
if(! in_array($contact['xchan_network'],['zot','zot6']))
return;
// update permissions

View File

@ -110,7 +110,7 @@ class Poller {
}
if($contact['xchan_network'] !== 'zot')
if(! in_array($contact['xchan_network'],['zot','zot6']))
continue;
if($c == $t) {

View File

@ -12,7 +12,6 @@ class Queue {
require_once('include/items.php');
require_once('include/bbcode.php');
if($argc > 1)
$queue_id = $argv[1];
else
@ -61,10 +60,20 @@ class Queue {
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
// or twice a day.
$r = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ",
$sqlrandfunc = db_getfunc('rand');
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
db_utcnow()
);
while ($r) {
foreach($r as $rv) {
queue_deliver($rv);
}
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
db_utcnow()
);
}
}
if(! $r)
return;

View File

@ -64,7 +64,7 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
return( [
'webfinger' => channel_reddress($x),
'portable_id' => $x['channel_hash'],
'email' => $a['account_email'],
'email' => $a[0]['account_email'],
'username' => $x['channel_address'],
'user_id' => $x['channel_id'],
'name' => $x['channel_name'],

View File

@ -32,6 +32,9 @@ class Activity {
if($x['type'] === ACTIVITY_OBJ_THING) {
return self::fetch_thing($x);
}
if($x['type'] === ACTIVITY_OBJ_EVENT) {
return self::fetch_event($x);
}
return $x;
@ -99,6 +102,40 @@ class Activity {
}
}
static function fetch_event($x) {
// convert old Zot event objects to ActivityStreams Event objects
if (array_key_exists('content',$x) && array_key_exists('dtstart',$x)) {
$ev = bbtoevent($x['content']);
if($ev) {
$actor = null;
if(array_key_exists('author',$x) && array_key_exists('link',$x['author'])) {
$actor = $x['author']['link'][0]['href'];
}
$y = [
'type' => 'Event',
'id' => z_root() . '/event/' . $ev['event_hash'],
'summary' => bbcode($ev['summary']),
// 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']) ],
'source' => [ 'content' => format_event_bbcode($ev), 'mediaType' => 'text/bbcode' ],
'actor' => $actor,
];
if($actor) {
return $y;
}
}
}
return $x;
}
static function encode_item_collection($items,$id,$type,$extra = null) {
$ret = [
@ -546,6 +583,12 @@ class Activity {
}
static function activity_mapper($verb) {
if(strpos($verb,'/') === false) {
@ -562,6 +605,9 @@ class Activity {
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://purl.org/zot/activity/attendyes' => 'Accept',
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
];
@ -588,6 +634,70 @@ class Activity {
}
static function activity_decode_mapper($verb) {
$acts = [
'http://activitystrea.ms/schema/1.0/post' => 'Create',
'http://activitystrea.ms/schema/1.0/share' => 'Announce',
'http://activitystrea.ms/schema/1.0/update' => 'Update',
'http://activitystrea.ms/schema/1.0/like' => 'Like',
'http://activitystrea.ms/schema/1.0/favorite' => 'Like',
'http://purl.org/zot/activity/dislike' => 'Dislike',
'http://activitystrea.ms/schema/1.0/tag' => 'Add',
'http://activitystrea.ms/schema/1.0/follow' => 'Follow',
'http://activitystrea.ms/schema/1.0/unfollow' => 'Unfollow',
'http://purl.org/zot/activity/attendyes' => 'Accept',
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
];
foreach($acts as $k => $v) {
if($verb === $v) {
return $k;
}
}
logger('Unmapped activity: ' . $verb);
return 'Create';
}
static function activity_obj_decode_mapper($obj) {
$objs = [
'http://activitystrea.ms/schema/1.0/note' => 'Note',
'http://activitystrea.ms/schema/1.0/note' => 'Article',
'http://activitystrea.ms/schema/1.0/comment' => 'Note',
'http://activitystrea.ms/schema/1.0/person' => 'Person',
'http://purl.org/zot/activity/profile' => 'Profile',
'http://activitystrea.ms/schema/1.0/photo' => 'Image',
'http://activitystrea.ms/schema/1.0/profile-photo' => 'Icon',
'http://activitystrea.ms/schema/1.0/event' => 'Event',
'http://activitystrea.ms/schema/1.0/wiki' => 'Document',
'http://purl.org/zot/activity/location' => 'Place',
'http://purl.org/zot/activity/chessgame' => 'Game',
'http://purl.org/zot/activity/tagterm' => 'zot:Tag',
'http://purl.org/zot/activity/thing' => 'Object',
'http://purl.org/zot/activity/file' => 'zot:File',
'http://purl.org/zot/activity/mood' => 'zot:Mood',
];
foreach($objs as $k => $v) {
if($obj === $v) {
return $k;
}
}
logger('Unmapped activity object: ' . $obj);
return 'Note';
}
static function activity_obj_mapper($obj) {
if(strpos($obj,'/') === false) {
@ -1236,6 +1346,20 @@ class Activity {
}
static function get_actor_bbmention($id) {
$x = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' or hubloc_id_url = '%s' limit 1",
dbesc($id),
dbesc($id)
);
if($x) {
return sprintf('@[zrl=%s]%s[/zrl]',$x[0]['xchan_url'],$x[0]['xchan_name']);
}
return '@{' . $id . '}';
}
static function decode_note($act) {
@ -1320,14 +1444,44 @@ class Activity {
$s['summary'] = self::bb_content($content,'summary');
$s['body'] = ((self::bb_content($content,'bbcode') && (! $response_activity)) ? self::bb_content($content,'bbcode') : self::bb_content($content,'content'));
$s['verb'] = self::activity_mapper($act->type);
$s['verb'] = self::activity_decode_mapper($act->type);
if($act->type === 'Tombstone') {
$s['item_deleted'] = 1;
}
$s['obj_type'] = self::activity_obj_mapper($act->obj['type']);
$s['obj'] = $act->obj;
$s['obj_type'] = self::activity_obj_decode_mapper($act->obj['type']);
if($s['obj_type'] === ACTIVITY_OBJ_NOTE && $s['mid'] !== $s['parent_mid']) {
$s['obj_type'] = ACTIVITY_OBJ_COMMENT;
}
if($act->obj['type'] === 'Event') {
$s['obj'] = [];
$s['obj']['asld'] = $act->obj;
$s['obj']['type'] = ACTIVITY_OBJ_EVENT;
$s['obj']['id'] = $act->obj['id'];
$s['obj']['title'] = $act->obj['summary'];
if(strpos($act->obj['startTime'],'Z'))
$s['obj']['adjust'] = true;
else
$s['obj']['adjust'] = false;
$s['obj']['dtstart'] = datetime_convert('UTC','UTC',$act->obj['startTime']);
if($act->obj['endTime'])
$s['obj']['dtend'] = datetime_convert('UTC','UTC',$act->obj['endTime']);
else
$s['obj']['nofinish'] = true;
$s['obj']['description'] = $act->obj['content'];
if(array_path_exists('location/content',$act->obj))
$s['obj']['location'] = $act->obj['location']['content'];
}
else {
$s['obj'] = $act->obj;
}
$instrument = $act->get_property_obj('instrument');
if((! $instrument) && (! $response_activity)) {

View File

@ -57,7 +57,7 @@ class Apps {
}
static public function get_base_apps() {
return get_config('system','base_apps',[
$x = get_config('system','base_apps',[
'Connections',
'Network',
'Settings',
@ -72,6 +72,8 @@ class Apps {
'Mail',
'Profile Photo'
]);
call_hooks('get_base_apps',$x);
return $x;
}
static public function import_system_apps() {
@ -808,12 +810,14 @@ class Apps {
return($r);
}
static public function app_order($uid,$apps) {
static public function app_order($uid,$apps,$menu) {
if(! $apps)
return $apps;
$x = (($uid) ? get_pconfig($uid,'system','app_order') : get_config('system','app_order'));
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
$x = (($uid) ? get_pconfig($uid,'system',$conf) : get_config('system',$conf));
if(($x) && (! is_array($x))) {
$y = explode(',',$x);
$y = array_map('trim',$y);
@ -850,19 +854,25 @@ class Apps {
return false;
}
static function moveup($uid,$guid) {
static function moveup($uid,$guid,$menu) {
$syslist = array();
$list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']);
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
$list = self::app_list($uid, false, [ $menu ]);
if($list) {
foreach($list as $li) {
$syslist[] = self::app_encode($li);
$papp = self::app_encode($li);
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
continue;
$syslist[] = $papp;
}
}
self::translate_system_apps($syslist);
usort($syslist,'self::app_name_compare');
$syslist = self::app_order($uid,$syslist);
$syslist = self::app_order($uid,$syslist,$menu);
if(! $syslist)
return;
@ -887,23 +897,29 @@ class Apps {
$narr[] = $x['name'];
}
set_pconfig($uid,'system','app_order',implode(',',$narr));
set_pconfig($uid,'system',$conf,implode(',',$narr));
}
static function movedown($uid,$guid) {
static function movedown($uid,$guid,$menu) {
$syslist = array();
$list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']);
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
$list = self::app_list($uid, false, [ $menu ]);
if($list) {
foreach($list as $li) {
$syslist[] = self::app_encode($li);
$papp = self::app_encode($li);
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
continue;
$syslist[] = $papp;
}
}
self::translate_system_apps($syslist);
usort($syslist,'self::app_name_compare');
$syslist = self::app_order($uid,$syslist);
$syslist = self::app_order($uid,$syslist,$menu);
if(! $syslist)
return;
@ -928,7 +944,7 @@ class Apps {
$narr[] = $x['name'];
}
set_pconfig($uid,'system','app_order',implode(',',$narr));
set_pconfig($uid,'system',$conf,implode(',',$narr));
}

View File

@ -87,17 +87,29 @@ class DReport {
// Is the sender one of our channels?
$c = q("select channel_id from channel where channel_hash = '%s' limit 1",
$c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s' limit 1",
dbesc($dr['sender']),
dbesc($dr['sender'])
);
if(! $c)
return false;
// legacy zot recipients add a space and their name to the xchan. remove it if true.
$legacy_recipient = strpos($dr['recipient'], ' ');
if($legacy_recipient !== false) {
$legacy_recipient_parts = explode(' ', $dr['recipient'], 2);
$rxchan = $legacy_recipient_parts[0];
}
else {
$rxchan = $dr['recipient'];
}
// is the recipient one of our connections, or do we want to store every report?
$rxchan = $dr['recipient'];
$pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all');
if($pcf)
return true;

View File

@ -397,9 +397,7 @@ logger('4');
}
}
$closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness');
if($closeness === false)
$closeness = 80;
$closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness',80);
$y = abook_store_lowlevel(
[
@ -997,9 +995,19 @@ logger('4');
}
if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) {
foreach($x['delivery_report'] as $xx) {
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
// legacy recipients add a space and their name to the xchan. split those if true.
$legacy_recipient = strpos($xx['recipient'], ' ');
if($legacy_recipient !== false) {
$legacy_recipient_parts = explode(' ', $xx['recipient'], 2);
$xx['recipient'] = $legacy_recipient_parts[0];
$xx['name'] = $legacy_recipient_parts[1];
}
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),

View File

@ -131,14 +131,19 @@ class PConfig {
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
$now = datetime_convert();
if (! $updated) {
$updated = datetime_convert();
//Sometimes things happen fast... very fast.
//To make sure legitimate updates aren't rejected
//because not enough time has passed. We say our updates
//happened just a short time in the past rather than right now.
$updated = datetime_convert('UTC','UTC','-2 seconds');
}
$hash = hash('sha256',$family.':'.$key);
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
if (self::Get($uid, 'hz_delpconfig', $hash) > $updated) {
if (self::Get($uid, 'hz_delpconfig', $hash) > $now) {
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
return self::Get($uid,$family,$key);
} else {
@ -173,7 +178,7 @@ class PConfig {
}
else {
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
if ($new) {
@ -241,9 +246,9 @@ class PConfig {
if(is_null($uid) || $uid === false)
return false;
$updated = ($updated) ? $updated : datetime_convert();
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
$updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds');
$now = datetime_convert();
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
if (! $newer) {
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);

View File

@ -90,12 +90,12 @@ class Appman extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
if(argc() > 2) {
if(argc() > 3) {
if(argv(2) === 'moveup') {
Zlib\Apps::moveup(local_channel(),argv(1));
Zlib\Apps::moveup(local_channel(),argv(1),argv(3));
}
if(argv(2) === 'movedown') {
Zlib\Apps::movedown(local_channel(),argv(1));
Zlib\Apps::movedown(local_channel(),argv(1),argv(3));
}
goaway(z_root() . '/apporder');
}

View File

@ -17,25 +17,28 @@ class Apporder extends \Zotlabs\Web\Controller {
nav_set_selected('Order Apps');
$syslist = array();
$list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
if($list) {
foreach($list as $li) {
$syslist[] = Zlib\Apps::app_encode($li);
foreach( [ 'nav_featured_app', 'nav_pinned_app' ] as $l ) {
$syslist = [];
$list = Zlib\Apps::app_list(local_channel(), false, [ $l ]);
if($list) {
foreach($list as $li) {
$syslist[] = Zlib\Apps::app_encode($li);
}
}
}
Zlib\Apps::translate_system_apps($syslist);
Zlib\Apps::translate_system_apps($syslist);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
$syslist = Zlib\Apps::app_order(local_channel(),$syslist);
$syslist = Zlib\Apps::app_order(local_channel(),$syslist, $l);
foreach($syslist as $app) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
}
else {
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
foreach($syslist as $app) {
if($l === 'nav_pinned_app') {
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
}
elseif(strpos($app['categories'],'nav_pinned_app') === false) {
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
}
}
}

View File

@ -17,8 +17,16 @@ class Articles extends Controller {
if(argc() > 1)
$which = argv(1);
else
return;
if(! $which) {
if(local_channel()) {
$channel = App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
} else {
return;
}
}
profile_load($which);

View File

@ -124,6 +124,11 @@ class Channel extends Controller {
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
if(strpos($mid,'b64.') === 0)
$decoded = @base64url_decode(substr($mid,4));
if($decoded)
$mid = $decoded;
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
@ -375,6 +380,9 @@ class Channel extends Controller {
if((! $update) && (! $load)) {
if($decoded)
$mid = 'b64.' . base64url_encode($mid);
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.

View File

@ -101,7 +101,8 @@ class Connedit extends \Zotlabs\Web\Controller {
}
$profile_id = $_POST['profile_assign'];
$profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
if($profile_id) {
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
dbesc($profile_id),
@ -113,18 +114,23 @@ class Connedit extends \Zotlabs\Web\Controller {
}
}
$abook_incl = escape_tags($_POST['abook_incl']);
$abook_excl = escape_tags($_POST['abook_excl']);
$abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
$abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
$hidden = intval($_POST['hidden']);
$priority = intval($_POST['poll']);
if($priority > 5 || $priority < 0)
$priority = 0;
if(! array_key_exists('closeness',$_POST)) {
$_POST['closeness'] = 80;
}
$closeness = intval($_POST['closeness']);
if($closeness < 0)
$closeness = 99;
if($closeness < 0 || $closeness > 99) {
$closeness = 80;
}
$rating = intval($_POST['rating']);
if($rating < (-10))
@ -231,6 +237,8 @@ class Connedit extends \Zotlabs\Web\Controller {
}
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
abook_incl = '%s', abook_excl = '%s'
@ -733,9 +741,12 @@ class Connedit extends \Zotlabs\Web\Controller {
}
$slider_tpl = get_markup_template('contact_slider.tpl');
$slideval = intval($contact['abook_closeness']);
$slide = replace_macros($slider_tpl,array(
'$min' => 1,
'$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99),
'$val' => $slideval,
'$labels' => $label_str,
));
}
@ -892,7 +903,7 @@ class Connedit extends \Zotlabs\Web\Controller {
'$inherited' => t('inherited'),
'$submit' => t('Submit'),
'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
'$close' => $contact['abook_closeness'],
'$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
'$them' => t('Their Settings'),
'$me' => t('My Settings'),
'$perms' => $perms,

View File

@ -80,8 +80,9 @@ class Dreport extends \Zotlabs\Web\Controller {
return;
}
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
$r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'",
dbesc($channel['channel_hash']),
dbesc($channel['channel_portable_id']),
dbesc($mid)
);

View File

@ -75,6 +75,10 @@ class Group extends Controller {
);
if($r)
info( t('Privacy group updated.') . EOL );
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
call_hooks ('privacygroup_extras_post',$hookinfo);
build_sync_packet(local_channel(),null,true);
}
@ -127,6 +131,10 @@ class Group extends Controller {
$i++;
}
$hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ];
call_hooks ('privacygroup_extras',$hookinfo);
$pgrp_extras = $hookinfo['pgrp_extras'];
$tpl = get_markup_template('privacy_groups.tpl');
$o = replace_macros($tpl, [
'$title' => t('Privacy Groups'),
@ -136,6 +144,7 @@ class Group extends Controller {
// new group form
'$gname' => array('groupname',t('Privacy group name')),
'$public' => array('public',t('Members are visible to other channels'), false),
'$pgrp_extras' => $pgrp_extras,
'$form_security_token' => get_form_security_token("group_edit"),
'$submit' => t('Submit'),
@ -166,8 +175,11 @@ class Group extends Controller {
);
if($r)
$result = group_rmv(local_channel(),$r[0]['gname']);
if($result)
if($result) {
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(2) ];
call_hooks ('privacygroup_extras_drop',$hookinfo);
info( t('Privacy group removed.') . EOL);
}
else
notice( t('Unable to remove privacy group.') . EOL);
}

View File

@ -52,7 +52,7 @@ class Like extends \Zotlabs\Web\Controller {
$observer = \App::get_observer();
$interactive = $_REQUEST['interactive'];
if($interactive) {
if((! $observer) || ($interactive)) {
$o .= '<h1>' . t('Like/Dislike') . '</h1>';
$o .= EOL . EOL;
@ -251,6 +251,9 @@ class Like extends \Zotlabs\Web\Controller {
}
}
else {
if(! $observer)
killme();
// this is used to like an item or comment

View File

@ -138,8 +138,8 @@ class Linkinfo extends \Zotlabs\Web\Controller {
}
$image = "";
if(sizeof($siteinfo["images"]) > 0){
if(is_array($siteinfo["images"]) && count($siteinfo["images"])){
/* Execute below code only if image is present in siteinfo */
$total_images = 0;
@ -161,7 +161,7 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$total_images ++;
if($max_images && $max_images >= $total_images)
break;
}
}
}
if(strlen($text)) {

View File

@ -132,6 +132,13 @@ class Network extends \Zotlabs\Web\Controller {
$deftag = '';
if (feature_enabled(local_channel(),'affinity')) {
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
if ($affinity_locked) {
set_pconfig(local_channel(),'affinity','cmin',$cmin);
set_pconfig(local_channel(),'affinity','cmax',$cmax);
}
}
if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
$nouveau = true;

View File

@ -134,7 +134,7 @@ class New_channel extends \Zotlabs\Web\Controller {
$default_role = '';
$aid = get_account_id();
if($aid) {
$r = q("select count(channel_id) as total from channel where channel_account_id = %d",
$r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0",
intval($aid)
);
if($r && (! intval($r[0]['total']))) {

View File

@ -24,7 +24,7 @@ class Pconfig extends \Zotlabs\Web\Controller {
$aj = intval($_POST['aj']);
// Do not store "serialized" data received in the $_POST
if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('O:8:"stdClass":[0-9]+:{.*}$|s',$v)) {
if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('|O:8:"stdClass":[0-9]+:{.*}$|s',$v)) {
return;
}

View File

@ -32,7 +32,7 @@ class Photo extends \Zotlabs\Web\Controller {
}
$cache_mode = array(
'on' => get_config('system','photo_cache_enable', 0),
'on' => false,
'age' => 86400,
'exp' => true,
'leak' => false
@ -159,13 +159,15 @@ class Photo extends \Zotlabs\Web\Controller {
// Validate cache
$cache = array(
'resid' => $photo,
'uid' => $r[0]['uid'],
'status' => false
);
if($cache_mode['on'])
call_hooks('cache_url_hook', $cache);
if(! $cache['status']) {
header("Location: " . htmlspecialchars_decode($r[0]['display_path']));
$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();
}
}

View File

@ -988,7 +988,7 @@ class Photos extends \Zotlabs\Web\Controller {
$photo = array(
'href' => z_root() . '/photo/' . $hires['resource_id'] . '-' . $hires['imgscale'] . '.' . $phototypes[$hires['mimetype']],
'title'=> t('View Full Size'),
'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['imgscale'] . '.' . $phototypes[$lores['mimetype']] . '?f=&_u=' . datetime_convert('','','','ymdhis')
'src' => z_root() . '/photo/' . $lores['resource_id'] . '-' . $lores['imgscale'] . '.' . $phototypes[$lores['mimetype']]
);
if($nextlink)

View File

@ -17,8 +17,12 @@ class Featured {
$cmin = intval($_POST['affinity_cmin']);
if($cmin < 0 || $cmin > 99)
$cmin = 0;
$lock = ($_POST['affinity_lock']) ? intval($_POST['affinity_lock']) : 1;
set_pconfig(local_channel(),'affinity','cmin',$cmin);
set_pconfig(local_channel(),'affinity','cmax',$cmax);
set_pconfig(local_channel(),'affinity','lock',$lock);
info( t('Affinity Slider settings updated.') . EOL);
@ -49,6 +53,10 @@ class Featured {
$setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array(
'$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0'))
));
$lock = intval(get_pconfig(local_channel(),'affinity','lock',1));
$setting_fields .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
'$field' => array('affinity_lock', t('Always reset on new page visit.'), $lock, t('default: yes'), Array('No','Yes'))
));
$settings_addons .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array(
'$addon' => array('affinity_slider', '' . t('Affinity Slider Settings'), '', t('Submit')),

View File

@ -441,13 +441,18 @@ class Setup extends \Zotlabs\Web\Controller {
require_once 'include/environment.php';
$help = '';
$mem_warning = '';
$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>';
}
$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 .= '<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);

View File

@ -12,10 +12,16 @@ class Sslify extends \Zotlabs\Web\Controller {
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
$hdrs[strtolower($k)] = $v;
}
if (array_key_exists('content-type', $hdrs)) {
$type = $hdrs['content-type'];
header('Content-Type: ' . $type);
}
if (array_key_exists('content-type', $hdrs))
header('Content-Type: ' . $hdrs['content-type']);
if (array_key_exists('last-modified', $hdrs))
header('Last-Modified: ' . $hdrs['last-modified']);
if (array_key_exists('cache-control', $hdrs))
header('Cache-Control: ' . $hdrs['cache-control']);
if (array_key_exists('expires', $hdrs))
header('Expires: ' . $hdrs['expires']);
echo $x['body'];
killme();

View File

@ -442,8 +442,8 @@ class Wiki extends Controller {
$mimeType = $_POST['mimetype'];
if($mimeType === 'text/bbcode') {
$linkconverted = NativeWikiPage::convert_links($content,$wikiURL);
$html = zidify_links(smilies(bbcode($linkconverted)));
$html = zidify_links(smilies(bbcode($content)));
$html = NativeWikiPage::convert_links($html,$wikiURL);
}
elseif($mimeType === 'text/markdown') {
$linkconverted = NativeWikiPage::convert_links($content,$wikiURL);

12
Zotlabs/Update/_1230.php Normal file
View File

@ -0,0 +1,12 @@
<?php
namespace Zotlabs\Update;
class _1230 {
function run() {
q("update abook set abook_closeness = 80 where abook_closeness = 0 and abook_self = 0");
return UPDATE_SUCCESS;
}
}

View File

@ -15,9 +15,14 @@ class Affinity {
$cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $default_cmin);
$cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $default_cmax);
if(feature_enabled(local_channel(),'affinity')) {
$affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1));
if ($affinity_locked) {
set_pconfig(local_channel(),'affinity','cmin',$cmin);
set_pconfig(local_channel(),'affinity','cmax',$cmax);
}
$labels = array(
t('Me'),
t('Family'),
@ -53,4 +58,4 @@ class Affinity {
return '';
}
}

View File

@ -55,7 +55,7 @@ class Finger {
$r = q("select xchan.*, hubloc.* from xchan
left join hubloc on xchan_hash = hubloc_hash
where xchan_addr = '%s' and hubloc_primary = 1 and hubloc_deleted = 0 limit 1",
where xchan_addr = '%s' and hubloc_primary = 1 and hubloc_deleted = 0 and hubloc_network = 'zot' limit 1",
dbesc($xchan_addr)
);

View File

@ -53,7 +53,7 @@ define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'STD_VERSION', '3.9.5' );
define ( 'ZOT_REVISION', '6.0a' );
define ( 'DB_UPDATE_VERSION', 1229 );
define ( 'DB_UPDATE_VERSION', 1230 );
define ( 'PROJECT_BASE', __DIR__ );
@ -84,7 +84,8 @@ define ( 'DIRECTORY_FALLBACK_MASTER', 'https://zotadel.net');
$DIRECTORY_FALLBACK_SERVERS = array(
'https://hubzilla.zottel.net',
'https://zotadel.net'
'https://zotadel.net',
'https://zotsite.net'
);
@ -576,6 +577,8 @@ define ( 'ITEM_TYPE_BUG', 4 );
define ( 'ITEM_TYPE_DOC', 5 );
define ( 'ITEM_TYPE_CARD', 6 );
define ( 'ITEM_TYPE_ARTICLE', 7 );
//OSADA ITEM_TYPE_MAIL = 8
define ( 'ITEM_TYPE_CUSTOM', 9 );
define ( 'ITEM_IS_STICKY', 1000 );

340
composer.lock generated
View File

@ -63,16 +63,16 @@
},
{
"name": "bshaffer/oauth2-server-php",
"version": "v1.10.0",
"version": "v1.11.1",
"source": {
"type": "git",
"url": "https://github.com/bshaffer/oauth2-server-php.git",
"reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9"
"reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/d158878425392fe5a0cc34f15dbaf46315ae0ed9",
"reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9",
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/5a0c8000d4763b276919e2106f54eddda6bc50fa",
"reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa",
"shasum": ""
},
"require": {
@ -117,7 +117,7 @@
"oauth",
"oauth2"
],
"time": "2017-11-15T01:41:02+00:00"
"time": "2018-12-04T00:29:32+00:00"
},
{
"name": "commerceguys/intl",
@ -251,16 +251,16 @@
},
{
"name": "league/html-to-markdown",
"version": "4.8.0",
"version": "4.8.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d"
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d",
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"shasum": ""
},
"require": {
@ -311,7 +311,7 @@
"html",
"markdown"
],
"time": "2018-09-18T12:18:08+00:00"
"time": "2018-12-24T17:21:44+00:00"
},
{
"name": "lukasreschke/id3parser",
@ -1925,32 +1925,33 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"version": "1.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
"reference": "9f83dded91781a01c63574e387eaa769be769115"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
"reference": "9f83dded91781a01c63574e387eaa769be769115",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
"dev-master": "1.5-dev"
}
},
"autoload": {
@ -1980,13 +1981,14 @@
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
"time": "2018-12-04T20:46:45+00:00"
},
{
"name": "myclabs/deep-copy",
@ -2571,6 +2573,7 @@
"testing",
"xunit"
],
"abandoned": true,
"time": "2018-02-07T06:47:59+00:00"
},
{
@ -2827,16 +2830,16 @@
},
{
"name": "phpunit/phpunit",
"version": "7.4.4",
"version": "7.5.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd"
"reference": "c23d78776ad415d5506e0679723cb461d71f488f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
"reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c23d78776ad415d5506e0679723cb461d71f488f",
"reference": "c23d78776ad415d5506e0679723cb461d71f488f",
"shasum": ""
},
"require": {
@ -2857,7 +2860,7 @@
"phpunit/php-timer": "^2.0",
"sebastian/comparator": "^3.0",
"sebastian/diff": "^3.0",
"sebastian/environment": "^3.1 || ^4.0",
"sebastian/environment": "^4.0",
"sebastian/exporter": "^3.1",
"sebastian/global-state": "^2.0",
"sebastian/object-enumerator": "^3.0.3",
@ -2881,7 +2884,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "7.4-dev"
"dev-master": "7.5-dev"
}
},
"autoload": {
@ -2907,7 +2910,7 @@
"testing",
"xunit"
],
"time": "2018-11-14T16:52:02+00:00"
"time": "2018-12-12T07:20:32+00:00"
},
{
"name": "psr/container",
@ -3008,6 +3011,46 @@
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "~3.7.0",
"satooshi/php-coveralls": ">=1.0"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2016-02-11T07:05:27+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.1",
@ -3175,28 +3218,28 @@
},
{
"name": "sebastian/environment",
"version": "3.1.0",
"version": "4.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5"
"reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
"reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/febd209a219cea7b56ad799b30ebbea34b71eb8f",
"reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f",
"shasum": ""
},
"require": {
"php": "^7.0"
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.1"
"phpunit/phpunit": "^7.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1.x-dev"
"dev-master": "4.0-dev"
}
},
"autoload": {
@ -3221,7 +3264,7 @@
"environment",
"hhvm"
],
"time": "2017-07-01T08:51:00+00:00"
"time": "2018-11-25T09:31:21+00:00"
},
{
"name": "sebastian/exporter",
@ -3573,16 +3616,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "c55fe9257003b2d95c0211b3f6941e8dfd26dffd"
"reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/c55fe9257003b2d95c0211b3f6941e8dfd26dffd",
"reference": "c55fe9257003b2d95c0211b3f6941e8dfd26dffd",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/db7e59fec9c82d45e745eb500e6ede2d96f4a6e9",
"reference": "db7e59fec9c82d45e745eb500e6ede2d96f4a6e9",
"shasum": ""
},
"require": {
@ -3599,7 +3642,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3626,20 +3669,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T09:10:45+00:00"
"time": "2018-11-26T11:49:31+00:00"
},
{
"name": "symfony/class-loader",
"version": "v3.4.18",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/class-loader.git",
"reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1"
"reference": "420458095cf60025eb0841276717e0da7f75e50e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/class-loader/zipball/5605edec7b8f034ead2497ff4aab17bb70d558c1",
"reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1",
"url": "https://api.github.com/repos/symfony/class-loader/zipball/420458095cf60025eb0841276717e0da7f75e50e",
"reference": "420458095cf60025eb0841276717e0da7f75e50e",
"shasum": ""
},
"require": {
@ -3682,20 +3725,20 @@
],
"description": "Symfony ClassLoader Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:06:03+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "symfony/config",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238"
"reference": "005d9a083d03f588677d15391a716b1ac9b887c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"url": "https://api.github.com/repos/symfony/config/zipball/005d9a083d03f588677d15391a716b1ac9b887c0",
"reference": "005d9a083d03f588677d15391a716b1ac9b887c0",
"shasum": ""
},
"require": {
@ -3718,7 +3761,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3745,24 +3788,25 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:09:42+00:00"
"time": "2018-11-30T22:21:14+00:00"
},
{
"name": "symfony/console",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "432122af37d8cd52fba1b294b11976e0d20df595"
"reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595",
"reference": "432122af37d8cd52fba1b294b11976e0d20df595",
"url": "https://api.github.com/repos/symfony/console/zipball/4dff24e5d01e713818805c1862d2e3f901ee7dd0",
"reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/contracts": "^1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
@ -3786,7 +3830,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3813,20 +3857,88 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T09:30:44+00:00"
"time": "2018-11-27T07:40:44+00:00"
},
{
"name": "symfony/css-selector",
"version": "v3.4.18",
"name": "symfony/contracts",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb"
"url": "https://github.com/symfony/contracts.git",
"reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
"url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf",
"reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"require-dev": {
"psr/cache": "^1.0",
"psr/container": "^1.0"
},
"suggest": {
"psr/cache": "When using the Cache contracts",
"psr/container": "When using the Service contracts",
"symfony/cache-contracts-implementation": "",
"symfony/service-contracts-implementation": "",
"symfony/translation-contracts-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\": ""
},
"exclude-from-classmap": [
"**/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A set of abstractions extracted out of the Symfony components",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"time": "2018-12-05T08:06:11+00:00"
},
{
"name": "symfony/css-selector",
"version": "v3.4.20",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/345b9a48595d1ab9630db791dbc3e721bf0233e8",
"reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8",
"shasum": ""
},
"require": {
@ -3866,37 +3978,39 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:33:53+00:00"
"time": "2018-11-11T19:48:54+00:00"
},
{
"name": "symfony/dependency-injection",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483"
"reference": "e4adc57a48d3fa7f394edfffa9e954086d7740e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483",
"reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e4adc57a48d3fa7f394edfffa9e954086d7740e5",
"reference": "e4adc57a48d3fa7f394edfffa9e954086d7740e5",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"psr/container": "^1.0"
"psr/container": "^1.0",
"symfony/contracts": "^1.0"
},
"conflict": {
"symfony/config": "<4.1.1",
"symfony/config": "<4.2",
"symfony/finder": "<3.4",
"symfony/proxy-manager-bridge": "<3.4",
"symfony/yaml": "<3.4"
},
"provide": {
"psr/container-implementation": "1.0"
"psr/container-implementation": "1.0",
"symfony/service-contracts-implementation": "1.0"
},
"require-dev": {
"symfony/config": "~4.1",
"symfony/config": "~4.2",
"symfony/expression-language": "~3.4|~4.0",
"symfony/yaml": "~3.4|~4.0"
},
@ -3910,7 +4024,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3937,20 +4051,20 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
"time": "2018-10-31T10:54:16+00:00"
"time": "2018-12-02T15:59:36+00:00"
},
{
"name": "symfony/dom-crawler",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "80e60271bb288de2a2259662cff125cff4f93f95"
"reference": "7438a32108fdd555295f443605d6de2cce473159"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/80e60271bb288de2a2259662cff125cff4f93f95",
"reference": "80e60271bb288de2a2259662cff125cff4f93f95",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7438a32108fdd555295f443605d6de2cce473159",
"reference": "7438a32108fdd555295f443605d6de2cce473159",
"shasum": ""
},
"require": {
@ -3967,7 +4081,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -3994,24 +4108,25 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T12:40:59+00:00"
"time": "2018-11-26T10:55:26+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "552541dad078c85d9414b09c041ede488b456cd5"
"reference": "921f49c3158a276d27c0d770a5a347a3b718b328"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5",
"reference": "552541dad078c85d9414b09c041ede488b456cd5",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328",
"reference": "921f49c3158a276d27c0d770a5a347a3b718b328",
"shasum": ""
},
"require": {
"php": "^7.1.3"
"php": "^7.1.3",
"symfony/contracts": "^1.0"
},
"conflict": {
"symfony/dependency-injection": "<3.4"
@ -4030,7 +4145,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -4057,20 +4172,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2018-10-10T13:52:42+00:00"
"time": "2018-12-01T08:52:38+00:00"
},
{
"name": "symfony/filesystem",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981"
"reference": "2f4c8b999b3b7cadb2a69390b01af70886753710"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2f4c8b999b3b7cadb2a69390b01af70886753710",
"reference": "2f4c8b999b3b7cadb2a69390b01af70886753710",
"shasum": ""
},
"require": {
@ -4080,7 +4195,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -4107,7 +4222,7 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-10-30T13:18:25+00:00"
"time": "2018-11-11T19:52:12+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@ -4170,20 +4285,21 @@
},
{
"name": "symfony/translation",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c"
"reference": "c0e2191e9bed845946ab3d99767513b56ca7dcd6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
"url": "https://api.github.com/repos/symfony/translation/zipball/c0e2191e9bed845946ab3d99767513b56ca7dcd6",
"reference": "c0e2191e9bed845946ab3d99767513b56ca7dcd6",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/contracts": "^1.0.2",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
@ -4191,6 +4307,9 @@
"symfony/dependency-injection": "<3.4",
"symfony/yaml": "<3.4"
},
"provide": {
"symfony/translation-contracts-implementation": "1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
@ -4208,7 +4327,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -4235,20 +4354,20 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2018-10-28T18:38:52+00:00"
"time": "2018-12-06T10:45:32+00:00"
},
{
"name": "symfony/yaml",
"version": "v4.1.7",
"version": "v4.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9"
"reference": "c41175c801e3edfda90f32e292619d10c27103d7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9",
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9",
"url": "https://api.github.com/repos/symfony/yaml/zipball/c41175c801e3edfda90f32e292619d10c27103d7",
"reference": "c41175c801e3edfda90f32e292619d10c27103d7",
"shasum": ""
},
"require": {
@ -4267,7 +4386,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.1-dev"
"dev-master": "4.2-dev"
}
},
"autoload": {
@ -4294,7 +4413,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-10-02T16:36:10+00:00"
"time": "2018-11-11T19:52:12+00:00"
},
{
"name": "theseer/tokenizer",
@ -4338,20 +4457,21 @@
},
{
"name": "webmozart/assert",
"version": "1.3.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a"
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
"reference": "0df1908962e7a3071564e857d86874dad1ef204a",
"url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0"
"php": "^5.3.3 || ^7.0",
"symfony/polyfill-ctype": "^1.8"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
@ -4384,7 +4504,7 @@
"check",
"validate"
],
"time": "2018-01-29T19:49:41+00:00"
"time": "2018-12-25T11:19:39+00:00"
}
],
"aliases": [],

View File

@ -0,0 +1,42 @@
[h2]collect_public_recipients[/h2]
Replace the default list of public recipients (i.e., all contacts).
Allow plugins to create a list of recipients for public messages instead of the default
of all channel connections.
Called with the following array:
[
'recipients' => [],
'item' => $item,
'private_envelope' => $private_envelope,
'include_groups' => $include_groups
];
[code]
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
$hookinfo = [
'recipients' => [],
'item' => $item,
'private_envelope' => $private_envelope,
'include_groups' => $include_groups
];
call_hooks('collect_public_recipients',$hookinfo);
if ($hookinfo['recipients']) {
$r = $hookinfo['recipients'];
} else {
$r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ",
intval($item['uid'])
);
}
if($r) {
. . .
[/code]
see: include/item.php

View File

@ -0,0 +1,5 @@
[h2]daemon_master_release[/h2]
Permit filtering or alternate methods of processing of background processes when [code] \Zotlabs\Daemon\Master::Release() [/code] is called.
Default behavior is for a new PHP process to fire immediately upon a call to Master::Summon(). This hook permits pre-emption and the ability to provide queuing or other alternatives to this procedure.

24
doc/hook/item_custom.bb Normal file
View File

@ -0,0 +1,24 @@
[h2]item_custom[/h2]
Allow addons to create and process custom item types.
Addon authors will need to use iconfig meta data (with sharing on) or some other method
to specify and determine whether the custom item is destined for their addon.
It is fed an array of ['item' => ${item_array}, 'allow_exec' => {true/false}]
By default $arr['item']['cancel'] is set to TRUE which will abort storage of the
custom item in the item table unless the addon unsets it or sets it to false.
[code]
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
/* Custom items are not stored by default
because they require an addon to process. */
$d['item']['cancel']=true;
call_hooks('item_custom',$d);
}
[/code]
see: include/items.php

18
doc/hook/item_stored.bb Normal file
View File

@ -0,0 +1,18 @@
[h2]item_stored[/h2]
Allow addons to continue processing after an item has been stored in the event
that they need access to the item_id or other data that gets assigned during
the storage process.
It is fed an array of type item (including terms and iconfig data).
[code]
/**
* @hooks item_stored
* Called after new item is stored in the database.
* (By this time we have an item_id and other frequently needed info.)
*/
call_hooks('item_stored',$arr);
[/code]
see: include/items.php

View File

@ -0,0 +1,15 @@
[h2]item_stored_update[/h2]
Allow addons to continue processing after an item update has been stored
It is fed an array of type item (including terms and iconfig data).
[code]
/**
* @hooks item_stored_update
* Called after updated item is stored in the database.
*/
call_hooks('item_stored_update',$arr);
[/code]
see: include/items.php

View File

@ -0,0 +1,12 @@
[h2]privacygroup_extras[/h2]
Add items to the Privacy Group edit form
[code]
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(1) ];
call_hooks ('privacygroup_extras',$hookinfo);
$pgrp_extras = $hookinfo['pgrp_extras'];
[/code]
see: Zotlabs/Module/Group.php
see: view/tpl/privacy_groups.tpl

View File

@ -0,0 +1,11 @@
[h2]privacygroup_extras_drop[/h2]
Called after privacy group is dropped
[code]
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$argv(2) ];
call_hooks ('privacygroup_extras_drop',$hookinfo);
[/code]
see: Zotlabs/Module/Group.php
see: view/tpl/privacy_groups.tpl

View File

@ -0,0 +1,11 @@
[h2]privacygroup_extras_post[/h2]
Called as privacy group edit form is edited.
[code]
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
call_hooks ('privacygroup_extras_post',$hookinfo);
[/code]
see: Zotlabs/Module/Group.php
see: view/tpl/privacy_groups.tpl

View File

@ -136,6 +136,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/check_siteallowed]check_siteallowed[/zrl]
Used to over-ride or bypass the site black/white block lists
[zrl=[baseurl]/help/hook/collect_public_recipients]collect_public_recipients[/zrl]
Used to establish a list of recipients to send a public message to.
[zrl=[baseurl]/help/hook/comment_buttons]comment_buttons[/zrl]
Called when rendering the edit buttons for comments
@ -190,6 +193,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/daemon_addon]daemon_addon[/zrl]
Called when invoking the extensible background daemon
[zrl=[baseurl]/help/hook/daemon_master_release]daemon_master_release[/zrl]
Called at the start of processing \Zotlabs\Daemon\Master::Release()
[zrl=[baseurl]/help/hook/directory_item]directory_item[/zrl]
Called when generating a directory listing for display
@ -343,9 +349,18 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/item_store]item_store[/zrl]
Called when item_store() stores a record of type item
[zrl=[baseurl]/help/hook/item_stored]item_stored[/zrl]
Called after item_store() has stored a record of type item in the database.
[zrl=[baseurl]/help/hook/item_custom]item_custom[/zrl]
Called before item_store() stores a record of type item (allowing addons to process ITEM_TYPE_CUSTOM items).
[zrl=[baseurl]/help/hook/item_store_update]item_store_update[/zrl]
Called when item_store_update() is called to update a stored item.
[zrl=[baseurl]/help/hook/item_stored_update]item_stored_update[/zrl]
Called after item_store_update() has updated a stored item.
[zrl=[baseurl]/help/hook/item_translate]item_translate[/zrl]
Called from item_store and item_store_update after the post language has been autodetected
@ -544,6 +559,15 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/prepare_body_init]prepare_body_init[/zrl]
Called before generating the HTML for a displayed conversation item
[zrl=[baseurl]/help/hook/privacygroup_extras]privacygroup_extras[/zrl]
Called before generating the HTML for the Privacy Group edit options
[zrl=[baseurl]/help/hook/privacygroup_extras_delete]privacygroup_extras_delete[/zrl]
Called after privacy group is dropped.
[zrl=[baseurl]/help/hook/privacygroup_extras_post]privacygroup_extras_post[/zrl]
Called when privacy group edit form is submitted.
[zrl=[baseurl]/help/hook/proc_run]proc_run[/zrl]
Called when invoking PHP sub processes

View File

@ -326,22 +326,11 @@ function bb_ShareAttributes($match) {
$auth = is_matrix_url($profile);
}
// message_id is never used, do we still need it?
$message_id = "";
preg_match("/message_id='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$message_id = $matches[1];
if(! $message_id) {
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$message_id = $matches[1];
}
$rnd = mt_rand();
$reldate = '<span class="autotime" title="' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'c') . '" >' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'r') . '</span>';
$headline = '<div class="shared_container"> <div class="shared_header">';
$headline = '<div id="shared_container_' . $rnd . '" class="shared_container"> <div id="shared_header_' . $rnd . '" class="shared_header">';
if ($avatar != "")
$headline .= '<a href="' . (($auth) ? zid($profile) : $profile) . '" ><img src="' . $avatar . '" alt="' . $author . '" height="32" width="32" /></a>';
@ -363,7 +352,7 @@ function bb_ShareAttributes($match) {
$headline .= '<span>' . $fmt . '</span></div>';
$text = $headline . '<div class="reshared-content">' . trim($match[2]) . '</div></div>';
$text = $headline . '<div id="reshared-content-' . $rnd . '" class="reshared-content">' . trim($match[2]) . '</div></div>';
return $text;
}
@ -1021,7 +1010,7 @@ function bbcode($Text, $options = []) {
}
// Check for colored text
if (strpos($Text,'[/hl]') !== false) {
$Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "<span style=\"background-color: yellow;\">$1</span>", $Text);
$Text = preg_replace("(\[hl\](.*?)\[\/hl\])ism", "<span class=\"default-highlight\">$1</span>", $Text);
$Text = preg_replace("(\[hl=(.*?)\](.*?)\[\/hl\])ism", "<span style=\"background-color: $1;\">$2</span>", $Text);
}

View File

@ -190,7 +190,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
return $result;
}
$allowed = (($is_zot || $r[0]['xchan_network'] === 'rss') ? 1 : 0);
$allowed = (($is_zot || in_array($r[0]['xchan_network'],['rss','zot6'])) ? 1 : 0);
$x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => $allowed, 'singleton' => 0);
@ -266,9 +266,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
}
}
else {
$closeness = get_pconfig($uid,'system','new_abook_closeness');
if($closeness === false)
$closeness = 80;
$closeness = get_pconfig($uid,'system','new_abook_closeness',80);
$r = abook_store_lowlevel(
[

View File

@ -12,12 +12,12 @@ use \Michelf\MarkdownExtra;
function get_help_fullpath($path,$suffix=null) {
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
// Determine the language and modify the path accordingly
$x = determine_help_language();
$lang = $x['language'];
$url_idx = ($x['from_url'] ? 1 : 0);
// The English translation is at the root of /doc/. Other languages are in
// subfolders named by the language code such as "de", "es", etc.
if($lang !== 'en') {
@ -53,15 +53,14 @@ function get_help_fullpath($path,$suffix=null) {
* @return string|unknown
*/
function get_help_content($tocpath = false) {
global $lang;
$doctype = 'markdown';
$text = '';
$path = (($tocpath !== false) ? $tocpath : '');
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
if($tocpath === false && argc() > 1) {
$path = '';
@ -74,7 +73,7 @@ function get_help_content($tocpath = false) {
if($path) {
$fullpath = get_help_fullpath($path);
$fullpath = get_help_fullpath($path);
$title = basename($path);
if(! $tocpath)
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
@ -88,10 +87,10 @@ function get_help_content($tocpath = false) {
load_doc_file($fullpath . '.md') === '' &&
load_doc_file($fullpath . '.bb') === '' &&
load_doc_file($fullpath . '.html') === ''
) {
) {
$path = $title;
}
$fullpath = get_help_fullpath($path);
$fullpath = get_help_fullpath($path);
$text = load_doc_file($fullpath . '.md');
if(! $text) {
@ -111,15 +110,15 @@ function get_help_content($tocpath = false) {
if($tocpath === false) {
if(! $text) {
$path = 'Site';
$fullpath = get_help_fullpath($path,'.md');
$path = 'Site';
$fullpath = get_help_fullpath($path,'.md');
$text = load_doc_file($fullpath . '.md');
\App::$page['title'] = t('Help');
}
if(! $text) {
$doctype = 'bbcode';
$path = 'main';
$fullpath = get_help_fullpath($path,'.md');
$path = 'main';
$fullpath = get_help_fullpath($path,'.md');
$text = load_doc_file($fullpath . '.bb');
goaway('/help/about/about');
\App::$page['title'] = t('Help');
@ -219,7 +218,6 @@ function find_doc_file($s) {
*/
function search_doc_files($s) {
\App::set_pager_itemspage(60);
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
@ -351,7 +349,7 @@ function store_doc_file($s) {
$x = item_store_update($item);
}
else {
$item['uuid'] = $item_message_id();
$item['uuid'] = item_message_id();
$item['mid'] = $item['parent_mid'] = z_root() . '/item/' . $item['uuid'];
$x = item_store($item);
}

View File

@ -1035,8 +1035,9 @@ function import_mail($channel, $mails, $sync = false) {
if(! $m)
continue;
$m['aid'] = $channel['channel_account_id'];
$m['uid'] = $channel['channel_id'];
$m['account_id'] = $channel['channel_account_id'];
$m['channel_id'] = $channel['channel_id'];
$mail_id = mail_store($m);
if($sync && $mail_id) {
Zotlabs\Daemon\Master::Summon(array('Notifier','single_mail',$mail_id));

View File

@ -95,9 +95,24 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
//$sys = get_sys_channel();
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
$r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ",
$hookinfo = [
'recipients' => [],
'item' => $item,
'private_envelope' => $private_envelope,
'include_groups' => $include_groups
];
call_hooks('collect_public_recipients',$hookinfo);
if ($hookinfo['recipients']) {
$r = $hookinfo['recipients'];
} else {
$r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ",
intval($item['uid'])
);
);
}
if($r) {
// filter out restrictive public_policy settings from remote networks
@ -1591,6 +1606,14 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
'item' => $arr,
'allow_exec' => $allow_exec
];
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
/* Custom items are not stored by default
because they require an addon to process. */
$d['item']['cancel']=true;
call_hooks('item_custom',$d);
}
/**
* @hooks item_store
* Called when item_store() stores a record of type item.
@ -2016,6 +2039,13 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
*/
call_hooks('post_remote_end', $arr);
/**
* @hooks item_stored
* Called after new item is stored in the database.
* (By this time we have an item_id and other frequently needed info.)
*/
call_hooks('item_stored',$arr);
item_update_parent_commented($arr);
// If _creating_ a deleted item, don't propagate it further or send out notifications.
@ -2049,6 +2079,15 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
'item' => $arr,
'allow_exec' => $allow_exec
];
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
/* Custom items are not stored by default
because they require an addon to process. */
$d['item']['cancel']=true;
call_hooks('item_custom_update',$d);
}
/**
* @hooks item_store_update
* Called when item_store_update() is called to update a stored item. It
@ -2339,6 +2378,12 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
*/
call_hooks('post_remote_update_end', $arr);
/**
* @hooks item_stored_update
* Called after updated item is stored in the database.
*/
call_hooks('item_stored_update',$arr);
if($deliver) {
send_status_notifications($orig_post_id,$arr);
tag_deliver($uid,$orig_post_id);

View File

@ -91,8 +91,6 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
// remove duplicate adjacent code tags
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s);
// Don't show link to full picture (until it is fixed)
$s = scale_external_images($s, false);
/**
* @hooks markdown_to_bb

View File

@ -222,6 +222,9 @@ function nav($template = 'default') {
if(! $settings_url && isset(App::$nav_sel['settings_url']))
$settings_url = App::$nav_sel['settings_url'];
$pinned_list = [];
$syslist = [];
//app bin
if($is_owner) {
if(get_pconfig(local_channel(), 'system','import_system_apps') !== datetime_convert('UTC','UTC','now','Y-m-d')) {
@ -234,14 +237,29 @@ function nav($template = 'default') {
set_pconfig(local_channel(), 'system','force_import_system_apps', STD_VERSION);
}
$syslist = array();
$list = Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
$list = Apps::app_list(local_channel(), false, [ 'nav_pinned_app' ]);
if($list) {
foreach($list as $li) {
$pinned_list[] = Apps::app_encode($li);
}
}
Apps::translate_system_apps($pinned_list);
usort($pinned_list,'Zotlabs\\Lib\\Apps::app_name_compare');
$pinned_list = Apps::app_order(local_channel(),$pinned_list, 'nav_pinned_app');
$syslist = [];
$list = Apps::app_list(local_channel(), false, [ 'nav_featured_app' ]);
if($list) {
foreach($list as $li) {
$syslist[] = Apps::app_encode($li);
}
}
Apps::translate_system_apps($syslist);
}
else {
$syslist = Apps::get_system_apps(true);
@ -249,26 +267,38 @@ function nav($template = 'default') {
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
$syslist = Apps::app_order(local_channel(),$syslist);
$syslist = Apps::app_order(local_channel(),$syslist, 'nav_featured_app');
foreach($syslist as $app) {
if(\App::$nav_sel['name'] == $app['name'])
$app['active'] = true;
if($is_owner) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
if($pinned_list) {
foreach($pinned_list as $app) {
if(\App::$nav_sel['name'] == $app['name'])
$app['active'] = true;
if($is_owner) {
$navbar_apps[] = Apps::app_render($app,'navbar');
}
else {
$nav_apps[] = Apps::app_render($app,'nav');
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
$navbar_apps[] = Apps::app_render($app,'navbar');
}
}
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
$navbar_apps[] = Apps::app_render($app,'navbar');
}
if($syslist) {
foreach($syslist as $app) {
if(\App::$nav_sel['name'] == $app['name'])
$app['active'] = true;
if($is_owner) {
if(strpos($app['categories'],'nav_pinned_app') === false) {
$nav_apps[] = Apps::app_render($app,'nav');
}
}
else {
$nav_apps[] = Apps::app_render($app,'nav');
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
if(strpos($app['categories'],'nav_pinned_app') === false) {
$nav_apps[] = Apps::app_render($app,'nav');
}
}
}
}

View File

@ -120,6 +120,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
if(array_key_exists('http_version',$opts))
@curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']);
if(x($opts,'cookiejar'))
@curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
if(x($opts,'cookiefile'))
@ -157,7 +160,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) {
while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) {
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
$header .= $chunk;
$base = substr($base,strlen($chunk));
@ -290,6 +293,9 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
if(array_key_exists('http_version',$opts))
@curl_setopt($ch,CURLOPT_HTTP_VERSION,$opts['http_version']);
if(x($opts,'cookiejar'))
@curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
if(x($opts,'cookiefile'))
@ -323,7 +329,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) {
while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) {
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
$header .= $chunk;
$base = substr($base,strlen($chunk));
@ -694,99 +700,6 @@ function sxml2array ( $xmlObject, $out = array () )
}
/**
* @brief Scales an external image.
*
* @param string $s
* @param string $include_link default true
* @param string $scale_replace default false
* @return string
*/
function scale_external_images($s, $include_link = true, $scale_replace = false) {
// Picture addresses can contain special characters
$s = htmlspecialchars_decode($s, ENT_COMPAT);
$matches = null;
$c = preg_match_all('/\[([zi])mg(.*?)\](.*?)\[\/[zi]mg\]/ism', $s, $matches, PREG_SET_ORDER);
if($c) {
require_once('include/photo/photo_driver.php');
foreach($matches as $mtch) {
logger('data: ' . $mtch[2] . ' ' . $mtch[3]);
if(substr($mtch[2],0,1) == '=') {
$owidth = intval(substr($mtch[2],1));
if($owidth > 0 && $owidth < 1024)
continue;
}
$hostname = str_replace('www.','',substr(z_root(),strpos(z_root(),'://')+3));
if(stristr($mtch[3],$hostname))
continue;
// $scale_replace, if passed, is an array of two elements. The
// first is the name of the full-size image. The second is the
// name of a remote, scaled-down version of the full size image.
// This allows Friendica to display the smaller remote image if
// one exists, while still linking to the full-size image
if($scale_replace)
$scaled = str_replace($scale_replace[0], $scale_replace[1], $mtch[3]);
else
$scaled = $mtch[3];
if(! strpbrk(substr($scaled, 0, 1), 'zhfmt'))
continue;
$i = z_fetch_url($scaled, true);
$cache = get_config('system', 'itemcache');
if (($cache != '') and is_dir($cache)) {
$cachefile = $cache . '/' . hash('md5', $scaled);
file_put_contents($cachefile, $i['body']);
}
// guess mimetype from headers or filename
$type = guess_image_type($mtch[3], $i['header']);
if(strpos($type, 'image') === false)
continue;
if($i['success']) {
$ph = photo_factory($i['body'], $type);
if(! is_object($ph))
continue;
if($ph->is_valid()) {
$orig_width = $ph->getWidth();
$orig_height = $ph->getHeight();
if($orig_width > 1024 || $orig_height > 1024) {
$tag = (($match[1] == 'z') ? 'zmg' : 'img');
$linktag = (($match[1] == 'z') ? 'zrl' : 'url');
$ph->scaleImage(1024);
$new_width = $ph->getWidth();
$new_height = $ph->getHeight();
logger('data: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], LOGGER_DEBUG);
$s = str_replace($mtch[0],'[' . $tag . '=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/' . $tag . ']'
. "\n" . (($include_link)
? '[' . $linktag . '=' . $mtch[3] . ']' . t('view full size') . '[/' . $linktag . ']' . "\n"
: ''),$s);
logger('new string: ' . $s, LOGGER_DEBUG);
}
}
}
}
}
// replace the special char encoding
$s = htmlspecialchars($s, ENT_COMPAT, 'UTF-8');
return $s;
}
/**
* @brief xml2array() will convert the given XML text to an array in the XML structure.
*

View File

@ -482,7 +482,6 @@ function guess_image_type($filename, $headers = '') {
// logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG);
$type = null;
if ($headers) {
$hdrs=array();
$h = explode("\n",$headers);
foreach ($h as $l) {
@ -490,11 +489,16 @@ function guess_image_type($filename, $headers = '') {
$hdrs[strtolower($k)] = $v;
}
logger('Curl headers: '.var_export($hdrs, true), LOGGER_DEBUG);
if (array_key_exists('content-type', $hdrs))
$type = $hdrs['content-type'];
}
if (is_null($type)){
if (array_key_exists('content-type', $hdrs)) {
$ph = photo_factory('');
$types = $ph->supportedTypes();
if(array_key_exists($hdrs['content-type'], $types))
$type = $hdrs['content-type'];
}
}
if (is_null($type)){
$ignore_imagick = get_config('system', 'ignore_imagick');
// Guessing from extension? Isn't that... dangerous?
if(class_exists('Imagick') && file_exists($filename) && is_readable($filename) && !$ignore_imagick) {
@ -638,7 +642,6 @@ function import_xchan_photo($photo,$xchan,$thing = false,$force = false) {
$img_str = $result['body'];
$type = guess_image_type($photo, $result['header']);
$modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time()));
if(is_null($type))
$photo_failure = true;
}

View File

@ -213,8 +213,8 @@ function reload_plugins() {
try {
$func();
} catch (Exception $e) {
handleerrors_plugin($plugin,"","UNLOAD FAILED (uninstalling) : ".$e->getMessage(),true);
continue;
handleerrors_plugin($pl, '', 'UNLOAD FAILED (uninstalling) : ' . $e->getMessage(),true);
continue;
}
}
if(function_exists($pl . '_load')) {
@ -222,8 +222,8 @@ function reload_plugins() {
try {
$func();
} catch (Exception $e) {
handleerrors_plugin($plugin,"","LOAD FAILED (uninstalling): ".$e->getMessage(),true);
continue;
handleerrors_plugin($pl, '', 'LOAD FAILED (uninstalling): ' . $e->getMessage(),true);
continue;
}
}
q("UPDATE addon SET tstamp = %d WHERE id = %d",
@ -305,7 +305,7 @@ function plugins_sync() {
* @return array
*/
function visible_plugin_list() {
$r = q("select * from addon where hidden = 0 order by aname asc");
$x = (($r) ? ids_to_array($r,'aname') : array());
$y = [];
@ -315,7 +315,7 @@ function visible_plugin_list() {
$y[] = $xv;
}
}
}
}
return $y;
}
@ -456,21 +456,21 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) {
function call_hooks($name, &$data = null) {
$a = 0;
if (isset(App::$hooks[$name])) {
if (isset(App::$hooks[$name])) {
foreach(App::$hooks[$name] as $hook) {
if ($name != 'permit_hook') { // avoid looping
$checkhook = [
'name'=>$name,
'hook'=>$hook,
'data'=>$data,
'name'=>$name,
'hook'=>$hook,
'data'=>$data,
// Note: Since PHP uses COPY-ON-WRITE
// for variables, there is no cost to
// for variables, there is no cost to
// passing the $data structure (unless
// the permit_hook processors change the
// information it contains.
'permit'=>true
];
'permit'=>true
];
call_hooks('permit_hook',$checkhook);
if (!$checkhook['permit']) {
continue;
@ -618,7 +618,7 @@ function get_widget_info($widget){
}
}
if(! ($widget_found && $f))
if(! ($widget_found && $f))
return $info;
$f = escape_tags($f);
@ -736,8 +736,8 @@ function get_theme_info($theme){
'description' => '',
'author' => array(),
'version' => '',
'minversion' => '',
'maxversion' => '',
'minversion' => STD_VERSION,
'maxversion' => STD_VERSION,
'compat' => '',
'credits' => '',
'maintainer' => array(),
@ -1041,7 +1041,7 @@ function get_intltext_template($s, $root = '') {
if (isset(\App::$override_intltext_templates[$testroot][$s]["content"])) {
return \App::$override_intltext_templates[$testroot][$s]["content"];
} else {
if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) &&
if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) &&
isset(\App::$override_intltext_templates[$testroot][$s]["file"])) {
$s = \App::$override_intltext_templates[$testroot][$s]["file"];
$root = \App::$override_intltext_templates[$testroot][$s]["root"];
@ -1058,30 +1058,30 @@ function get_intltext_template($s, $root = '') {
}
function get_markup_template($s, $root = '') {
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
$t = App::template_engine();
$t = App::template_engine();
if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) {
return \App::$override_markup_templates[$testroot][$s]["content"];
} else {
if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) &&
isset(\App::$override_markup_templates[$testroot][$s]["file"])) {
$root = \App::$override_markup_templates[$testroot][$s]["root"];
$s = \App::$override_markup_templates[$testroot][$s]["file"];
$template = $t->get_markup_template($s, $root);
} elseif (\App::$override_templateroot) {
$newroot = \App::$override_templateroot;
if ($newroot != '' && substr($newroot,-1) != '/' ) {
$newroot .= '/';
}
$newroot .= $root;
$template = $t->get_markup_template($s, $newroot);
} else {
$template = $t->get_markup_template($s, $root);
if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) {
return \App::$override_markup_templates[$testroot][$s]["content"];
} else {
if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) &&
isset(\App::$override_markup_templates[$testroot][$s]["file"])) {
$root = \App::$override_markup_templates[$testroot][$s]["root"];
$s = \App::$override_markup_templates[$testroot][$s]["file"];
$template = $t->get_markup_template($s, $root);
} elseif (\App::$override_templateroot) {
$newroot = \App::$override_templateroot;
if ($newroot != '' && substr($newroot,-1) != '/' ) {
$newroot .= '/';
}
$newroot .= $root;
$template = $t->get_markup_template($s, $newroot);
} else {
$template = $t->get_markup_template($s, $root);
}
return $template;
}
return $template;
}
}
/**

View File

@ -13,7 +13,7 @@ function update_queue_item($id, $add_priority = 0) {
return;
$y = q("select min(outq_created) as earliest from outq where outq_posturl = '%s'",
$y = q("select outq_created as earliest from outq where outq_posturl = '%s' order by earliest limit 1",
dbesc($x[0]['outq_posturl'])
);
@ -311,4 +311,4 @@ function queue_deliver($outq, $immediate = false) {
return;
}
}
}

View File

@ -1691,7 +1691,14 @@ function prepare_body(&$item,$attach = false,$opts = false) {
if(local_channel() == $item['uid'])
$filer = format_filer($item);
$s = sslify($s);
if($s)
$s = sslify($s);
if($photo)
$photo = sslify($photo);
if($event)
$event = sslify($event);
$prep_arr = array(
'item' => $item,
@ -3305,8 +3312,6 @@ function cleanup_bbcode($body) {
$body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
$body = scale_external_images($body, false);
return $body;
}

View File

@ -70,9 +70,9 @@ function zid($s, $address = '') {
$zurl .= '#' . $fragment;
$arr = [
'url' => $s,
'zid' => urlencode($myaddr),
'result' => $zurl
'url' => $s,
'zid' => urlencode($myaddr),
'result' => $zurl
];
/**
* @hooks zid

View File

@ -1100,6 +1100,8 @@ function zot_process_response($hub, $arr, $outq) {
return;
}
$dreport = true;
$x = json_decode($arr['body'], true);
if(! $x) {
@ -1116,31 +1118,44 @@ function zot_process_response($hub, $arr, $outq) {
}
if(! (is_array($x['delivery_report']) && count($x['delivery_report']))) {
logger('encrypted delivery report could not be decrypted');
return;
$dreport = false;
}
}
foreach($x['delivery_report'] as $xx) {
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc($xx['name']),
dbesc($xx['status']),
dbesc(datetime_convert('UTC','UTC',$xx['date'])),
dbesc($xx['sender'])
);
if($dreport) {
foreach($x['delivery_report'] as $xx) {
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
// legacy zot recipients add a space and their name to the xchan. split those if true.
$legacy_recipient = strpos($xx['recipient'], ' ');
if($legacy_recipient !== false) {
$legacy_recipient_parts = explode(' ', $xx['recipient'], 2);
$xx['recipient'] = $legacy_recipient_parts[0];
$xx['name'] = $legacy_recipient_parts[1];
}
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc($xx['name']),
dbesc($xx['status']),
dbesc(datetime_convert('UTC','UTC',$xx['date'])),
dbesc($xx['sender'])
);
}
}
}
}
// we have a more descriptive delivery report, so discard the per hub 'queued' report.
q("delete from dreport where dreport_queue = '%s' ",
dbesc($outq['outq_hash'])
);
if($dreport) {
// we have a more descriptive delivery report, so discard the per hub 'queued' report.
q("delete from dreport where dreport_queue = '%s' ",
dbesc($outq['outq_hash'])
);
}
// update the timestamp for this site
@ -1232,6 +1247,7 @@ function zot_fetch($arr) {
$datatosend = json_encode(crypto_encapsulate(json_encode($data),$hub['hubloc_sitekey'], $algorithm));
$import = zot_zot($url,$datatosend);
}
else {
$algorithm = zot_best_algorithm($hub['site_crypto']);
@ -4913,6 +4929,7 @@ function zot_reply_pickup($data) {
dbesc($data['secret']),
dbesc($data['callback'])
);
if(! $r) {
$ret['message'] = 'nothing to pick up';
logger('mod_zot: pickup: ' . $ret['message']);
@ -4922,12 +4939,13 @@ function zot_reply_pickup($data) {
/*
* Everything is good if we made it here, so find all messages that are going to this location
* and send them all.
* and send them all - or a reasonable number if there are a lot so we don't overflow memory.
*/
$r = q("select * from outq where outq_posturl = '%s'",
$r = q("select * from outq where outq_posturl = '%s' limit 100",
dbesc($data['callback'])
);
if($r) {
logger('mod_zot: successful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG);
@ -4953,6 +4971,19 @@ function zot_reply_pickup($data) {
}
}
// It's possible that we have more than 100 messages waiting to be sent.
// See if there are any more messages in the queue.
$x = q("select * from outq where outq_posturl = '%s' order by outq_created limit 1",
dbesc($data['callback'])
);
// If so, kick off a new delivery notification for the next batch
if ($x) {
logger("Send additional pickup request.", LOGGER_DEBUG);
queue_deliver($x[0],true);
}
// this is a bit of a hack because we don't have the hubloc_url here, only the callback url.
// worst case is we'll end up using aes256cbc if they've got a different post endpoint
@ -4964,6 +4995,8 @@ function zot_reply_pickup($data) {
$encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm);
json_return_and_die($encrypted);
// @FIXME: There is a possibility that the transmission will get interrupted
// and fail - in which case this packet of messages will be lost.
/* pickup: end */
}

View File

@ -1,24 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.0/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.5/phpunit.xsd"
bootstrap="../boot.php"
forceCoversAnnotation="false"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<testsuite name="Hubzilla default Test Suite">
<directory suffix="Test.php">./unit/</directory>
</testsuite>
<testsuite name="API Test Suite">
<directory suffix="Test.php" prefix="API">./unit/</directory>
</testsuite>
<testsuites>
<testsuite name="Hubzilla default Test Suite">
<directory suffix="Test.php">./unit/</directory>
</testsuite>
<testsuite name="API Test Suite">
<directory suffix="Test.php" prefix="API">./unit/</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>mysql</group>
</exclude>
</groups>
<!--cover reporting-->
<!--coverage reporting-->
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">../Zotlabs/</directory>
@ -26,21 +28,22 @@
</whitelist>
</filter>
<logging>
<log type="junit" target="./results/junit.xml" logIncompleteSkipped="false"/>
<log type="coverage-clover" target="./results/coverage-clover.xml"/>
<log type="junit" target="./results/junit.xml"/>
<!--<log type="coverage-clover" target="./results/coverage-clover.xml"/>-->
<log type="coverage-html" target="./results/coverage-report/" lowUpperBound="35"
highLowerBound="70"/>
<log type="testdox-text" target="./results/testdox.txt"/>
<!--<log type="testdox-text" target="./results/testdox.txt"/>-->
<log type="testdox-html" target="./results/testdox.html"/>
</logging>
<php>
<!-- Default test database config, only used if no environment variables
with same names are set.
!!! Never run against a real database, it will truncate all tables -->
<env name="hz_db_server" value="127.0.0.1"/>
<env name="hz_db_server" value="postgres"/>
<env name="hz_db_scheme" value="pgsql"/>
<env name="hz_db_port" value="5432"/>
<env name="hz_db_user" value="travis_hz"/>
<env name="hz_db_pass" value="hubzilla"/>
<env name="hz_db_database" value="travis_hubzilla"/>
<env name="hz_db_user" value="ci-user"/>
<env name="hz_db_pass" value="ci-pass"/>
<env name="hz_db_database" value="ci-db"/>
</php>
</phpunit>

View File

@ -10,6 +10,7 @@ echo <<< EOT
util/addons list all # list all addons (*)= installed, (!)= disabled due to version compatibility
util/addons install foo # install addon named 'foo'
util/addons uninstall foo # uninstall addon named 'foo'
util/addons reinstall # reinstall all plugins
EOT;
}
@ -68,6 +69,20 @@ if($argc == 2 && $argv[1] === 'list') {
killme();
}
if($argc == 2 && $argv[1] === 'reinstall') {
require_once("include/plugin.php");
if($plugins) {
foreach($plugins as $p) {
if($p[1]) {
echo "Reinstall: ". $p[0] . "\n";
uninstall_plugin($p[0]);
install_plugin($p[0]);
}
}
}
killme();
}
if($argc == 3 && $argv[1] === 'list' && $argv[2] === 'all') {
if($plugins) {

View File

@ -7,7 +7,7 @@ git pull
if [ -d extend ] ; then
for a in theme addon widget ; do
if [ -d $a ]; then
if [ -d extend/$a ]; then
for b in `ls extend/$a` ; do
echo Updating $b
'util/update_'$a'_repo' $b

View File

@ -8,7 +8,7 @@ To see the files changed for a given bug, go to https://github.com/bshaffer/oaut
To get the diff between two versions, go to https://github.com/bshaffer/oauth2-server-php/compare/v1.0...v1.1
To get the diff for a specific change, go to https://github.com/bshaffer/oauth2-server-php/commit/XXX where XXX is the change hash
* 1.10.0 (2017-12-14)
* 1.10.0 (2017-11-15)
PR: https://github.com/bshaffer/oauth2-server-php/pull/889
@ -26,7 +26,7 @@ To get the diff for a specific change, go to https://github.com/bshaffer/oauth2-
* #794 - [docs] Fix typo in composer.json
* #885 - [testing] Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase
* 1.9.0 (2016-01-06)
* 1.9.0 (2017-01-06)
PR: https://github.com/bshaffer/oauth2-server-php/pull/788

View File

@ -1,7 +1,7 @@
oauth2-server-php
=================
[![Build Status](https://travis-ci.org/bshaffer/oauth2-server-php.svg?branch=develop)](https://travis-ci.org/bshaffer/oauth2-server-php)
[![Build Status](https://travis-ci.org/bshaffer/oauth2-server-php.svg?branch=master)](https://travis-ci.org/bshaffer/oauth2-server-php)
[![Total Downloads](https://poser.pugx.org/bshaffer/oauth2-server-php/downloads.png)](https://packagist.org/packages/bshaffer/oauth2-server-php)

View File

@ -64,7 +64,12 @@ class Request implements RequestInterface
$this->files = $files;
$this->server = $server;
$this->content = $content;
$this->headers = is_null($headers) ? $this->getHeadersFromServer($this->server) : $headers;
if ($headers === null) {
$headers = array();
}
$this->headers = $headers + $this->getHeadersFromServer($this->server);
}
/**

View File

@ -366,7 +366,7 @@ class Response implements ResponseInterface
if (count($this->parameters) > 0) {
// add parameters to URL redirection
$parts = parse_url($url);
$sep = isset($parts['query']) && count($parts['query']) > 0 ? '&' : '?';
$sep = isset($parts['query']) && !empty($parts['query']) ? '&' : '?';
$url .= $sep . http_build_query($this->parameters);
}

View File

@ -128,7 +128,7 @@ class JwtAccessToken extends AccessToken
$expires = time() + $this->config['access_lifetime'];
$id = $this->generateAccessToken();
return array(
$payload = array(
'id' => $id, // for BC (see #591)
'jti' => $id,
'iss' => $this->config['issuer'],
@ -139,5 +139,21 @@ class JwtAccessToken extends AccessToken
'token_type' => $this->config['token_type'],
'scope' => $scope
);
if (isset($this->config['jwt_extra_payload_callable'])) {
if (!is_callable($this->config['jwt_extra_payload_callable'])) {
throw new \InvalidArgumentException('jwt_extra_payload_callable is not callable');
}
$extra = call_user_func($this->config['jwt_extra_payload_callable'], $client_id, $user_id, $scope);
if (!is_array($extra)) {
throw new \InvalidArgumentException('jwt_extra_payload_callable must return array');
}
$payload = array_merge($extra, $payload);
}
return $payload;
}
}

View File

@ -88,12 +88,12 @@ class Server implements ResourceControllerInterface,
/**
* @var array
*/
protected $grantTypes = [];
protected $grantTypes = array();
/**
* @var array
*/
protected $responseTypes = [];
protected $responseTypes = array();
/**
* @var TokenTypeInterface
@ -161,6 +161,7 @@ class Server implements ResourceControllerInterface,
// merge all config values. These get passed to our controller objects
$this->config = array_merge(array(
'use_jwt_access_tokens' => false,
'jwt_extra_payload_callable' => null,
'store_encrypted_token_string' => true,
'use_openid_connect' => false,
'id_lifetime' => 3600,
@ -840,7 +841,7 @@ class Server implements ResourceControllerInterface,
$refreshStorage = $this->storages['refresh_token'];
}
$config = array_intersect_key($this->config, array_flip(explode(' ', 'store_encrypted_token_string issuer access_lifetime refresh_token_lifetime')));
$config = array_intersect_key($this->config, array_flip(explode(' ', 'store_encrypted_token_string issuer access_lifetime refresh_token_lifetime jwt_extra_payload_callable')));
return new JwtAccessToken($this->storages['public_key'], $tokenStorage, $refreshStorage, $config);
}
@ -1015,4 +1016,4 @@ class Server implements ResourceControllerInterface,
{
return isset($this->config[$name]) ? $this->config[$name] : $default;
}
}
}

View File

@ -86,6 +86,24 @@ class RequestTest extends TestCase
$this->assertEquals('correct', $request->query('client_id', $request->request('client_id')));
}
public function testRequestHasHeadersAndServerHeaders()
{
$request = new Request(
array(),
array(),
array(),
array(),
array(),
array('CONTENT_TYPE' => 'text/xml', 'PHP_AUTH_USER' => 'client_id', 'PHP_AUTH_PW' => 'client_pass'),
null,
array('CONTENT_TYPE' => 'application/json')
);
$this->assertSame('client_id', $request->headers('PHP_AUTH_USER'));
$this->assertSame('client_pass', $request->headers('PHP_AUTH_PW'));
$this->assertSame('application/json', $request->headers('CONTENT_TYPE'));
}
private function getTestServer($config = array())
{
$storage = Bootstrap::getInstance()->getMemoryStorage();

View File

@ -1,6 +1,8 @@
<?php
namespace OAuth2;use PHPUnit\Framework\TestCase;
namespace OAuth2;
use PHPUnit\Framework\TestCase;
class ResponseTest extends TestCase
{
@ -14,4 +16,23 @@ class ResponseTest extends TestCase
$string = $response->getResponseBody('xml');
$this->assertContains('<response><foo>bar</foo><halland>oates</halland></response>', $string);
}
public function testSetRedirect()
{
$response = new Response();
$url = 'https://foo/bar';
$state = 'stateparam';
$response->setRedirect(301, $url, $state);
$this->assertEquals(
sprintf('%s?state=%s', $url, $state),
$response->getHttpHeader('Location')
);
$query = 'query=foo';
$response->setRedirect(301, $url . '?' . $query, $state);
$this->assertEquals(
sprintf('%s?%s&state=%s', $url, $query, $state),
$response->getHttpHeader('Location')
);
}
}

View File

@ -40,6 +40,23 @@ class JwtAccessTokenTest extends TestCase
$this->assertEquals(3600, $delta);
$this->assertEquals($decodedAccessToken['id'], $decodedAccessToken['jti']);
}
public function testExtraPayloadCallback()
{
$jwtconfig = array('jwt_extra_payload_callable' => function() {
return array('custom_param' => 'custom_value');
});
$server = $this->getTestServer($jwtconfig);
$jwtResponseType = $server->getResponseType('token');
$accessToken = $jwtResponseType->createAccessToken('Test Client ID', 123, 'test', false);
$jwt = new Jwt;
$decodedAccessToken = $jwt->decode($accessToken['access_token'], null, false);
$this->assertArrayHasKey('custom_param', $decodedAccessToken);
$this->assertEquals('custom_value', $decodedAccessToken['custom_param']);
}
public function testGrantJwtAccessToken()
{
@ -140,7 +157,7 @@ class JwtAccessTokenTest extends TestCase
$this->assertNotNull($response->getParameter('access_token'));
}
private function getTestServer()
private function getTestServer($jwtconfig = array())
{
$memoryStorage = Bootstrap::getInstance()->getMemoryStorage();
@ -153,7 +170,7 @@ class JwtAccessTokenTest extends TestCase
$server->addGrantType(new ClientCredentials($memoryStorage));
// make the "token" response type a JwtAccessToken
$config = array('issuer' => 'https://api.example.com');
$config = array_merge(array('issuer' => 'https://api.example.com'), $jwtconfig);
$server->addResponseType(new JwtAccessToken($memoryStorage, $memoryStorage, null, $config));
return $server;

View File

@ -6,7 +6,8 @@ class PdoTest extends BaseTest
{
public function testCreatePdoStorageUsingPdoClass()
{
$pdo = new \PDO(sprintf('sqlite://%s', Bootstrap::getInstance()->getSqliteDir()));
$dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir());
$pdo = new \PDO($dsn);
$storage = new Pdo($pdo);
$this->assertNotNull($storage->getClientDetails('oauth_test_client'));
@ -14,7 +15,7 @@ class PdoTest extends BaseTest
public function testCreatePdoStorageUsingDSN()
{
$dsn = sprintf('sqlite://%s', Bootstrap::getInstance()->getSqliteDir());
$dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir());
$storage = new Pdo($dsn);
$this->assertNotNull($storage->getClientDetails('oauth_test_client'));
@ -22,7 +23,8 @@ class PdoTest extends BaseTest
public function testCreatePdoStorageUsingConfig()
{
$config = array('dsn' => sprintf('sqlite://%s', Bootstrap::getInstance()->getSqliteDir()));
$dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir());
$config = array('dsn' => $dsn);
$storage = new Pdo($config);
$this->assertNotNull($storage->getClientDetails('oauth_test_client'));

View File

@ -36,7 +36,7 @@ class Bootstrap
{
if (!$this->sqlite) {
$this->removeSqliteDb();
$pdo = new \PDO(sprintf('sqlite://%s', $this->getSqliteDir()));
$pdo = new \PDO(sprintf('sqlite:%s', $this->getSqliteDir()));
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->createSqliteDb($pdo);

View File

@ -380,9 +380,6 @@ return array(
'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php',
'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php',
'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php',
'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php',
'Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php',
'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
@ -1343,6 +1340,8 @@ return array(
'Zotlabs\\Update\\_1226' => $baseDir . '/Zotlabs/Update/_1226.php',
'Zotlabs\\Update\\_1227' => $baseDir . '/Zotlabs/Update/_1227.php',
'Zotlabs\\Update\\_1228' => $baseDir . '/Zotlabs/Update/_1228.php',
'Zotlabs\\Update\\_1229' => $baseDir . '/Zotlabs/Update/_1229.php',
'Zotlabs\\Update\\_1230' => $baseDir . '/Zotlabs/Update/_1230.php',
'Zotlabs\\Web\\Controller' => $baseDir . '/Zotlabs/Web/Controller.php',
'Zotlabs\\Web\\HTTPHeaders' => $baseDir . '/Zotlabs/Web/HTTPHeaders.php',
'Zotlabs\\Web\\HTTPSig' => $baseDir . '/Zotlabs/Web/HTTPSig.php',

View File

@ -548,9 +548,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php',
'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php',
'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php',
'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php',
'Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php',
'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
@ -1511,6 +1508,8 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Update\\_1226' => __DIR__ . '/../..' . '/Zotlabs/Update/_1226.php',
'Zotlabs\\Update\\_1227' => __DIR__ . '/../..' . '/Zotlabs/Update/_1227.php',
'Zotlabs\\Update\\_1228' => __DIR__ . '/../..' . '/Zotlabs/Update/_1228.php',
'Zotlabs\\Update\\_1229' => __DIR__ . '/../..' . '/Zotlabs/Update/_1229.php',
'Zotlabs\\Update\\_1230' => __DIR__ . '/../..' . '/Zotlabs/Update/_1230.php',
'Zotlabs\\Web\\Controller' => __DIR__ . '/../..' . '/Zotlabs/Web/Controller.php',
'Zotlabs\\Web\\HTTPHeaders' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPHeaders.php',
'Zotlabs\\Web\\HTTPSig' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPSig.php',

View File

@ -58,17 +58,17 @@
},
{
"name": "bshaffer/oauth2-server-php",
"version": "v1.10.0",
"version_normalized": "1.10.0.0",
"version": "v1.11.1",
"version_normalized": "1.11.1.0",
"source": {
"type": "git",
"url": "https://github.com/bshaffer/oauth2-server-php.git",
"reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9"
"reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/d158878425392fe5a0cc34f15dbaf46315ae0ed9",
"reference": "d158878425392fe5a0cc34f15dbaf46315ae0ed9",
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/5a0c8000d4763b276919e2106f54eddda6bc50fa",
"reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa",
"shasum": ""
},
"require": {
@ -89,7 +89,7 @@
"predis/predis": "Required to use Redis storage",
"thobbs/phpcassa": "Required to use Cassandra storage"
},
"time": "2017-11-15T01:41:02+00:00",
"time": "2018-12-04T00:29:32+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -254,17 +254,17 @@
},
{
"name": "league/html-to-markdown",
"version": "4.8.0",
"version_normalized": "4.8.0.0",
"version": "4.8.1",
"version_normalized": "4.8.1.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d"
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d",
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"shasum": ""
},
"require": {
@ -277,7 +277,7 @@
"phpunit/phpunit": "4.*",
"scrutinizer/ocular": "~1.1"
},
"time": "2018-09-18T12:18:08+00:00",
"time": "2018-12-24T17:21:44+00:00",
"bin": [
"bin/html-to-markdown"
],

View File

@ -4,6 +4,14 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip
## [Unreleased][unreleased]
## [4.8.1] - 2018-12-24
### Added
- Added support for PHP 7.3
### Fixed
- Fixed paragraphs following tables (#165, #166)
- Fixed incorrect list item escaping (#168, #169)
## [4.8.0] - 2018-09-18
### Added
- Added support for email auto-linking
@ -235,7 +243,8 @@ not ideally set, so this releases fixes that. Moving forwards this should reduce
### Added
- Initial release
[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...master
[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.1...master
[4.8.1]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...4.8.1
[4.8.0]: https://github.com/thephpleague/html-to-markdown/compare/4.7.0...4.8.0
[4.7.0]: https://github.com/thephpleague/html-to-markdown/compare/4.6.2...4.7.0
[4.6.2]: https://github.com/thephpleague/html-to-markdown/compare/4.6.1...4.6.2

View File

@ -37,7 +37,13 @@ class DefaultConverter implements ConverterInterface, ConfigurationAwareInterfac
return $element->getValue();
}
return html_entity_decode($element->getChildrenAsString());
$markdown = html_entity_decode($element->getChildrenAsString());
if ($element->getTagName() === 'table') {
$markdown .= "\n\n";
}
return $markdown;
}
/**

View File

@ -35,7 +35,10 @@ class HardBreakConverter implements ConverterInterface, ConfigurationAwareInterf
$next_value = $next->getValue();
if ($next_value) {
if (in_array(substr($next_value, 0, 2), array('- ', '* ', '+ '))) {
$return .= '\\';
$parent = $element->getParent();
if ($parent && $parent->getTagName() == 'li') {
$return .= '\\';
}
}
}
}

View File

@ -216,8 +216,6 @@ function string2bb(element) {
});
textcomplete.register([contacts,forums,smilies,tags]);
});
};
})( jQuery );

View File

@ -44,6 +44,17 @@ $(document).ready(function() {
$(document).on('click', '.conversation-settings-link', getConversationSettings);
$(document).on('click', '#settings_module_ajax_submit', postConversationSettings);
$(document).on('click focus', '.comment-edit-form textarea', function(e) {
if(! this.autocomplete_handled) {
/* autocomplete @nicknames */
$(this).editor_autocomplete(baseurl+"/acl?f=&n=1");
/* autocomplete bbcode */
$(this).bbco_autocomplete('bbcode');
this.autocomplete_handled = true;
}
});
var tf = new Function('n', 's', 'var k = s.split("/")['+aStr['plural_func']+']; return (k ? k : s);');
jQuery.timeago.settings.strings = {
@ -239,7 +250,11 @@ function handle_comment_form(e) {
},10000);
});
function commentSaveChanges(convId,isFinal = false) {
function commentSaveChanges(convId, isFinal) {
if(typeof isFinal === 'undefined')
isFinal = false;
if(auto_save_draft) {
tmp = $('#' + emptyCommentElm).val();
if(tmp) {
@ -453,6 +468,9 @@ function notificationsUpdate(cached_data) {
$.get(pingCmd,function(data) {
// Put the object into storage
if(! data)
return;
sessionStorage.setItem('notifications_cache', JSON.stringify(data));
var fnotifs = [];
@ -751,11 +769,6 @@ function updateConvItems(mode,data) {
mediaPlaying = false;
});
/* autocomplete @nicknames */
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl?f=&n=1");
/* autocomplete bbcode */
$(".comment-edit-form textarea").bbco_autocomplete('bbcode');
var bimgs = ((preloadImages) ? false : $(".wall-item-body img").not(function() { return this.complete; }));
var bimgcount = bimgs.length;
@ -888,7 +901,12 @@ function liveUpdate(notify_id) {
if((src === null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
if(($('.comment-edit-text.expanded').length) || (in_progress) || (mediaPlaying)) {
// if auto updates are enabled and a comment box is open,
// prevent live updates until the comment is submitted
var lockUpdates = (($('.comment-edit-text.expanded').length && (! bParam_static)) ? true : false);
if(lockUpdates || in_progress || mediaPlaying) {
if(livetime) {
clearTimeout(livetime);
}

View File

@ -1803,3 +1803,8 @@ dl.bb-dl > dd > li {
.hover-fx-show:hover .hover-fx-hide {
opacity: 1;
}
/* default highlighted text if not specified by schema: */
span.default-highlight {
background-color: yellow;
}

View File

@ -322,20 +322,6 @@ a, a:visited, a:link, .fakelink, .fakelink:visited, .fakelink:link {
.text-dark {
color: #aaa !important;
}
a.text-dark:focus, a.text-dark:hover {
color: #ddd !important;
}
.badge-warning {
background-color: #ffc927;
}
.badge-warning a.text-dark {
color: #333 !important;
}
.badge-warning a.text-dark:focus, .badge-warning a.text-dark:hover {
color: red !important;
text-decoration: none;
}
.group-selected, .fileas-selected, .categories-selected, .search-selected, a.active {
color: #fff !important;
@ -492,10 +478,25 @@ pre {
background-color: #222;
}
/* change color of [hl] tag: */
div.wall-item-body span /*strong:only-of-type */{
color: #1212b6;
padding: 2px 3px;
/* font-weight: 500; */
white-space: nowrap;
/* category badge fix: */
a.text-dark:focus, a.text-dark:hover {
color: #ddd !important;
}
.badge-warning {
/* background-color: #ffc927; */
}
.badge-warning a.text-dark {
color: #333 !important;
}
.badge-warning a.text-dark:focus, .badge-warning a.text-dark:hover {
color: red !important;
text-decoration: none;
}
/* fix color for highlithed text */
span.default-highlight {
color: #333;
border-radius: 4px;
}

View File

@ -31,8 +31,8 @@
<a class="dropdown-item{{if $app.active}} active{{/if}}" href="{{$app.url}}">{{if $icon}}<i class="generic-icons-nav fa fa-fw fa-{{$icon}}"></i>{{else}}<img src="{{$app.photo}}" width="16" height="16" style="margin-right:9px;"/>{{/if}}{{$app.name}}</a>
{{/if}}
{{if $order}}
<a href="{{$hosturl}}appman/{{$app.guid}}/moveup" class="btn btn-outline-secondary btn-sm" style="margin-bottom: 5px;"><i class="generic-icons-nav fa fa-fw fa-arrow-up"></i></a>
<a href="{{$hosturl}}appman/{{$app.guid}}/movedown" class="btn btn-outline-secondary btn-sm" style="margin-bottom: 5px;"><i class="generic-icons-nav fa fa-fw fa-arrow-down"></i></a>
<a href="{{$hosturl}}appman/{{$app.guid}}/moveup{{if $pinned}}/nav_pinned_app{{else}}/nav_featured_app{{/if}}" class="btn btn-outline-secondary btn-sm" style="margin-bottom: 5px;"><i class="generic-icons-nav fa fa-fw fa-arrow-up"></i></a>
<a href="{{$hosturl}}appman/{{$app.guid}}/movedown{{if $pinned}}/nav_pinned_app{{else}}/nav_featured_app{{/if}}" class="btn btn-outline-secondary btn-sm" style="margin-bottom: 5px;"><i class="generic-icons-nav fa fa-fw fa-arrow-down"></i></a>
{{if $icon}}<i class="generic-icons-nav fa fa-fw fa-{{$icon}}"></i>{{else}}<img src="{{$app.photo}}" width="16" height="16" style="margin-right:9px;"/>{{/if}}{{$app.name}}<br>
{{/if}}

View File

@ -9,12 +9,12 @@
<div class="wall-item-outside-wrapper{{if $item.is_comment}} comment{{/if}}{{if $item.previewing}} preview{{/if}}" id="wall-item-outside-wrapper-{{$item.id}}" >
<div class="clearfix wall-item-content-wrapper{{if $item.is_comment}} comment{{/if}}" id="wall-item-content-wrapper-{{$item.id}}">
{{if $item.photo}}
<div class="wall-photo-item" id="wall-photo-item-{{$item.id}}">
<div class="wall-photo-item{{if $item.is_new && !$item.title}} wall-item-head-new rounded-top{{/if}}" id="wall-photo-item-{{$item.id}}">
{{$item.photo}}
</div>
{{/if}}
{{if $item.event}}
<div class="wall-event-item" id="wall-event-item-{{$item.id}}">
<div class="wall-event-item{{if $item.is_new && !$item.title}} wall-item-head-new rounded-top{{/if}}" id="wall-event-item-{{$item.id}}">
{{$item.event}}
</div>
{{/if}}
@ -26,7 +26,7 @@
<hr class="m-0">
{{/if}}
{{/if}}
<div class="p-2 clearfix wall-item-head{{if $item.is_new && !$item.title && !$item.event && !$item.is_comment}} wall-item-head-new rounded-top{{/if}}">
<div class="p-2 clearfix wall-item-head{{if $item.is_new && !$item.title && !$item.event && !$item.is_comment && !$item.photo}} wall-item-head-new rounded-top{{/if}}">
<div class="wall-item-info " id="wall-item-info-{{$item.id}}" >
<div class="wall-item-photo-wrapper{{if $item.owner_url}} wwfrom{{/if}} h-card p-author" id="wall-item-photo-wrapper-{{$item.id}}">
<img src="{{$item.thumb}}" class="fakelink wall-item-photo{{$item.sparkle}} u-photo p-name" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" data-toggle="dropdown" />

View File

@ -9,12 +9,12 @@
<div class="wall-item-outside-wrapper{{if $item.is_comment}} comment{{/if}}{{if $item.previewing}} preview{{/if}}" id="wall-item-outside-wrapper-{{$item.id}}" >
<div class="clearfix wall-item-content-wrapper{{if $item.is_comment}} comment{{/if}}" id="wall-item-content-wrapper-{{$item.id}}">
{{if $item.photo}}
<div class="wall-photo-item" id="wall-photo-item-{{$item.id}}">
<div class="wall-photo-item{{if $item.is_new && !$item.title}} wall-item-head-new rounded-top{{/if}}" id="wall-photo-item-{{$item.id}}">
{{$item.photo}}
</div>
{{/if}}
{{if $item.event}}
<div class="wall-event-item" id="wall-event-item-{{$item.id}}">
<div class="wall-event-item{{if $item.is_new && !$item.title}} wall-item-head-new rounded-top{{/if}}" id="wall-event-item-{{$item.id}}">
{{$item.event}}
</div>
{{/if}}
@ -26,7 +26,7 @@
<hr class="m-0">
{{/if}}
{{/if}}
<div class="p-2 clearfix wall-item-head{{if $item.is_new && !$item.title && !$item.event && !$item.is_comment}} wall-item-head-new rounded-top{{/if}}">
<div class="p-2 clearfix wall-item-head{{if $item.is_new && !$item.title && !$item.event && !$item.is_comment && !$item.photo}} wall-item-head-new rounded-top{{/if}}">
<div class="wall-item-info" id="wall-item-info-{{$item.id}}" >
<div class="wall-item-photo-wrapper{{if $item.owner_url}} wwfrom{{/if}} h-card p-author" id="wall-item-photo-wrapper-{{$item.id}}">
<img src="{{$item.thumb}}" class="fakelink wall-item-photo{{$item.sparkle}} u-photo p-name" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" data-toggle="dropdown" /></a>

View File

@ -219,7 +219,7 @@ var activeCommentText = '';
}
function linkdropper(event) {
var linkFound = event.dataTransfer.types.contains("text/uri-list");
var linkFound = ((event.dataTransfer.types.indexOf("text/uri-list") > -1) ? true : false);
if(linkFound) {
event.preventDefault();
var editwin = '#' + event.target.id;
@ -256,7 +256,7 @@ var activeCommentText = '';
commentwin = ((editwin.indexOf('comment') >= 0) ? true : false);
if(commentwin) {
var commentid = editwin.substring(editwin.lastIndexOf('-') + 1);
commentOpen(document.getElementById(event.target.id),commentid);
$("#comment-edit-text-" + commentid).addClass("expanded");
}
}

View File

@ -24,7 +24,7 @@
});
window.onpopstate = function(e) {
if(e.state !== null)
if(e.state !== null && e.state.b64mid !== bParam_mid)
getData(e.state.b64mid, '');
};
});

View File

@ -8,6 +8,7 @@
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
{{include file="field_input.tpl" field=$gname}}
{{include file="field_checkbox.tpl" field=$public}}
{{$pgrp_extras}}
<button type="submit" name="submit" class="btn btn-sm btn-primary float-right">{{$submit}}</button>
</form>
</div>