mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 09:01:15 -04:00
Compare commits
210 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90fd323ac5 | ||
|
|
b6c384a0f7 | ||
|
|
cda8a7be38 | ||
|
|
ddbc35181c | ||
|
|
57dde3e980 | ||
|
|
3eba0c2297 | ||
|
|
414b7e28d3 | ||
|
|
fca464071f | ||
|
|
4f08f4b84c | ||
|
|
1b5175d018 | ||
|
|
0bfda6d4c8 | ||
|
|
880b22604b | ||
|
|
04a2dc075f | ||
|
|
01448c152c | ||
|
|
a09beb3833 | ||
|
|
feda1e6d84 | ||
|
|
4256bea418 | ||
|
|
4d47b098e5 | ||
|
|
163754a46c | ||
|
|
66b56416b6 | ||
|
|
c855346358 | ||
|
|
0e32c86c3d | ||
|
|
19952264c8 | ||
|
|
5ec1e97cae | ||
|
|
5f5746a2f6 | ||
|
|
d0ee6d1ad2 | ||
|
|
06c71eec65 | ||
|
|
aabc6c2825 | ||
|
|
8323458da9 | ||
|
|
d7c7ff1c12 | ||
|
|
d77c7d51e3 | ||
|
|
d51d0160d3 | ||
|
|
c2ad9d4996 | ||
|
|
79f828125d | ||
|
|
ad4b18cbbe | ||
|
|
1bd49671b7 | ||
|
|
9896057549 | ||
|
|
44832bbacb | ||
|
|
f20a923dd7 | ||
|
|
30403da326 | ||
|
|
6b68a76bbe | ||
|
|
8f10b58cb1 | ||
|
|
f8bc408abc | ||
|
|
f581f6163a | ||
|
|
88486a1278 | ||
|
|
9fcadc2d7c | ||
|
|
9ef6c57ca5 | ||
|
|
443d7684db | ||
|
|
a3ba7f0788 | ||
|
|
f083c0cba1 | ||
|
|
defa2d9df1 | ||
|
|
05c422ef23 | ||
|
|
51d274961b | ||
|
|
4b4cc04897 | ||
|
|
4bf3d4d87a | ||
|
|
71cc980e96 | ||
|
|
58c0b81908 | ||
|
|
3b42bd43ab | ||
|
|
a151532ffa | ||
|
|
a0d1ce77dc | ||
|
|
863cae1bab | ||
|
|
4010ea814a | ||
|
|
8e25c091f4 | ||
|
|
0bba9482df | ||
|
|
f8a8559523 | ||
|
|
1044e8e91a | ||
|
|
ba4b1cb5af | ||
|
|
5cb4cdaa5e | ||
|
|
7be1d9e45a | ||
|
|
ae97649948 | ||
|
|
f15e32d063 | ||
|
|
afc75af62f | ||
|
|
2778a7220f | ||
|
|
26f593afaa | ||
|
|
beac45b075 | ||
|
|
dfc5159aa3 | ||
|
|
886cdb440b | ||
|
|
6ed9443972 | ||
|
|
08e0f172de | ||
|
|
f1d168f781 | ||
|
|
302d9796c4 | ||
|
|
1260887fa7 | ||
|
|
ce8073d25e | ||
|
|
31f4d9066b | ||
|
|
35e66770be | ||
|
|
cf2f7f2132 | ||
|
|
a145559662 | ||
|
|
d029e3dc16 | ||
|
|
286326a98e | ||
|
|
2f59d78737 | ||
|
|
adf4782076 | ||
|
|
b38ffef2be | ||
|
|
6375f2d73a | ||
|
|
a7d3a49171 | ||
|
|
920e7db709 | ||
|
|
4a6b45cf04 | ||
|
|
7bd60adfbe | ||
|
|
c335719e8f | ||
|
|
d57cdf645e | ||
|
|
e47a96bf24 | ||
|
|
daad607c7c | ||
|
|
29f1f9c872 | ||
|
|
a49cfa8142 | ||
|
|
b57d296adc | ||
|
|
01d8bd445e | ||
|
|
750d6f4be9 | ||
|
|
c6e14a696e | ||
|
|
d34423fce9 | ||
|
|
4999547f87 | ||
|
|
fc5dc9717a | ||
|
|
d20759c141 | ||
|
|
f7b00c62a4 | ||
|
|
32873ce70d | ||
|
|
dc59561a95 | ||
|
|
4bf3fdd898 | ||
|
|
108a892a11 | ||
|
|
2c4bd9a3fe | ||
|
|
098ec1abb4 | ||
|
|
17cf824545 | ||
|
|
e35f5d3c93 | ||
|
|
f4f98e5856 | ||
|
|
dc0335d1d5 | ||
|
|
6013814cf4 | ||
|
|
e0a0570cc4 | ||
|
|
61deb4fcfd | ||
|
|
7c4c60425b | ||
|
|
302f49baf2 | ||
|
|
3f6cd5a663 | ||
|
|
1b232041c9 | ||
|
|
eaf117cce1 | ||
|
|
7148311953 | ||
|
|
c23dfa0d23 | ||
|
|
b08de33b0b | ||
|
|
fc1d8c0138 | ||
|
|
a5a77d1e7c | ||
|
|
f57fcefe6b | ||
|
|
6c6dca05e7 | ||
|
|
97b4a31b16 | ||
|
|
40d9277ef3 | ||
|
|
009044b71e | ||
|
|
4760a3f3e8 | ||
|
|
3302012c02 | ||
|
|
812c5a314f | ||
|
|
c2da8c3fd4 | ||
|
|
aa78640491 | ||
|
|
7c49688e1b | ||
|
|
dbe10c7965 | ||
|
|
f1f5107282 | ||
|
|
cc06250bf8 | ||
|
|
af1ea7f495 | ||
|
|
3491c488d3 | ||
|
|
1828b6daab | ||
|
|
c26f45b7c2 | ||
|
|
e116b90116 | ||
|
|
43a5f928ba | ||
|
|
873fa16517 | ||
|
|
f7ce374a28 | ||
|
|
2dd124d09e | ||
|
|
d6523c67a6 | ||
|
|
a9fd3608ea | ||
|
|
b25cace3ea | ||
|
|
4320f047db | ||
|
|
b4b3e7b9a4 | ||
|
|
b6938da552 | ||
|
|
4830a1559d | ||
|
|
92ea3ef720 | ||
|
|
73d2719330 | ||
|
|
af82aab3a6 | ||
|
|
51b4b6216f | ||
|
|
de32b0bba5 | ||
|
|
de0fab78ed | ||
|
|
71425c3b23 | ||
|
|
75f7b1e261 | ||
|
|
9af35d998f | ||
|
|
34e3f3907a | ||
|
|
46b0510b99 | ||
|
|
a7624ea48b | ||
|
|
2f3b4a7aaf | ||
|
|
a9bbe0b128 | ||
|
|
0d9d0a4b70 | ||
|
|
8235d0bd50 | ||
|
|
c2e01bedc5 | ||
|
|
32c4614a32 | ||
|
|
24ae6c91ea | ||
|
|
346a4f5933 | ||
|
|
c6551336c8 | ||
|
|
3dab0d365d | ||
|
|
0252bac4ba | ||
|
|
b468069875 | ||
|
|
7e1f431eca | ||
|
|
70c55da1df | ||
|
|
f9ab7647dd | ||
|
|
623aa7ea48 | ||
|
|
046d264688 | ||
|
|
944e168120 | ||
|
|
9594105e57 | ||
|
|
675343f575 | ||
|
|
fc6ff45c49 | ||
|
|
b4bac88c39 | ||
|
|
c622ba84b9 | ||
|
|
339f95c647 | ||
|
|
ec67e0ab22 | ||
|
|
0b371c8103 | ||
|
|
2192ea6fdf | ||
|
|
0060f88c45 | ||
|
|
1eac4db491 | ||
|
|
0d2c3be367 | ||
|
|
1241e778f9 | ||
|
|
3ab0ef1902 | ||
|
|
c7c35b8b5a |
91
CHANGELOG
91
CHANGELOG
@@ -1,3 +1,94 @@
|
||||
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
|
||||
- Streamline PDF previews
|
||||
- Allow notification filtering by name or address
|
||||
- Fix too restrictive attached photo permissions
|
||||
- Update ES translation
|
||||
- Use flex for the default template
|
||||
- Do not store serialized pconfig value received via to Module/Pconfig.php
|
||||
- Update jquery-file-upload lib and move to composer
|
||||
- Update imagesloaded lib and move to composer
|
||||
- Fix activitypub tag notifications
|
||||
- Fix call to undefined function in PConfig
|
||||
- Fix typo which prevented propagation of comments to zot6 (dev)
|
||||
- Activitypub: add support for pterotype (wordpress plugin)
|
||||
- Openstreetmap: check validity of lat+lon before rendering a map
|
||||
|
||||
|
||||
Hubzilla 3.8.5 (2018-11-19)
|
||||
- Fix pconfig for new installs
|
||||
- Fix delayed publication of posts in combination with channel clones
|
||||
- Fix issue where photo filesize was not updated in the DB when a photo was edited
|
||||
- Fix issue where the original photo size was not set correct in the DB
|
||||
- Fix delivery issue in zot_fetch()
|
||||
- Fix typo in channel reputation addon
|
||||
|
||||
|
||||
Hubzilla 3.8.4 (2018-11-14)
|
||||
- Fix xss issue (thanks to Eduardo)
|
||||
- Implement hook in enotify to be used by superblock
|
||||
- Various css fixes
|
||||
- Improve photo cache handling
|
||||
- Provide a function hz_syslog() to log to syslog
|
||||
- Fix request_target in z_post_url()
|
||||
- Fix plural handling for various languages
|
||||
- Some preparatory work for zot6
|
||||
- Fix warning in gallery addon
|
||||
- Fix date issue on xchan photo update in diaspora and pubcrawl addons
|
||||
- Fix typos in startpage addon
|
||||
- Improve activitypub addressing
|
||||
- Fix taxonomy in activitypub direct messages
|
||||
- Fix syntax error in diaspora addon
|
||||
- New e-learning addon flashcards
|
||||
- Remove DNS check for database connection during installation
|
||||
- Implement timestamps for pconfig
|
||||
|
||||
|
||||
Hubzilla 3.8.3 (2018-11-05)
|
||||
- Do not count likes in forum notifications if likes notifications are disabled
|
||||
- Fix typo in spanish translation which broke javascript
|
||||
- Improve linkinfo charset handling and image detection
|
||||
- Fix wrong image resize for some external images
|
||||
- Move blueimp upload lib to composer and update to version 9.25
|
||||
- Remove primary/clone counts from admin summary until we have a mechanism to update the fixed counts
|
||||
- Fix html2markdown() and re-enable previously failing tests
|
||||
- Improve look of oembed content for Hubzilla links
|
||||
- Fix forum notifications count not correct
|
||||
- Fix gallery addon which broke mod apps in some situations
|
||||
- Fix wiki_list widget not working on every page respectively level
|
||||
|
||||
|
||||
Hubzilla 3.8.2 (2018-10-29)
|
||||
- Merge unmerged changes from dev into master
|
||||
- Fix issues with forum handling in mod network and ping
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -808,12 +808,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 +852,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 +895,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 +942,7 @@ class Apps {
|
||||
$narr[] = $x['name'];
|
||||
}
|
||||
|
||||
set_pconfig($uid,'system','app_order',implode(',',$narr));
|
||||
set_pconfig($uid,'system',$conf,implode(',',$narr));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -825,9 +825,10 @@ class Enotify {
|
||||
|
||||
// convert this logic into a json array just like the system notifications
|
||||
|
||||
return array(
|
||||
$x = array(
|
||||
'notify_link' => $item['llink'],
|
||||
'name' => $item['author']['xchan_name'],
|
||||
'addr' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'url' => $item['author']['xchan_url'],
|
||||
'photo' => $item['author']['xchan_photo_s'],
|
||||
'when' => relative_date(($edit)? $item['edited'] : $item['created']),
|
||||
@@ -835,9 +836,19 @@ class Enotify {
|
||||
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'notify_id' => 'undefined',
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => strip_tags(bbcode($itemem_text))
|
||||
'message' => strip_tags(bbcode($itemem_text)),
|
||||
// these are for the superblock addon
|
||||
'hash' => $item['author']['xchan_hash'],
|
||||
'uid' => local_channel(),
|
||||
'display' => true
|
||||
);
|
||||
|
||||
call_hooks('enotify_format',$x);
|
||||
if(! $x['display']) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,16 +7,10 @@ namespace Zotlabs\Lib;
|
||||
*
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\DReport;
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Lib\Group;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
use Zotlabs\Lib\System;
|
||||
use Zotlabs\Lib\MessageFilter;
|
||||
use Zotlabs\Lib\Queue;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Zot6\HTTPSig;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
require_once('include/crypto.php');
|
||||
|
||||
@@ -211,9 +205,10 @@ class Libzot {
|
||||
|
||||
if($channel) {
|
||||
$headers = [
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Content-type' => 'application/x-zot+json'
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Content-type' => 'application/x-zot+json',
|
||||
'(request-target)' => 'post ' . get_request_string($url)
|
||||
];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false,'sha512',
|
||||
@@ -378,13 +373,13 @@ class Libzot {
|
||||
else {
|
||||
// if we were just granted read stream permission and didn't have it before, try to pull in some posts
|
||||
if((! $old_read_stream_perm) && (intval($permissions['view_stream'])))
|
||||
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$r[0]['abook_id']));
|
||||
Master::Summon([ 'Onepoll', $r[0]['abook_id'] ]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
|
||||
$my_perms = \Zotlabs\Access\Permissions::serialise($p['perms']);
|
||||
$p = Permissions::connect_perms($channel['channel_id']);
|
||||
$my_perms = Permissions::serialise($p['perms']);
|
||||
|
||||
$automatic = $p['automatic'];
|
||||
|
||||
@@ -424,8 +419,8 @@ class Libzot {
|
||||
);
|
||||
|
||||
if($new_connection) {
|
||||
if(! \Zotlabs\Access\Permissions::PermsCompare($new_perms,$previous_perms))
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','permissions_create',$new_connection[0]['abook_id']));
|
||||
if(! Permissions::PermsCompare($new_perms,$previous_perms))
|
||||
Master::Summon([ 'Notifier', 'permissions_create', $new_connection[0]['abook_id'] ]);
|
||||
Enotify::submit(
|
||||
[
|
||||
'type' => NOTIFY_INTRO,
|
||||
@@ -438,7 +433,7 @@ class Libzot {
|
||||
if(intval($permissions['view_stream'])) {
|
||||
if(intval(get_pconfig($channel['channel_id'],'perm_limits','send_stream') & PERMS_PENDING)
|
||||
|| (! intval($new_connection[0]['abook_pending'])))
|
||||
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$new_connection[0]['abook_id']));
|
||||
Master::Summon([ 'Onepoll', $new_connection[0]['abook_id'] ]);
|
||||
}
|
||||
|
||||
|
||||
@@ -975,39 +970,45 @@ class Libzot {
|
||||
$x = json_decode($x,true);
|
||||
}
|
||||
|
||||
if(! $x['success']) {
|
||||
|
||||
// handle remote validation issues
|
||||
|
||||
$b = q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc(($x['message']) ? $x['message'] : 'unknown delivery error'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
if(! is_array($x)) {
|
||||
btlogger('failed communication - no response');
|
||||
}
|
||||
|
||||
if(array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) {
|
||||
foreach($x['delivery_report'] as $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($xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
}
|
||||
if($x) {
|
||||
if(! $x['success']) {
|
||||
|
||||
// handle remote validation issues
|
||||
|
||||
$b = q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc(($x['message']) ? $x['message'] : 'unknown delivery error'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
}
|
||||
|
||||
// we have a more descriptive delivery report, so discard the per hub 'queue' report.
|
||||
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)) {
|
||||
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($xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
q("delete from dreport where dreport_queue = '%s' ",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
// we have a more descriptive delivery report, so discard the per hub 'queue' report.
|
||||
|
||||
q("delete from dreport where dreport_queue = '%s' ",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// update the timestamp for this site
|
||||
|
||||
q("update site set site_dead = 0, site_update = '%s' where site_url = '%s'",
|
||||
@@ -1092,13 +1093,27 @@ class Libzot {
|
||||
return;
|
||||
}
|
||||
|
||||
$message_request = ((array_key_exists('message_id',$env)) ? true : false);
|
||||
if($message_request)
|
||||
logger('processing message request');
|
||||
$message_request = false;
|
||||
|
||||
|
||||
$has_data = array_key_exists('data',$env) && $env['data'];
|
||||
$data = (($has_data) ? $env['data'] : false);
|
||||
|
||||
|
||||
$AS = null;
|
||||
|
||||
if($env['encoding'] === 'activitystreams') {
|
||||
|
||||
$AS = new ActivityStreams($data);
|
||||
if(! $AS->is_valid()) {
|
||||
logger('Activity rejected: ' . print_r($data,true));
|
||||
return;
|
||||
}
|
||||
$arr = Activity::decode_note($AS);
|
||||
|
||||
logger($AS->debug());
|
||||
}
|
||||
|
||||
|
||||
$deliveries = null;
|
||||
|
||||
if(array_key_exists('recipients',$env) && count($env['recipients'])) {
|
||||
@@ -1140,7 +1155,7 @@ class Libzot {
|
||||
// and who are allowed to see them based on the sender's permissions
|
||||
// @fixme;
|
||||
|
||||
$deliveries = self::public_recips($env);
|
||||
$deliveries = self::public_recips($env,$AS);
|
||||
|
||||
|
||||
}
|
||||
@@ -1157,49 +1172,43 @@ class Libzot {
|
||||
|
||||
if(in_array($env['type'],['activity','response'])) {
|
||||
|
||||
if($env['encoding'] === 'zot') {
|
||||
$arr = get_item_elements($data);
|
||||
|
||||
$v = validate_item_elements($data,$arr);
|
||||
|
||||
if(! $v['success']) {
|
||||
logger('Activity rejected: ' . $v['message'] . ' ' . print_r($data,true));
|
||||
return;
|
||||
}
|
||||
$arr = Activity::decode_note($AS);
|
||||
|
||||
//logger($AS->debug());
|
||||
|
||||
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$arr['author_xchan'] = $r[0]['hubloc_hash'];
|
||||
}
|
||||
elseif($env['encoding'] === 'activitystreams') {
|
||||
|
||||
$AS = new \Zotlabs\Lib\ActivityStreams($data);
|
||||
if(! $AS->is_valid()) {
|
||||
logger('Activity rejected: ' . print_r($data,true));
|
||||
return;
|
||||
}
|
||||
$arr = \Zotlabs\Lib\Activity::decode_note($AS);
|
||||
|
||||
logger($AS->debug());
|
||||
$s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($env['sender'])
|
||||
);
|
||||
|
||||
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$arr['author_xchan'] = $r[0]['hubloc_hash'];
|
||||
}
|
||||
// @fixme (in individual delivery, change owner if needed)
|
||||
// in individual delivery, change owner if needed
|
||||
if($s) {
|
||||
$arr['owner_xchan'] = $s[0]['hubloc_hash'];
|
||||
}
|
||||
else {
|
||||
$arr['owner_xchan'] = $env['sender'];
|
||||
if($private) {
|
||||
$arr['item_private'] = true;
|
||||
}
|
||||
// @fixme - spoofable
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($private) {
|
||||
$arr['item_private'] = true;
|
||||
}
|
||||
// @fixme - spoofable
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
}
|
||||
|
||||
|
||||
logger('Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
@@ -1225,15 +1234,31 @@ class Libzot {
|
||||
}
|
||||
|
||||
|
||||
static function is_top_level($env) {
|
||||
static function is_top_level($env,$act) {
|
||||
if($env['encoding'] === 'zot' && array_key_exists('flags',$env) && in_array('thread_parent', $env['flags'])) {
|
||||
return true;
|
||||
}
|
||||
if($env['encoding'] === 'activitystreams') {
|
||||
if(array_key_exists('inReplyTo',$env['data']) && $env['data']['inReplyTo']) {
|
||||
if($act) {
|
||||
if(in_array($act->type, ['Like','Dislike'])) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
$x = self::find_parent($env,$act);
|
||||
if($x === $act->id || $x === $act->obj['id']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function find_parent($env,$act) {
|
||||
if($act) {
|
||||
if(in_array($act->type, ['Like','Dislike'])) {
|
||||
return $act->obj['id'];
|
||||
}
|
||||
if($act->parent_id) {
|
||||
return $act->parent_id;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1255,7 +1280,7 @@ class Libzot {
|
||||
* @return NULL|array
|
||||
*/
|
||||
|
||||
static function public_recips($msg) {
|
||||
static function public_recips($msg, $act) {
|
||||
|
||||
require_once('include/channel.php');
|
||||
|
||||
@@ -1269,7 +1294,7 @@ class Libzot {
|
||||
|
||||
$perm = 'send_stream';
|
||||
|
||||
if(self::is_top_level($msg)) {
|
||||
if(self::is_top_level($msg,$act)) {
|
||||
$check_mentions = true;
|
||||
}
|
||||
}
|
||||
@@ -1301,9 +1326,9 @@ class Libzot {
|
||||
|
||||
if($check_mentions) {
|
||||
// It's a top level post. Look at the tags. See if any of them are mentions and are on this hub.
|
||||
if(array_path_exists('data/object/tag',$msg)) {
|
||||
if(is_array($msg['data']['object']['tag']) && $msg['data']['object']['tag']) {
|
||||
foreach($msg['data']['object']['tag'] as $tag) {
|
||||
if($act && $act->obj) {
|
||||
if(is_array($act->obj['tag']) && $act->obj['tag']) {
|
||||
foreach($act->obj['tag'] as $tag) {
|
||||
if($tag['type'] === 'Mention' && (strpos($tag['href'],z_root()) !== false)) {
|
||||
$address = basename($tag['href']);
|
||||
if($address) {
|
||||
@@ -1325,9 +1350,12 @@ class Libzot {
|
||||
// everybody that stored a copy of the parent. This way we know we're covered. We'll check the
|
||||
// comment permissions when we deliver them.
|
||||
|
||||
if(array_path_exists('data/inReplyTo',$msg)) {
|
||||
$z = q("select owner_xchan as hash from item where parent_mid = '%s' ",
|
||||
dbesc($msg['data']['inReplyTo'])
|
||||
$thread_parent = self::find_parent($msg,$act);
|
||||
|
||||
if($thread_parent) {
|
||||
$z = q("select channel_hash as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) ",
|
||||
dbesc($thread_parent),
|
||||
dbesc($thread_parent)
|
||||
);
|
||||
if($z) {
|
||||
foreach($z as $zv) {
|
||||
@@ -1341,7 +1369,7 @@ class Libzot {
|
||||
// It's a bit of work since it's a multi-dimensional array
|
||||
|
||||
if($r) {
|
||||
$r = array_unique($r);
|
||||
$r = array_values(array_unique($r));
|
||||
}
|
||||
|
||||
logger('public_recips: ' . print_r($r,true), LOGGER_DATA, LOG_DEBUG);
|
||||
@@ -1378,7 +1406,7 @@ class Libzot {
|
||||
|
||||
$local_public = $public;
|
||||
|
||||
$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,$arr['mid']);
|
||||
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
|
||||
|
||||
$channel = channelx_by_hash($d);
|
||||
|
||||
@@ -1413,7 +1441,7 @@ class Libzot {
|
||||
$local_public = true;
|
||||
|
||||
$r = q("select xchan_selfcensored from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($sender['hash'])
|
||||
dbesc($sender)
|
||||
);
|
||||
// don't import sys channel posts from selfcensored authors
|
||||
if($r && (intval($r[0]['xchan_selfcensored']))) {
|
||||
@@ -1441,11 +1469,30 @@ class Libzot {
|
||||
$arr['item_wall'] = 0;
|
||||
}
|
||||
|
||||
if((! perm_is_allowed($channel['channel_id'],$sender,$perm)) && (! $tag_delivery) && (! $local_public)) {
|
||||
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
|
||||
$DR->update('permission denied');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
$friendofriend = false;
|
||||
|
||||
if ((! $tag_delivery) && (! $local_public)) {
|
||||
$allowed = (perm_is_allowed($channel['channel_id'],$sender,$perm));
|
||||
if((! $allowed) && $perm === 'post_comments') {
|
||||
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if ($parent) {
|
||||
$allowed = can_comment_on_post($d,$parent[0]);
|
||||
}
|
||||
}
|
||||
if($request) {
|
||||
$allowed = true;
|
||||
$friendofriend = true;
|
||||
}
|
||||
|
||||
if (! $allowed) {
|
||||
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
|
||||
$DR->update('permission denied');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if($arr['mid'] != $arr['parent_mid']) {
|
||||
@@ -1456,7 +1503,7 @@ class Libzot {
|
||||
// As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
|
||||
// processing it is pointless.
|
||||
|
||||
$r = q("select route, id from item where mid = '%s' and uid = %d limit 1",
|
||||
$r = q("select route, id, owner_xchan, item_private from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
@@ -1480,15 +1527,21 @@ class Libzot {
|
||||
|
||||
if((! $relay) && (! $request) && (! $local_public)
|
||||
&& perm_is_allowed($channel['channel_id'],$sender,'send_stream')) {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'request', $channel['channel_id'], $sender, $arr['parent_mid']));
|
||||
self::fetch_conversation($channel,$arr['parent_mid']);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if($relay) {
|
||||
|
||||
if($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
|
||||
// reset the route in case it travelled a great distance upstream
|
||||
// use our parent's route so when we go back downstream we'll match
|
||||
// with whatever route our parent has.
|
||||
// Also friend-of-friend conversations may have been imported without a route,
|
||||
// but we are now getting comments via listener delivery
|
||||
// and if there is no privacy on this or the parent, we don't care about the route,
|
||||
// so just set the owner and route accordingly.
|
||||
$arr['route'] = $r[0]['route'];
|
||||
$arr['owner_xchan'] = $r[0]['owner_xchan'];
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1546,13 +1599,13 @@ class Libzot {
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
|
||||
$item_id = delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
|
||||
$item_id = self::delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
|
||||
$DR->update(($item_id) ? 'deleted' : 'delete_failed');
|
||||
$result[] = $DR->get();
|
||||
|
||||
if($relay && $item_id) {
|
||||
logger('process_delivery: invoking relay');
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
|
||||
Master::Summon([ 'Notifier', 'relay', intval($item_id) ]);
|
||||
$DR->update('relayed');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
@@ -1662,7 +1715,7 @@ class Libzot {
|
||||
|
||||
if($relay && $item_id) {
|
||||
logger('Invoking relay');
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
|
||||
Master::Summon([ 'Notifier', 'relay', intval($item_id) ]);
|
||||
$DR->addto_update('relayed');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
@@ -1676,6 +1729,98 @@ class Libzot {
|
||||
return $result;
|
||||
}
|
||||
|
||||
static public function fetch_conversation($channel,$mid) {
|
||||
|
||||
// Use Zotfinger to create a signed request
|
||||
|
||||
$a = Zotfinger::exec($mid,$channel);
|
||||
|
||||
logger('received conversation: ' . print_r($a,true), LOGGER_DATA);
|
||||
|
||||
if($a['data']['type'] !== 'OrderedCollection') {
|
||||
return;
|
||||
}
|
||||
|
||||
if(! intval($a['data']['totalItems'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ret = [];
|
||||
|
||||
foreach($a['data']['orderedItems'] as $activity) {
|
||||
|
||||
$AS = new ActivityStreams($activity);
|
||||
if(! $AS->is_valid()) {
|
||||
logger('FOF Activity rejected: ' . print_r($activity,true));
|
||||
continue;
|
||||
}
|
||||
$arr = Activity::decode_note($AS);
|
||||
|
||||
logger($AS->debug());
|
||||
|
||||
|
||||
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$y = import_author_xchan([ 'url' => $AS->actor['id'] ]);
|
||||
if($y) {
|
||||
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
}
|
||||
if(! $r) {
|
||||
logger('FOF Activity: no actor');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if($AS->obj['actor'] && $AS->obj['actor']['id'] && $AS->obj['actor']['id'] !== $AS->actor['id']) {
|
||||
$y = import_author_xchan([ 'url' => $AS->obj['actor']['id'] ]);
|
||||
if(! $y) {
|
||||
logger('FOF Activity: no object actor');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($r) {
|
||||
$arr['author_xchan'] = $r[0]['hubloc_hash'];
|
||||
}
|
||||
|
||||
$s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
|
||||
dbesc($a['signature']['signer'])
|
||||
);
|
||||
|
||||
if($s) {
|
||||
$arr['owner_xchan'] = $s[0]['hubloc_hash'];
|
||||
}
|
||||
else {
|
||||
$arr['owner_xchan'] = $a['signature']['signer'];
|
||||
}
|
||||
|
||||
// @fixme - spoofable
|
||||
if($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
if($AS->data['signed_data']) {
|
||||
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
|
||||
}
|
||||
|
||||
logger('FOF Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
$result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_hash'] ],false,false,true);
|
||||
if ($result) {
|
||||
$ret = array_merge($ret, $result);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove community tag.
|
||||
*
|
||||
@@ -1900,7 +2045,7 @@ class Libzot {
|
||||
|
||||
foreach($deliveries as $d) {
|
||||
|
||||
$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,$arr['mid']);
|
||||
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
|
||||
|
||||
$r = q("select * from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($d['hash'])
|
||||
@@ -2112,7 +2257,8 @@ class Libzot {
|
||||
if(intval($channel['channel_removed']) && $hub['hubloc_url'] === z_root())
|
||||
$hub['hubloc_deleted'] = 1;
|
||||
|
||||
$ret[] = [
|
||||
|
||||
$z = [
|
||||
'host' => $hub['hubloc_host'],
|
||||
'address' => $hub['hubloc_addr'],
|
||||
'id_url' => $hub['hubloc_id_url'],
|
||||
@@ -2120,10 +2266,25 @@ class Libzot {
|
||||
'url' => $hub['hubloc_url'],
|
||||
'url_sig' => $hub['hubloc_url_sig'],
|
||||
'site_id' => $hub['hubloc_site_id'],
|
||||
'callback' => $hub['hubloc_callback'],
|
||||
'callback' => $hub['hubloc_url'] . '/zot',
|
||||
'sitekey' => $hub['hubloc_sitekey'],
|
||||
'deleted' => (intval($hub['hubloc_deleted']) ? true : false)
|
||||
];
|
||||
|
||||
// version compatibility tweaks
|
||||
|
||||
if(! strpos($z['url_sig'],'.')) {
|
||||
$z['url_sig'] = 'sha256.' . $z['url_sig'];
|
||||
}
|
||||
|
||||
if(! $z['id_url']) {
|
||||
$z['id_url'] = $z['url'] . '/channel/' . substr($z['address'],0,strpos($z['address'],'@'));
|
||||
}
|
||||
if(! $z['site_id']) {
|
||||
$z['site_id'] = Libzot::make_xchan_hash($z['url'],$z['sitekey']);
|
||||
}
|
||||
|
||||
$ret[] = $z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2331,6 +2492,10 @@ class Libzot {
|
||||
// we may only end up with one; which results in posts with no author name or photo and are a bit
|
||||
// of a hassle to repair. If either or both are missing, do a full discovery probe.
|
||||
|
||||
if(! array_key_exists('id',$x)) {
|
||||
return import_author_activitypub($x);
|
||||
}
|
||||
|
||||
$hash = self::make_xchan_hash($x['id'],$x['key']);
|
||||
|
||||
$desturl = $x['url'];
|
||||
@@ -2502,7 +2667,7 @@ class Libzot {
|
||||
}
|
||||
else {
|
||||
// check if it has characteristics of a public forum based on custom permissions.
|
||||
$m = \Zotlabs\Access\Permissions::FilledAutoperms($e['channel_id']);
|
||||
$m = Permissions::FilledAutoperms($e['channel_id']);
|
||||
if($m) {
|
||||
foreach($m as $k => $v) {
|
||||
if($k == 'tag_deliver' && intval($v) == 1)
|
||||
@@ -2584,13 +2749,13 @@ class Libzot {
|
||||
];
|
||||
|
||||
$ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom');
|
||||
|
||||
$ret['protocols'] = [ 'zot6' ];
|
||||
$ret['searchable'] = $searchable;
|
||||
$ret['adult_content'] = $adult_channel;
|
||||
$ret['public_forum'] = $public_forum;
|
||||
|
||||
$ret['comments'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($e['channel_id'],'post_comments'));
|
||||
$ret['mail'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($e['channel_id'],'post_mail'));
|
||||
$ret['comments'] = map_scope(PermissionLimits::Get($e['channel_id'],'post_comments'));
|
||||
$ret['mail'] = map_scope(PermissionLimits::Get($e['channel_id'],'post_mail'));
|
||||
|
||||
if($deleted)
|
||||
$ret['deleted'] = $deleted;
|
||||
|
||||
@@ -57,6 +57,7 @@ class PConfig {
|
||||
\App::$config[$uid][$c]['config_loaded'] = true;
|
||||
}
|
||||
\App::$config[$uid][$c][$k] = $rr['v'];
|
||||
\App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +114,7 @@ class PConfig {
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
static public function Set($uid, $family, $key, $value) {
|
||||
static public function Set($uid, $family, $key, $value, $updated=NULL) {
|
||||
|
||||
// this catches subtle errors where this function has been called
|
||||
// with local_channel() when not logged in (which returns false)
|
||||
@@ -130,29 +131,74 @@ class PConfig {
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if (! $updated) {
|
||||
$updated = datetime_convert();
|
||||
}
|
||||
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) > $updated) {
|
||||
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
|
||||
return self::Get($uid,$family,$key);
|
||||
} else {
|
||||
self::Delete($uid,'hz_delpconfig',$hash);
|
||||
}
|
||||
}
|
||||
|
||||
if(self::Get($uid, $family, $key) === false) {
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
\App::$config[$uid] = array();
|
||||
if(! array_key_exists($family, \App::$config[$uid]))
|
||||
\App::$config[$uid][$family] = array();
|
||||
|
||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
|
||||
|
||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
dbesc($dbvalue),
|
||||
dbesc($updated)
|
||||
);
|
||||
|
||||
// There is a possible race condition if another process happens
|
||||
// to insert something after this thread has Loaded and now. We should
|
||||
// at least make a note of it if it happens.
|
||||
|
||||
if (!$ret) {
|
||||
logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR);
|
||||
}
|
||||
|
||||
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
|
||||
}
|
||||
else {
|
||||
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
|
||||
|
||||
$ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
if ($new) {
|
||||
|
||||
// @NOTE There is still a possible race condition under limited circumstances
|
||||
// where a value will be updated by another thread with more current data than
|
||||
// we have. At this point there is no easy way to test for it, so we update
|
||||
// and hope for the best.
|
||||
|
||||
$ret = q("UPDATE pconfig SET v = '%s', updated = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
dbesc($updated),
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
|
||||
} else {
|
||||
logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR);
|
||||
return self::Get($uid, $family, $key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// keep a separate copy for all variables which were
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel clones.
|
||||
@@ -163,7 +209,11 @@ class PConfig {
|
||||
\App::$config[$uid]['transient'][$family] = array();
|
||||
|
||||
\App::$config[$uid][$family][$key] = $value;
|
||||
\App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
|
||||
if ($new) {
|
||||
\App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
\App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
|
||||
}
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
@@ -186,18 +236,29 @@ class PConfig {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($uid, $family, $key) {
|
||||
static public function Delete($uid, $family, $key, $updated = NULL) {
|
||||
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
|
||||
$updated = ($updated) ? $updated : datetime_convert();
|
||||
|
||||
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
|
||||
|
||||
if (! $newer) {
|
||||
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($uid,\App::$config)
|
||||
&& is_array(\App::$config['uid'])
|
||||
&& array_key_exists($family,\App::$config['uid'])
|
||||
&& array_key_exists($key, \App::$config[$uid][$family]))
|
||||
if (isset(\App::$config[$uid][$family][$key])) {
|
||||
unset(\App::$config[$uid][$family][$key]);
|
||||
}
|
||||
|
||||
if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) {
|
||||
unset(\App::$config[$uid][$family]['pcfgud:'.$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
intval($uid),
|
||||
@@ -205,6 +266,22 @@ class PConfig {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if ($family != 'hz_delpconfig') {
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
set_pconfig($uid,'hz_delpconfig',$hash,$updated);
|
||||
}
|
||||
|
||||
// Synchronize delete with clones.
|
||||
|
||||
if(! array_key_exists('transient', \App::$config[$uid]))
|
||||
\App::$config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, \App::$config[$uid]['transient']))
|
||||
\App::$config[$uid]['transient'][$family] = array();
|
||||
|
||||
if ($new) {
|
||||
\App::$config[$uid]['transient'][$family]['pcfgdel:'.$key] = $updated;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,11 +109,9 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
|
||||
// available channels, primary and clones
|
||||
$channels = array();
|
||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0 and channel_system = 0");
|
||||
$r = q("SELECT COUNT(*) AS total FROM channel WHERE channel_removed = 0 and channel_system = 0");
|
||||
if ($r) {
|
||||
$channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']);
|
||||
$channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']);
|
||||
$channels['clones'] = array('label' => t('Clones'), 'val' => $r[0]['clones']);
|
||||
}
|
||||
|
||||
// We can do better, but this is a quick queue status
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -80,6 +80,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']) : '');
|
||||
|
||||
@@ -331,6 +336,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.
|
||||
|
||||
|
||||
@@ -375,8 +375,7 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
$o .= '</noscript>';
|
||||
|
||||
if ($items[0]['title'])
|
||||
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
|
||||
\App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']);
|
||||
|
||||
$o .= conversation($items, 'display', $update, 'client');
|
||||
}
|
||||
|
||||
@@ -127,6 +127,15 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
// prevent incompatible osada or zap data from horking your database
|
||||
|
||||
if(array_path_exists('compatibility/codebase',$data)) {
|
||||
notice('Data export format is not compatible with this software');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if($moving)
|
||||
$seize = 1;
|
||||
|
||||
|
||||
@@ -50,7 +50,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;
|
||||
|
||||
@@ -249,6 +249,9 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if(! $observer)
|
||||
killme();
|
||||
|
||||
// this is used to like an item or comment
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
@@ -228,8 +228,13 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
|
||||
$header = $result['header'];
|
||||
$body = $result['body'];
|
||||
|
||||
// Check codepage in HTTP headers or HTML if not exist
|
||||
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
|
||||
if(empty($cp))
|
||||
$cp = (preg_match('/meta.+content=["|\']text\/html; charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
|
||||
$body = mb_convert_encoding($body, 'UTF-8', (preg_match('/meta.+content=["|\']text\/html;\s+charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'UTF-8'));
|
||||
$body = mb_convert_encoding($body, 'UTF-8', $cp);
|
||||
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
@@ -265,20 +270,43 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
|
||||
|
||||
switch (strtolower($attr["name"])) {
|
||||
case 'generator':
|
||||
$siteinfo['generator'] = $attr['content'];
|
||||
break;
|
||||
case "fulltitle":
|
||||
$siteinfo["title"] = $attr["content"];
|
||||
$siteinfo["title"] = trim($attr["content"]);
|
||||
break;
|
||||
case "description":
|
||||
$siteinfo["text"] = $attr["content"];
|
||||
$siteinfo["text"] = trim($attr["content"]);
|
||||
break;
|
||||
case "thumbnail":
|
||||
$siteinfo["image"] = $attr["content"];
|
||||
break;
|
||||
case "twitter:image":
|
||||
$siteinfo["image"] = $attr["content"];
|
||||
break;
|
||||
case "twitter:image:src":
|
||||
$siteinfo["image"] = $attr["content"];
|
||||
break;
|
||||
case "twitter:card":
|
||||
if (($siteinfo["type"] == "") || ($attr["content"] == "photo")) {
|
||||
$siteinfo["type"] = $attr["content"];
|
||||
}
|
||||
break;
|
||||
case "twitter:description":
|
||||
$siteinfo["text"] = trim($attr["content"]);
|
||||
break;
|
||||
case "twitter:title":
|
||||
$siteinfo["title"] = trim($attr["content"]);
|
||||
break;
|
||||
case "dc.title":
|
||||
$siteinfo["title"] = $attr["content"];
|
||||
$siteinfo["title"] = trim($attr["content"]);
|
||||
break;
|
||||
case "dc.description":
|
||||
$siteinfo["text"] = $attr["content"];
|
||||
$siteinfo["text"] = trim($attr["content"]);
|
||||
break;
|
||||
case "keywords":
|
||||
$keywords = explode(",", $attr["content"]);
|
||||
break;
|
||||
case "news_keywords":
|
||||
$keywords = explode(",", $attr["content"]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +258,10 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
elseif($pf && $unseen && $nouveau) {
|
||||
|
||||
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
|
||||
if(! ($vnotify & VNOTIFY_LIKE))
|
||||
$likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
// This is for nouveau view public forum cid queries (if a forum notification is clicked)
|
||||
$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
|
||||
intval(local_channel()),
|
||||
@@ -269,7 +273,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
if($p_str)
|
||||
$p_sql = " OR item.parent IN ( $p_str ) ";
|
||||
|
||||
$sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 ";
|
||||
$sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 $likes_sql ";
|
||||
}
|
||||
else {
|
||||
// This is for threaded view cid queries (e.g. if a forum is selected from the forum filter)
|
||||
|
||||
@@ -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']))) {
|
||||
@@ -145,7 +145,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
$canadd = true;
|
||||
if($r && ($limit !== false)) {
|
||||
$channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit);
|
||||
if ($r[0]['total'] >= $limit) {
|
||||
if ($r[0]['total'] > $limit) {
|
||||
$canadd = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
dbesc($res)
|
||||
);
|
||||
if($r) {
|
||||
$sql_extra = "and item.id = " . intval($r[0]['iid']) . " ";
|
||||
$sql_extra .= " and item.id = " . intval($r[0]['iid']) . " ";
|
||||
}
|
||||
else {
|
||||
return $ret;
|
||||
@@ -194,6 +194,9 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
intval(ITEM_TYPE_CARD)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
@@ -255,7 +258,6 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
if(! $channel)
|
||||
return $ret;
|
||||
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_pages'))
|
||||
return $ret;
|
||||
|
||||
@@ -265,7 +267,7 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
dbesc($res)
|
||||
);
|
||||
if($r) {
|
||||
$sql_extra = "and item.id = " . intval($r[0]['iid']) . " ";
|
||||
$sql_extra .= " and item.id = " . intval($r[0]['iid']) . " ";
|
||||
}
|
||||
else {
|
||||
return $ret;
|
||||
@@ -278,6 +280,9 @@ class Oep extends \Zotlabs\Web\Controller {
|
||||
intval(ITEM_TYPE_ARTICLE)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,7) and item.item_deleted = 0
|
||||
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
|
||||
and item.item_blocked = 0 ";
|
||||
|
||||
@@ -31,15 +31,17 @@ class Owa extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where hubloc_addr = '%s' ",
|
||||
dbesc(str_replace('acct:','',$keyId))
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
|
||||
dbesc(str_replace('acct:','',$keyId)),
|
||||
dbesc($keyId)
|
||||
);
|
||||
if(! $r) {
|
||||
$found = discover_by_webbie(str_replace('acct:','',$keyId));
|
||||
if($found) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where hubloc_addr = '%s' ",
|
||||
dbesc(str_replace('acct:','',$keyId))
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
|
||||
dbesc(str_replace('acct:','',$keyId)),
|
||||
dbesc($keyId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ class Pconfig extends \Zotlabs\Web\Controller {
|
||||
$k = trim(escape_tags($_POST['k']));
|
||||
$v = trim($_POST['v']);
|
||||
$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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(in_array(argv(2),$this->disallowed_pconfig())) {
|
||||
notice( t('This setting requires special processing and editing has been blocked.') . EOL);
|
||||
|
||||
@@ -4,13 +4,12 @@ namespace Zotlabs\Module;
|
||||
require_once('include/security.php');
|
||||
require_once('include/attach.php');
|
||||
require_once('include/photo/photo_driver.php');
|
||||
require_once('include/photos.php');
|
||||
|
||||
|
||||
class Photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
$prvcachecontrol = false;
|
||||
$streaming = null;
|
||||
$channel = null;
|
||||
@@ -32,26 +31,26 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$observer_xchan = get_observer_hash();
|
||||
$ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
|
||||
$default = z_root() . '/' . get_default_profile_photo();
|
||||
|
||||
if(isset($type)) {
|
||||
|
||||
/**
|
||||
* Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
$default = get_default_profile_photo();
|
||||
|
||||
if($type === 'profile') {
|
||||
switch($res) {
|
||||
|
||||
case 'm':
|
||||
$resolution = 5;
|
||||
$default = z_root() . '/' . get_default_profile_photo(80);
|
||||
$default = get_default_profile_photo(80);
|
||||
break;
|
||||
case 's':
|
||||
$resolution = 6;
|
||||
$default = z_root() . '/' . get_default_profile_photo(48);
|
||||
$default = get_default_profile_photo(48);
|
||||
break;
|
||||
case 'l':
|
||||
default:
|
||||
@@ -60,6 +59,8 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$modified = filemtime($default);
|
||||
$default = z_root() . '/' . $default;
|
||||
$uid = $person;
|
||||
|
||||
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
|
||||
@@ -78,17 +79,18 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
intval(PHOTO_PROFILE)
|
||||
);
|
||||
if($r) {
|
||||
$modified = strtotime($r[0]['edited'] . "Z");
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
$mimetype = $r[0]['mimetype'];
|
||||
}
|
||||
if(intval($r[0]['os_storage']))
|
||||
$data = file_get_contents($data);
|
||||
}
|
||||
|
||||
if(! $data) {
|
||||
$data = fetch_image_from_url($default,$mimetype);
|
||||
}
|
||||
if(! $mimetype) {
|
||||
$mimetype = 'image/png';
|
||||
$x = z_fetch_url($default,true,0,[ 'novalidate' => true ]);
|
||||
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
|
||||
$mimetype = 'image/png';
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -124,9 +126,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$photo = substr($photo,0,-2);
|
||||
// If viewing on a high-res screen, attempt to serve a higher resolution image:
|
||||
if ($resolution == 2 && ($cookie_value > 1))
|
||||
{
|
||||
$resolution = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("SELECT uid, photo_usage FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
@@ -163,10 +163,13 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($exists && $allowed) {
|
||||
$data = dbunescbin($e[0]['content']);
|
||||
$filesize = $e[0]['filesize'];
|
||||
$mimetype = $e[0]['mimetype'];
|
||||
if(intval($e[0]['os_storage'])) {
|
||||
$modified = strtotime($e[0]['edited'] . 'Z');
|
||||
if(intval($e[0]['os_storage']))
|
||||
$streaming = $data;
|
||||
}
|
||||
if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '')
|
||||
$prvcachecontrol = true;
|
||||
}
|
||||
else {
|
||||
if(! $allowed) {
|
||||
@@ -177,27 +180,40 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
http_status_exit(404,'not found');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
header_remove('Pragma');
|
||||
|
||||
if($ismodified === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
|
||||
header_remove('Expires');
|
||||
header_remove('Cache-Control');
|
||||
header_remove('Set-Cookie');
|
||||
http_status_exit(304,'not modified');
|
||||
}
|
||||
|
||||
if(! isset($data)) {
|
||||
if(isset($resolution)) {
|
||||
switch($resolution) {
|
||||
|
||||
case 4:
|
||||
$data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(),$mimetype);
|
||||
$default = get_default_profile_photo();
|
||||
break;
|
||||
case 5:
|
||||
$data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(80),$mimetype);
|
||||
$default = get_default_profile_photo(80);
|
||||
break;
|
||||
case 6:
|
||||
$data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(48),$mimetype);
|
||||
$default = get_default_profile_photo(48);
|
||||
break;
|
||||
default:
|
||||
killme();
|
||||
// NOTREACHED
|
||||
break;
|
||||
}
|
||||
$x = z_fetch_url(z_root() . '/' . $default,true,0,[ 'novalidate' => true ]);
|
||||
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
|
||||
$mimetype = 'image/png';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,15 +226,14 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// @FIXME Seems never invoked
|
||||
// Writing in cachefile
|
||||
if (isset($cachefile) && $cachefile != '')
|
||||
if (isset($cachefile) && $cachefile != '') {
|
||||
file_put_contents($cachefile, $data);
|
||||
|
||||
if(function_exists('header_remove')) {
|
||||
header_remove('Pragma');
|
||||
header_remove('pragma');
|
||||
$modified = filemtime($cachefile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
header("Content-type: " . $mimetype);
|
||||
|
||||
if($prvcachecontrol) {
|
||||
@@ -240,15 +255,16 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
// This has performance considerations but we highly recommend you
|
||||
// leave it alone.
|
||||
|
||||
$cache = get_config('system','photo_cache_time');
|
||||
if(! $cache)
|
||||
$cache = (3600 * 24); // 1 day
|
||||
|
||||
$cache = get_config('system','photo_cache_time', 86400); // 1 day by default
|
||||
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT");
|
||||
header("Cache-Control: max-age=" . $cache);
|
||||
|
||||
}
|
||||
|
||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT");
|
||||
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
|
||||
|
||||
// If it's a file resource, stream it.
|
||||
|
||||
if($streaming && $channel) {
|
||||
|
||||
@@ -263,7 +263,8 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$fsize = strlen($data);
|
||||
}
|
||||
|
||||
$x = q("update photo set content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0",
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
@@ -277,9 +278,13 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
|
||||
$x = q("update photo set content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
|
||||
dbescbin($ph->imageString()),
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
dbesc($resource_id),
|
||||
@@ -292,9 +297,13 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
|
||||
$x = q("update photo set content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
|
||||
dbescbin($ph->imageString()),
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
dbesc($resource_id),
|
||||
@@ -307,9 +316,13 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
$data = $ph->imageString();
|
||||
$fsize = strlen($data);
|
||||
|
||||
$x = q("update photo set content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
|
||||
dbescbin($ph->imageString()),
|
||||
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
|
||||
dbesc(datetime_convert()),
|
||||
dbescbin($data),
|
||||
intval($fsize),
|
||||
intval($height),
|
||||
intval($width),
|
||||
dbesc($resource_id),
|
||||
@@ -612,9 +625,9 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
|
||||
nav_set_selected('Photos');
|
||||
|
||||
$o = '<script src="library/blueimp_upload/js/vendor/jquery.ui.widget.js"></script>
|
||||
<script src="library/blueimp_upload/js/jquery.iframe-transport.js"></script>
|
||||
<script src="library/blueimp_upload/js/jquery.fileupload.js"></script>';
|
||||
$o = '<script src="vendor/blueimp/jquery-file-upload/js/vendor/jquery.ui.widget.js"></script>
|
||||
<script src="vendor/blueimp/jquery-file-upload/js/jquery.iframe-transport.js"></script>
|
||||
<script src="vendor/blueimp/jquery-file-upload/js/jquery.fileupload.js"></script>';
|
||||
|
||||
|
||||
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
|
||||
@@ -975,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)
|
||||
@@ -1109,6 +1122,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$comments = '';
|
||||
if(! $r) {
|
||||
if($observer && ($can_post || $can_comment)) {
|
||||
$feature_auto_save_draft = ((feature_enabled($owner_uid, 'auto_save_draft')) ? "true" : "false");
|
||||
$commentbox = replace_macros($cmnt_tpl,array(
|
||||
'$return_path' => '',
|
||||
'$mode' => 'photos',
|
||||
@@ -1124,7 +1138,8 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
'$submit' => t('Submit'),
|
||||
'$preview' => t('Preview'),
|
||||
'$ww' => '',
|
||||
'$feature_encrypt' => false
|
||||
'$feature_encrypt' => false,
|
||||
'$auto_save_draft' => $feature_auto_save_draft
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1257,8 +1272,14 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
if(feature_enabled($owner_uid,'dislike'))
|
||||
$response_verbs[] = 'dislike';
|
||||
|
||||
|
||||
$responses = get_responses($conv_responses,$response_verbs,'',$link_item);
|
||||
|
||||
$hookdata = [
|
||||
'onclick' => '$.colorbox({href: \'' . $photo['href'] . '\'}); return false;',
|
||||
'raw_photo' => $ph[0],
|
||||
'nickname' => \App::$data['channel']['channel_address']
|
||||
];
|
||||
call_hooks('photo_view_filter', $hookdata);
|
||||
|
||||
$photo_tpl = get_markup_template('photo_view.tpl');
|
||||
$o .= replace_macros($photo_tpl, array(
|
||||
@@ -1296,6 +1317,7 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
'$comments' => $comments,
|
||||
'$commentbox' => $commentbox,
|
||||
'$paginate' => $paginate,
|
||||
'$onclick' => $hookdata['onclick']
|
||||
));
|
||||
|
||||
\App::$data['photo_html'] = $o;
|
||||
|
||||
@@ -330,6 +330,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$notifs[] = array(
|
||||
'notify_link' => z_root() . '/mail/' . $zz['id'],
|
||||
'name' => $zz['xchan_name'],
|
||||
'addr' => $zz['xchan_addr'],
|
||||
'url' => $zz['xchan_url'],
|
||||
'photo' => $zz['xchan_photo_s'],
|
||||
'when' => relative_date($zz['created']),
|
||||
@@ -346,6 +347,10 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) {
|
||||
$result = array();
|
||||
|
||||
if(argv(1) === 'home') {
|
||||
$sql_extra .= ' and item_wall = 1 ';
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND item_unseen = 1
|
||||
@@ -361,8 +366,6 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
foreach($r as $item) {
|
||||
if((argv(1) === 'home') && (! intval($item['item_wall'])))
|
||||
continue;
|
||||
$result[] = \Zotlabs\Lib\Enotify::format($item);
|
||||
}
|
||||
}
|
||||
@@ -383,6 +386,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$result[] = array(
|
||||
'notify_link' => z_root() . '/connections/ifpending',
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => relative_date($rr['abook_created']),
|
||||
@@ -407,6 +411,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$result[] = array(
|
||||
'notify_link' => z_root() . '/admin/accounts',
|
||||
'name' => $rr['account_email'],
|
||||
'addr' => $rr['account_email'],
|
||||
'url' => '',
|
||||
'photo' => z_root() . '/' . get_default_profile_photo(48),
|
||||
'when' => relative_date($rr['account_created']),
|
||||
@@ -444,6 +449,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$result[] = array(
|
||||
'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => $when,
|
||||
@@ -460,7 +466,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
if(argc() > 1 && (argv(1) === 'files')) {
|
||||
$result = array();
|
||||
|
||||
$r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s FROM item
|
||||
$r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item
|
||||
LEFT JOIN xchan on author_xchan = xchan_hash
|
||||
WHERE item.verb = '%s'
|
||||
AND item.obj_type = '%s'
|
||||
@@ -477,6 +483,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$result[] = array(
|
||||
'notify_link' => z_root() . '/sharedwithme',
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
'photo' => $rr['xchan_photo_s'],
|
||||
'when' => relative_date($rr['created']),
|
||||
@@ -635,7 +642,6 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$forums = get_forum_channels(local_channel());
|
||||
|
||||
if($forums) {
|
||||
$perms_sql = item_permissions_sql(local_channel());
|
||||
$item_normal = item_normal();
|
||||
$fcount = count($forums);
|
||||
$forums['total'] = 0;
|
||||
@@ -644,14 +650,14 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
|
||||
intval(local_channel()),
|
||||
intval(TERM_FORUM),
|
||||
dbesc($forums[$x]['xchan_hash'])
|
||||
dbesc($forums[$x]['xchan_name'])
|
||||
);
|
||||
|
||||
$p_str = ids_to_querystr($p, 'parent');
|
||||
$p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
|
||||
|
||||
$r = q("select sum(item_unseen) as unseen from item
|
||||
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $perms_sql $item_normal",
|
||||
$r = q("select count(id) as unseen from item
|
||||
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $item_normal $sql_extra",
|
||||
intval(local_channel()),
|
||||
dbesc($forums[$x]['xchan_hash']),
|
||||
dbesc($forums[$x]['xchan_hash'])
|
||||
@@ -659,6 +665,7 @@ class Ping extends \Zotlabs\Web\Controller {
|
||||
if($r[0]['unseen']) {
|
||||
$forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']);
|
||||
$forums[$x]['name'] = $forums[$x]['xchan_name'];
|
||||
$forums[$x]['addr'] = $forums[$x]['xchan_addr'];
|
||||
$forums[$x]['url'] = $forums[$x]['xchan_url'];
|
||||
$forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
|
||||
$forums[$x]['unseen'] = $r[0]['unseen'];
|
||||
|
||||
@@ -6,7 +6,7 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
if(x($_REQUEST,'search'))
|
||||
\App::$data['search'] = $_REQUEST['search'];
|
||||
\App::$data['search'] = escape_tags($_REQUEST['search']);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
if(x(\App::$data,'search'))
|
||||
$search = trim(\App::$data['search']);
|
||||
else
|
||||
$search = ((x($_GET,'search')) ? trim(rawurldecode($_GET['search'])) : '');
|
||||
$search = ((x($_GET,'search')) ? trim(escape_tags(rawurldecode($_GET['search']))) : '');
|
||||
|
||||
$tag = false;
|
||||
if(x($_GET,'tag')) {
|
||||
$tag = true;
|
||||
$search = ((x($_GET,'tag')) ? trim(rawurldecode($_GET['tag'])) : '');
|
||||
$search = ((x($_GET,'tag')) ? trim(escape_tags(rawurldecode($_GET['tag']))) : '');
|
||||
}
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
@@ -227,9 +227,9 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($tag)
|
||||
$o .= '<h2>' . sprintf( t('Items tagged with: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
|
||||
$o .= '<h2>' . sprintf( t('Items tagged with: %s'),$search) . '</h2>';
|
||||
else
|
||||
$o .= '<h2>' . sprintf( t('Search results for: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
|
||||
$o .= '<h2>' . sprintf( t('Search results for: %s'),$search) . '</h2>';
|
||||
|
||||
$o .= conversation($items,'search',$update,'client');
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -19,7 +19,7 @@ class Zot extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
$zot = new ZotProtocol\Receiver(new ZotProtocol\Zot6Handler());
|
||||
json_return_and_die($zot->run(),'application/x-zot+jzon');
|
||||
json_return_and_die($zot->run(),'application/x-zot+json');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
26
Zotlabs/Update/_1225.php
Normal file
26
Zotlabs/Update/_1225.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1225 {
|
||||
|
||||
function run() {
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = q("ALTER TABLE pconfig ADD updated timestamp NOT NULL DEFAULT '0001-01-01 00:00:00' ");
|
||||
$r2 = q("create index \"pconfig_updated_idx\" on pconfig (\"updated\")");
|
||||
|
||||
$r = ($r1 && $r2);
|
||||
}
|
||||
else {
|
||||
$r = q("ALTER TABLE `pconfig` ADD `updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' ,
|
||||
ADD INDEX `pconfig_updated` (`updated`)");
|
||||
}
|
||||
|
||||
if($r)
|
||||
return UPDATE_SUCCESS;
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class Notifications {
|
||||
],
|
||||
'filter' => [
|
||||
'posts_label' => t('Show new posts only'),
|
||||
'name_label' => t('Filter by name')
|
||||
'name_label' => t('Filter by name or address')
|
||||
]
|
||||
];
|
||||
|
||||
@@ -43,7 +43,7 @@ class Notifications {
|
||||
],
|
||||
'filter' => [
|
||||
'posts_label' => t('Show new posts only'),
|
||||
'name_label' => t('Filter by name')
|
||||
'name_label' => t('Filter by name or address')
|
||||
]
|
||||
];
|
||||
|
||||
@@ -119,7 +119,7 @@ class Notifications {
|
||||
'label' => t('Forums'),
|
||||
'title' => t('Forums'),
|
||||
'filter' => [
|
||||
'name_label' => t('Filter by name')
|
||||
'name_label' => t('Filter by name or address')
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -150,7 +150,7 @@ class Notifications {
|
||||
],
|
||||
'filter' => [
|
||||
'posts_label' => t('Show new posts only'),
|
||||
'name_label' => t('Filter by name')
|
||||
'name_label' => t('Filter by name or address')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ class Wiki_list {
|
||||
|
||||
function widget($arr) {
|
||||
|
||||
if(argc() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = channelx_by_n(\App::$profile_uid);
|
||||
|
||||
$wikis = \Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash());
|
||||
|
||||
5
boot.php
5
boot.php
@@ -50,11 +50,10 @@ require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '3.8.2' );
|
||||
define ( 'STD_VERSION', '3.8.9' );
|
||||
define ( 'ZOT_REVISION', '6.0a' );
|
||||
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1224 );
|
||||
define ( 'DB_UPDATE_VERSION', 1225 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@
|
||||
"lukasreschke/id3parser": "^0.0.1",
|
||||
"smarty/smarty": "~3.1",
|
||||
"ramsey/uuid": "^3.8",
|
||||
"twbs/bootstrap": "4.1.3"
|
||||
"twbs/bootstrap": "4.1.3",
|
||||
"blueimp/jquery-file-upload": "^9.25",
|
||||
"desandro/imagesloaded": "^4.1"
|
||||
},
|
||||
"require-dev" : {
|
||||
"phpunit/phpunit" : "@stable",
|
||||
|
||||
341
composer.lock
generated
341
composer.lock
generated
@@ -4,8 +4,63 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "b7862124a9afe837c7eef8ee66f02ff4",
|
||||
"content-hash": "fe5e71d7076eeddf1c174be4a5c052dd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "blueimp/jquery-file-upload",
|
||||
"version": "v9.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vkhramtsov/jQuery-File-Upload.git",
|
||||
"reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/ff5accfe2e5c4a522777faa980a90cf86a636d1d",
|
||||
"reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"server/php/UploadHandler.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"homepage": "https://blueimp.net"
|
||||
}
|
||||
],
|
||||
"description": "File Upload widget for jQuery.",
|
||||
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
|
||||
"keywords": [
|
||||
"bootstrap",
|
||||
"chunk",
|
||||
"cross-domain",
|
||||
"cross-site",
|
||||
"drag",
|
||||
"drop",
|
||||
"file",
|
||||
"gae",
|
||||
"go",
|
||||
"jquery",
|
||||
"multiple",
|
||||
"php",
|
||||
"preview",
|
||||
"progress",
|
||||
"python",
|
||||
"resume",
|
||||
"selection",
|
||||
"upload",
|
||||
"widget"
|
||||
],
|
||||
"time": "2018-11-13T05:41:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bshaffer/oauth2-server-php",
|
||||
"version": "v1.10.0",
|
||||
@@ -108,6 +163,45 @@
|
||||
"description": "Internationalization library powered by CLDR data.",
|
||||
"time": "2017-12-29T00:13:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "desandro/imagesloaded",
|
||||
"version": "v4.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/desandro/imagesloaded.git",
|
||||
"reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/desandro/imagesloaded/zipball/67c4e57453120935180c45c6820e7d3fbd2ea1f9",
|
||||
"reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "component",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David DeSandro",
|
||||
"homepage": "http://desandro.com/",
|
||||
"role": "developer"
|
||||
}
|
||||
],
|
||||
"description": "JavaScript is all like _You images done yet or what?_",
|
||||
"homepage": "http://imagesloaded.desandro.com",
|
||||
"keywords": [
|
||||
"dom",
|
||||
"images",
|
||||
"javascript",
|
||||
"jquery-plugin",
|
||||
"library",
|
||||
"loaded",
|
||||
"ui"
|
||||
],
|
||||
"time": "2018-01-02T16:53:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.10.0",
|
||||
@@ -157,16 +251,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.7.0",
|
||||
"version": "4.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "76c076483cef89860d32a3fd25312f5a42848a8c"
|
||||
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/76c076483cef89860d32a3fd25312f5a42848a8c",
|
||||
"reference": "76c076483cef89860d32a3fd25312f5a42848a8c",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d",
|
||||
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -185,7 +279,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.8-dev"
|
||||
"dev-master": "4.9-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -198,17 +292,17 @@
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "http://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Nick Cernis",
|
||||
"email": "nick@cern.is",
|
||||
"homepage": "http://modernnerd.net",
|
||||
"role": "Original Author"
|
||||
},
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "An HTML-to-markdown conversion helper for PHP",
|
||||
@@ -217,7 +311,7 @@
|
||||
"html",
|
||||
"markdown"
|
||||
],
|
||||
"time": "2018-05-19T23:47:12+00:00"
|
||||
"time": "2018-09-18T12:18:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lukasreschke/id3parser",
|
||||
@@ -391,16 +485,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
||||
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -434,7 +528,7 @@
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2016-10-10T12:19:37+00:00"
|
||||
"time": "2018-11-20T15:27:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
@@ -520,16 +614,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sabre/dav",
|
||||
"version": "3.2.2",
|
||||
"version": "3.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/dav.git",
|
||||
"reference": "e987775e619728f12205606c9cc3ee565ffb1516"
|
||||
"reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/dav/zipball/e987775e619728f12205606c9cc3ee565ffb1516",
|
||||
"reference": "e987775e619728f12205606c9cc3ee565ffb1516",
|
||||
"url": "https://api.github.com/repos/sabre-io/dav/zipball/a9780ce4f35560ecbd0af524ad32d9d2c8954b80",
|
||||
"reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -599,7 +693,7 @@
|
||||
"framework",
|
||||
"iCalendar"
|
||||
],
|
||||
"time": "2017-02-15T03:06:08+00:00"
|
||||
"time": "2018-10-19T09:58:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/event",
|
||||
@@ -1002,16 +1096,16 @@
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v3.1.32",
|
||||
"version": "v3.1.33",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "ac9d4b587e5bf53381e21881820a9830765cb459"
|
||||
"reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/ac9d4b587e5bf53381e21881820a9830765cb459",
|
||||
"reference": "ac9d4b587e5bf53381e21881820a9830765cb459",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f",
|
||||
"reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1051,11 +1145,11 @@
|
||||
"keywords": [
|
||||
"templating"
|
||||
],
|
||||
"time": "2018-04-24T14:53:33+00:00"
|
||||
"time": "2018-09-12T20:54:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.9.0",
|
||||
"version": "v1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
@@ -2160,16 +2254,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock-phpunit",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock-phpunit.git",
|
||||
"reference": "ff1cc1d4e7478ce74221e05742588619bee84f69"
|
||||
"reference": "57b92e621f14c2c07a4567cd29ed4e87de0d2912"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/ff1cc1d4e7478ce74221e05742588619bee84f69",
|
||||
"reference": "ff1cc1d4e7478ce74221e05742588619bee84f69",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/57b92e621f14c2c07a4567cd29ed4e87de0d2912",
|
||||
"reference": "57b92e621f14c2c07a4567cd29ed4e87de0d2912",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2210,7 +2304,7 @@
|
||||
"test",
|
||||
"test double"
|
||||
],
|
||||
"time": "2018-04-06T13:54:43+00:00"
|
||||
"time": "2018-10-07T14:38:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
@@ -2481,16 +2575,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "6.0.7",
|
||||
"version": "6.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "865662550c384bc1db7e51d29aeda1c2c161d69a"
|
||||
"reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/865662550c384bc1db7e51d29aeda1c2c161d69a",
|
||||
"reference": "865662550c384bc1db7e51d29aeda1c2c161d69a",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
|
||||
"reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2501,7 +2595,7 @@
|
||||
"phpunit/php-text-template": "^1.2.1",
|
||||
"phpunit/php-token-stream": "^3.0",
|
||||
"sebastian/code-unit-reverse-lookup": "^1.0.1",
|
||||
"sebastian/environment": "^3.1",
|
||||
"sebastian/environment": "^3.1 || ^4.0",
|
||||
"sebastian/version": "^2.0.1",
|
||||
"theseer/tokenizer": "^1.1"
|
||||
},
|
||||
@@ -2514,7 +2608,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.0-dev"
|
||||
"dev-master": "6.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2540,25 +2634,28 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2018-06-01T07:51:50+00:00"
|
||||
"time": "2018-10-31T16:06:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
||||
"reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c"
|
||||
"reference": "050bedf145a257b1ff02746c31894800e5122946"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cecbc684605bb0cc288828eb5d65d93d5c676d3c",
|
||||
"reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
|
||||
"reference": "050bedf145a257b1ff02746c31894800e5122946",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
@@ -2587,7 +2684,7 @@
|
||||
"filesystem",
|
||||
"iterator"
|
||||
],
|
||||
"time": "2018-06-11T11:44:00+00:00"
|
||||
"time": "2018-09-13T20:33:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-text-template",
|
||||
@@ -2681,16 +2778,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-token-stream",
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
|
||||
"reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace"
|
||||
"reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace",
|
||||
"reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
|
||||
"reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2726,20 +2823,20 @@
|
||||
"keywords": [
|
||||
"tokenizer"
|
||||
],
|
||||
"time": "2018-02-01T13:16:43+00:00"
|
||||
"time": "2018-10-30T05:52:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "7.3.2",
|
||||
"version": "7.4.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "34705f81bddc3f505b9599a2ef96e2b4315ba9b8"
|
||||
"reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34705f81bddc3f505b9599a2ef96e2b4315ba9b8",
|
||||
"reference": "34705f81bddc3f505b9599a2ef96e2b4315ba9b8",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
|
||||
"reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2760,11 +2857,11 @@
|
||||
"phpunit/php-timer": "^2.0",
|
||||
"sebastian/comparator": "^3.0",
|
||||
"sebastian/diff": "^3.0",
|
||||
"sebastian/environment": "^3.1",
|
||||
"sebastian/environment": "^3.1 || ^4.0",
|
||||
"sebastian/exporter": "^3.1",
|
||||
"sebastian/global-state": "^2.0",
|
||||
"sebastian/object-enumerator": "^3.0.3",
|
||||
"sebastian/resource-operations": "^1.0",
|
||||
"sebastian/resource-operations": "^2.0",
|
||||
"sebastian/version": "^2.0.1"
|
||||
},
|
||||
"conflict": {
|
||||
@@ -2784,7 +2881,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "7.3-dev"
|
||||
"dev-master": "7.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2810,7 +2907,7 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2018-08-22T06:39:21+00:00"
|
||||
"time": "2018-11-14T16:52:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -3391,25 +3488,25 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/resource-operations",
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/resource-operations.git",
|
||||
"reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
|
||||
"reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
|
||||
"reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
|
||||
"reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6.0"
|
||||
"php": "^7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -3429,7 +3526,7 @@
|
||||
],
|
||||
"description": "Provides a list of PHP built-in functions that operate on resources",
|
||||
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
||||
"time": "2015-07-28T20:34:47+00:00"
|
||||
"time": "2018-10-04T04:07:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/version",
|
||||
@@ -3476,7 +3573,7 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/browser-kit",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/browser-kit.git",
|
||||
@@ -3533,16 +3630,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/class-loader",
|
||||
"version": "v3.4.15",
|
||||
"version": "v3.4.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/class-loader.git",
|
||||
"reference": "31db283fc86d3143e7ff87e922177b457d909c30"
|
||||
"reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/class-loader/zipball/31db283fc86d3143e7ff87e922177b457d909c30",
|
||||
"reference": "31db283fc86d3143e7ff87e922177b457d909c30",
|
||||
"url": "https://api.github.com/repos/symfony/class-loader/zipball/5605edec7b8f034ead2497ff4aab17bb70d558c1",
|
||||
"reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3585,20 +3682,20 @@
|
||||
],
|
||||
"description": "Symfony ClassLoader Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:19:56+00:00"
|
||||
"time": "2018-10-31T09:06:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "76015a3cc372b14d00040ff58e18e29f69eba717"
|
||||
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/76015a3cc372b14d00040ff58e18e29f69eba717",
|
||||
"reference": "76015a3cc372b14d00040ff58e18e29f69eba717",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
|
||||
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3648,20 +3745,20 @@
|
||||
],
|
||||
"description": "Symfony Config Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-08-08T06:37:38+00:00"
|
||||
"time": "2018-10-31T09:09:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "ca80b8ced97cf07390078b29773dc384c39eee1f"
|
||||
"reference": "432122af37d8cd52fba1b294b11976e0d20df595"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/ca80b8ced97cf07390078b29773dc384c39eee1f",
|
||||
"reference": "ca80b8ced97cf07390078b29773dc384c39eee1f",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595",
|
||||
"reference": "432122af37d8cd52fba1b294b11976e0d20df595",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3716,20 +3813,20 @@
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:24:31+00:00"
|
||||
"time": "2018-10-31T09:30:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v3.4.15",
|
||||
"version": "v3.4.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "edda5a6155000ff8c3a3f85ee5c421af93cca416"
|
||||
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/edda5a6155000ff8c3a3f85ee5c421af93cca416",
|
||||
"reference": "edda5a6155000ff8c3a3f85ee5c421af93cca416",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
|
||||
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3769,20 +3866,20 @@
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T09:06:28+00:00"
|
||||
"time": "2018-10-02T16:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dependency-injection",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dependency-injection.git",
|
||||
"reference": "bae4983003c9d451e278504d7d9b9d7fc1846873"
|
||||
"reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/bae4983003c9d451e278504d7d9b9d7fc1846873",
|
||||
"reference": "bae4983003c9d451e278504d7d9b9d7fc1846873",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483",
|
||||
"reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3840,20 +3937,20 @@
|
||||
],
|
||||
"description": "Symfony DependencyInjection Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-08-08T11:48:58+00:00"
|
||||
"time": "2018-10-31T10:54:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "1c4519d257e652404c3aa550207ccd8ada66b38e"
|
||||
"reference": "80e60271bb288de2a2259662cff125cff4f93f95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1c4519d257e652404c3aa550207ccd8ada66b38e",
|
||||
"reference": "1c4519d257e652404c3aa550207ccd8ada66b38e",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/80e60271bb288de2a2259662cff125cff4f93f95",
|
||||
"reference": "80e60271bb288de2a2259662cff125cff4f93f95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3897,20 +3994,20 @@
|
||||
],
|
||||
"description": "Symfony DomCrawler Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T11:00:49+00:00"
|
||||
"time": "2018-10-02T12:40:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e"
|
||||
"reference": "552541dad078c85d9414b09c041ede488b456cd5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bfb30c2ad377615a463ebbc875eba64a99f6aa3e",
|
||||
"reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5",
|
||||
"reference": "552541dad078c85d9414b09c041ede488b456cd5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3960,20 +4057,20 @@
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-07-26T09:10:45+00:00"
|
||||
"time": "2018-10-10T13:52:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "c0f5f62db218fa72195b8b8700e4b9b9cf52eb5e"
|
||||
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/c0f5f62db218fa72195b8b8700e4b9b9cf52eb5e",
|
||||
"reference": "c0f5f62db218fa72195b8b8700e4b9b9cf52eb5e",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981",
|
||||
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4010,20 +4107,20 @@
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-08-18T16:52:46+00:00"
|
||||
"time": "2018-10-30T13:18:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.9.0",
|
||||
"version": "v1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8"
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8",
|
||||
"reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4069,20 +4166,20 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2018-08-06T14:22:27+00:00"
|
||||
"time": "2018-09-21T13:07:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "fa2182669f7983b7aa5f1a770d053f79f0ef144f"
|
||||
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/fa2182669f7983b7aa5f1a770d053f79f0ef144f",
|
||||
"reference": "fa2182669f7983b7aa5f1a770d053f79f0ef144f",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
|
||||
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4138,20 +4235,20 @@
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-08-07T12:45:11+00:00"
|
||||
"time": "2018-10-28T18:38:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v4.1.4",
|
||||
"version": "v4.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "b832cc289608b6d305f62149df91529a2ab3c314"
|
||||
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/b832cc289608b6d305f62149df91529a2ab3c314",
|
||||
"reference": "b832cc289608b6d305f62149df91529a2ab3c314",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9",
|
||||
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4197,7 +4294,7 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-08-18T16:52:46+00:00"
|
||||
"time": "2018-10-02T16:36:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
|
||||
@@ -29,7 +29,7 @@ $Projectname es, básicamente, una aplicación de servidor web relativamente est
|
||||
|
||||
[*= Identidad nómada] La capacidad de autenticar y migrar fácilmente una identidad a través de hubs y dominios web independientes. La identidad nómada proporciona una verdadera propiedad de una identidad en línea, porque las identidades de los canales controlados por una cuenta en un hub no están vinculadas al propio hub. Un hub es más como un "host" para canales. Con Hubzilla, no tienes una "cuenta" en un servidor como lo haces en sitios web típicos; tienes una identidad que puedes llevarte a través de la rejilla usando clones.
|
||||
|
||||
[*= Zot] El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo para el control de acceso distribuido a escala de Internet que es discreto.
|
||||
[*= Zot] El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo discreto para el control de acceso distribuido a escala de Internet.
|
||||
[/dl]
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ Esta página enumera algunas de las características principales de $Projectname
|
||||
[h4]Control deslizante de afinidad[/h4]
|
||||
|
||||
Cuando se añaden conexiones en $Projectname, los miembros tienen la opción de asignar niveles de "afinidad" (cuán cerca está su amigo).
|
||||
Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad de "Amigos".
|
||||
Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad, justamente, de "Amigos".
|
||||
|
||||
En este punto, la herramienta $Projectname [i]Control deslizante de afinidad[/i], que normalmente aparece en la parte superior de la página, ajusta su contenido para incluir aquellos contactos que están dentro del rango de afinidad deseado. Los canales fuera de ese rango no se mostrarán, a menos que ajuste el control deslizante para incluirlos.
|
||||
|
||||
@@ -62,7 +62,7 @@ Las listas de control de acceso se pueden aplicar a contenido y mensajes, fotos,
|
||||
|
||||
[h4]Inicio de sesión único[/h4]
|
||||
|
||||
Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en el hub de su casa. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica".
|
||||
Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en la página principal del hub. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica".
|
||||
|
||||
|
||||
[h4]Almacenamiento de Archivos habilitado para WebDAV[/h4]
|
||||
@@ -93,7 +93,7 @@ Las aplicaciones pueden ser construidas y distribuidas por los miembros. Éstas
|
||||
|
||||
[h4]Diseño[/h4]
|
||||
|
||||
El diseño de la página se basa en un lenguaje de descripción llamado comanche. La propia $Projectname está escrito en diseños comanches que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario".
|
||||
El diseño de la página se basa en un lenguaje de descripción llamado comanche. La propia $Projectname está escrito en plantillas en comanche que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario".
|
||||
|
||||
|
||||
[h4]Marcadores[/h4]
|
||||
@@ -111,14 +111,14 @@ Además, los mensajes pueden crearse utilizando "encriptación de extremo a extr
|
||||
|
||||
Por lo general, los mensajes públicos no se cifran durante el transporte ni durante el almacenamiento.
|
||||
|
||||
Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído todavía.
|
||||
Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído antes.
|
||||
|
||||
Los mensajes se pueden crear con una fecha de caducidad, en la que se borrarán/quitarán en el sitio del destinatario.
|
||||
|
||||
|
||||
[h4]Federación de Servicios[/h4]
|
||||
|
||||
Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde/hacia la diáspora, Friendica, GNU-Social, Mastodon y otros proveedores que utilizan estos protocolos.
|
||||
Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde o hacia Diaspora, Friendica, GNU-Social, Mastodon, Pleroma y otros proveedores que utilizan estos protocolos.
|
||||
|
||||
También existe soporte experimental para la autenticación OpenID que puede utilizarse en las listas de control de acceso. Este es un trabajo en progreso. Su hub $Projectname puede ser utilizado como un proveedor de OpenID para autenticarle en servicios externos que utilizan esta tecnología.
|
||||
|
||||
@@ -126,7 +126,7 @@ Los canales pueden tener permisos para convertirse en "canales derivados" cuando
|
||||
|
||||
[h4]Grupos de Privacidad[/h4]
|
||||
|
||||
Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de la Diáspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo).
|
||||
Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de Diaspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo).
|
||||
|
||||
|
||||
[h4]Servicios de directorio[/h4]
|
||||
@@ -158,19 +158,25 @@ Las opciones son:
|
||||
|
||||
[h4]Foros Públicos y Privados[/h4]
|
||||
|
||||
Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros: 1) mensajes de "muro a muro" y 2) a través de las etiquetas @mención del foro. Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros.
|
||||
Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros:
|
||||
|
||||
1) mensajes de "muro a muro" y
|
||||
|
||||
2) a través de las etiquetas @mención del foro.
|
||||
|
||||
Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros.
|
||||
|
||||
[h4]Clonación de cuentas[/h4]
|
||||
|
||||
Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando creas una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com.
|
||||
Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando cree una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com.
|
||||
|
||||
Por el contrario, digamos que ha creado una identidad $Projectname llamada[b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b]
|
||||
Por el contrario, digamos que ha creado una identidad $Projectname llamada [b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b]
|
||||
|
||||
Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envías un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas.
|
||||
Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envía un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas.
|
||||
|
||||
Esta es una característica bastante revolucionaria, si consideramos algunos escenarios:
|
||||
|
||||
¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tienesque iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre.
|
||||
¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tiene que iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre.
|
||||
|
||||
El administrador de su hub ya no puede permitirse el lujo de pagar por su hub gratuito y público $Projectname. Anuncia que el centro cerrará en dos semanas. Esto le da tiempo suficiente para clonar su(s) identidad(es) y preservar las relaciones, amigos y contenido de su $Projectname.
|
||||
|
||||
@@ -193,9 +199,10 @@ $Projectname ofrece una sencilla copia de seguridad de la cuenta con un solo cli
|
||||
|
||||
[h4]Borrado de cuenta[/h4]
|
||||
|
||||
Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la rejilla (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible.
|
||||
Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la red (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible.
|
||||
|
||||
[h4]Supresión de contenido[/h4]
|
||||
|
||||
Cualquier contenido creado en $Projectname permanece bajo el control del miembro (o canal) que lo creó originalmente. En cualquier momento, un miembro puede borrar un mensaje o un rango de mensajes. El proceso de eliminación garantiza que el contenido se elimine, independientemente de si se publicó en el hub principal de un canal o en otro hub, donde el canal se autenticó de forma remota a través de Zot (protocolo de autenticación y comunicación de $Projectname).
|
||||
|
||||
|
||||
@@ -221,4 +228,4 @@ $Projectname se puede ampliar de varias maneras, a través de la personalizació
|
||||
|
||||
[h4]API[/h4]
|
||||
|
||||
Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth es proporcionado.
|
||||
Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth está disponible.
|
||||
1
doc/hook/photo_view_filter.bb
Normal file
1
doc/hook/photo_view_filter.bb
Normal file
@@ -0,0 +1 @@
|
||||
[h2]photo_view_filter[/h2]
|
||||
@@ -502,6 +502,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
|
||||
[zrl=[baseurl]/help/hook/photo_upload_form]photo_upload_form[/zrl]
|
||||
Called when generating a photo upload form
|
||||
|
||||
[zrl=[baseurl]/help/hook/photo_view_filter]photo_view_filter[/zrl]
|
||||
Called before the data is handed over to the photo_view template
|
||||
|
||||
[zrl=[baseurl]/help/hook/poke_verbs]poke_verbs[/zrl]
|
||||
Called when generating the list of actions for "poke" module
|
||||
|
||||
|
||||
@@ -1021,7 +1021,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);
|
||||
}
|
||||
|
||||
@@ -1198,24 +1198,24 @@ function bbcode($Text, $options = []) {
|
||||
// Images
|
||||
// [img]pathtoimage[/img]
|
||||
if (strpos($Text,'[/img]') !== false) {
|
||||
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
|
||||
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img style="max-width: 100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
|
||||
}
|
||||
if (strpos($Text,'[/zmg]') !== false) {
|
||||
$Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
|
||||
$Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" style="max-width: 100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
|
||||
}
|
||||
|
||||
// [img float={left, right}]pathtoimage[/img]
|
||||
if (strpos($Text,'[/img]') !== false) {
|
||||
$Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
$Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img src="$1" style="max-width: 100%; float: left;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
}
|
||||
if (strpos($Text,'[/img]') !== false) {
|
||||
$Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
$Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img src="$1" style="max-width: 100%; float: right;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
}
|
||||
if (strpos($Text,'[/zmg]') !== false) {
|
||||
$Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
$Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="max-width: 100%; float: left;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
}
|
||||
if (strpos($Text,'[/zmg]') !== false) {
|
||||
$Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
$Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="max-width: 100%; float: right;" alt="' . t('Image/photo') . '" />', $Text);
|
||||
}
|
||||
|
||||
// [img=widthxheight]pathtoimage[/img]
|
||||
|
||||
@@ -59,8 +59,8 @@ function set_pconfig($uid, $family, $key, $value) {
|
||||
return Zlib\PConfig::Set($uid,$family,$key,$value);
|
||||
}
|
||||
|
||||
function del_pconfig($uid, $family, $key) {
|
||||
return Zlib\PConfig::Delete($uid,$family,$key);
|
||||
function del_pconfig($uid, $family, $key, $updated = NULL) {
|
||||
return Zlib\PConfig::Delete($uid,$family,$key,$updated);
|
||||
}
|
||||
|
||||
function load_xconfig($xchan) {
|
||||
|
||||
@@ -173,14 +173,14 @@ abstract class dba_driver {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1') && (! strpbrk($server,':;'))) {
|
||||
if(! z_dns_check($server)) {
|
||||
$this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
|
||||
$this->connected = false;
|
||||
$this->db = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1') && (! strpbrk($server,':;'))) {
|
||||
// if(! z_dns_check($server)) {
|
||||
// $this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
|
||||
// $this->connected = false;
|
||||
// $this->db = null;
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -468,7 +468,7 @@ function db_columns($table) {
|
||||
if(ACTIVE_DBTYPE === DBTYPE_POSTGRES) {
|
||||
$r = q("SELECT column_name as field FROM information_schema.columns WHERE table_schema = 'public' AND table_name = '%s'",
|
||||
dbesc($table)
|
||||
);
|
||||
);
|
||||
if($r) {
|
||||
return ids_to_array($r,'field');
|
||||
}
|
||||
|
||||
@@ -186,31 +186,30 @@ function hubloc_change_primary($hubloc) {
|
||||
logger('no hubloc');
|
||||
return false;
|
||||
}
|
||||
|
||||
logger('setting primary: ' . $hubloc['hubloc_url'] . ((intval($hubloc['hubloc_primary'])) ? ' true' : ' false'));
|
||||
|
||||
// See if this is a local hubloc and if so update the primary for the corresponding channel record.
|
||||
|
||||
if($hubloc['hubloc_url'] === z_root()) {
|
||||
$r = q("select channel_id from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($hubloc['hubloc_hash'])
|
||||
);
|
||||
if($r) {
|
||||
q("update channel set channel_primary = %d where channel_id = %d",
|
||||
intval($hubloc['hubloc_primary']),
|
||||
intval($r[0]['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// we only need to proceed further if this particular hubloc is now primary
|
||||
|
||||
if(! (intval($hubloc['hubloc_primary']))) {
|
||||
logger('not primary: ' . $hubloc['hubloc_url']);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger('setting primary: ' . $hubloc['hubloc_url']);
|
||||
|
||||
// See if there's a local channel
|
||||
|
||||
$r = q("select channel_id, channel_primary from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($hubloc['hubloc_hash'])
|
||||
);
|
||||
if($r) {
|
||||
if(! $r[0]['channel_primary']) {
|
||||
q("update channel set channel_primary = 1 where channel_id = %d",
|
||||
intval($r[0]['channel_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("update channel set channel_primary = 0 where channel_id = %d",
|
||||
intval($r[0]['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// do we even have an xchan for this hubloc and if so is it already set as primary?
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
|
||||
@@ -93,8 +93,7 @@ function import_channel($channel, $account_id, $seize, $newname = '') {
|
||||
'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
|
||||
'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
|
||||
'channel_a_delegate', 'perm_limits', 'channel_password', 'channel_salt',
|
||||
'channel_moved', 'channel_primary', 'channel_removed', 'channel_deleted',
|
||||
'channel_system'
|
||||
'channel_moved', 'channel_removed', 'channel_deleted', 'channel_system'
|
||||
];
|
||||
|
||||
$clean = array();
|
||||
@@ -1036,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));
|
||||
|
||||
@@ -608,8 +608,6 @@ function get_item_elements($x,$allow_code = false) {
|
||||
$arr['created'] = datetime_convert('UTC','UTC',$x['created']);
|
||||
$arr['edited'] = datetime_convert('UTC','UTC',$x['edited']);
|
||||
|
||||
if($arr['created'] > datetime_convert())
|
||||
$arr['created'] = datetime_convert();
|
||||
if($arr['edited'] > datetime_convert())
|
||||
$arr['edited'] = datetime_convert();
|
||||
|
||||
@@ -2627,28 +2625,30 @@ function tag_deliver($uid, $item_id) {
|
||||
$plustagged = false;
|
||||
$matches = array();
|
||||
|
||||
$pattern = '/[\!@]\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/';
|
||||
$pattern = '/[\!@]\!?\[[uz]rl\=' . preg_quote($term['url'],'/') . '\](.*?)\[\/[uz]rl\]/';
|
||||
if(preg_match($pattern,$body,$matches))
|
||||
$tagged = true;
|
||||
|
||||
// original red forum tagging sequence @forumname+
|
||||
$pattern = '/\[url\=' . preg_quote($term['url'],'/') . '\]\@(.*?)\[\/url\]/';
|
||||
if(preg_match($pattern,$body,$matches))
|
||||
$tagged = true;
|
||||
|
||||
|
||||
// standard forum tagging sequence !forumname
|
||||
|
||||
$pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/';
|
||||
$forumpattern = '/\!\!?\[[uz]rl\=([^\]]*?)\]((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
|
||||
|
||||
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
|
||||
$forumpattern2 = '/\[[uz]rl\=([^\]]*?)\]\!((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
|
||||
|
||||
$found = false;
|
||||
|
||||
$matches = array();
|
||||
|
||||
if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) {
|
||||
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
|
||||
foreach($matches as $match) {
|
||||
$matched_forums ++;
|
||||
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) {
|
||||
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
|
||||
if($matched_forums <= $max_forums) {
|
||||
$plustagged = true;
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring');
|
||||
@@ -2656,13 +2656,12 @@ function tag_deliver($uid, $item_id) {
|
||||
}
|
||||
}
|
||||
|
||||
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
|
||||
if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) {
|
||||
foreach($matches as $match) {
|
||||
$matched_forums ++;
|
||||
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) {
|
||||
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
|
||||
if($matched_forums <= $max_forums) {
|
||||
$plustagged = true;
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring');
|
||||
@@ -2884,18 +2883,19 @@ function tgroup_check($uid, $item) {
|
||||
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
|
||||
|
||||
|
||||
$pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/';
|
||||
|
||||
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
|
||||
|
||||
$forumpattern2 = '/\[zrl\=([^\]]*?)\]\!((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
|
||||
|
||||
|
||||
$found = false;
|
||||
|
||||
$matches = array();
|
||||
|
||||
if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) {
|
||||
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
|
||||
foreach($matches as $match) {
|
||||
$matched_forums ++;
|
||||
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) {
|
||||
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
|
||||
if($matched_forums <= $max_forums) {
|
||||
$found = true;
|
||||
break;
|
||||
@@ -2905,10 +2905,10 @@ function tgroup_check($uid, $item) {
|
||||
}
|
||||
}
|
||||
|
||||
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
|
||||
if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) {
|
||||
foreach($matches as $match) {
|
||||
$matched_forums ++;
|
||||
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) {
|
||||
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
|
||||
if($matched_forums <= $max_forums) {
|
||||
$found = true;
|
||||
break;
|
||||
@@ -4610,10 +4610,10 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body,
|
||||
if(! stristr($image,z_root() . '/photo/'))
|
||||
continue;
|
||||
$image_uri = substr($image,strrpos($image,'/') + 1);
|
||||
if(strpos($image_uri,'-') !== false)
|
||||
$image_uri = substr($image_uri,0, strpos($image_uri,'-'));
|
||||
if(strpos($image_uri,'.') !== false)
|
||||
$image_uri = substr($image_uri,0, strpos($image_uri,'.'));
|
||||
if(strrpos($image_uri,'-') !== false)
|
||||
$image_uri = substr($image_uri,0, strrpos($image_uri,'-'));
|
||||
if(strrpos($image_uri,'.') !== false)
|
||||
$image_uri = substr($image_uri,0, strrpos($image_uri,'.'));
|
||||
if(! strlen($image_uri))
|
||||
continue;
|
||||
$srch = '<' . $xchan_hash . '>';
|
||||
|
||||
@@ -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
|
||||
@@ -248,20 +246,12 @@ function bb_to_markdown($Text, $options = []) {
|
||||
// Convert it to HTML - don't try oembed
|
||||
$Text = bbcode($Text, [ 'tryoembed' => false ]);
|
||||
|
||||
// Markdownify does not preserve previously escaped html entities such as <> and &.
|
||||
//$Text = str_replace(array('<','>','&'),array('&_lt_;','&_gt_;','&_amp_;'),$Text);
|
||||
|
||||
// Now convert HTML to Markdown
|
||||
|
||||
$Text = html2markdown($Text);
|
||||
|
||||
//html2markdown adds backslashes infront of hashes after a new line. remove them
|
||||
$Text = str_replace("\n\#", "\n#", $Text);
|
||||
|
||||
// It also adds backslashes to our attempt at getting around the html entity preservation for some weird reason.
|
||||
|
||||
//$Text = str_replace(array('&\\_lt\\_;','&\\_gt\\_;','&\\_amp\\_;'),array('<','>','&'),$Text);
|
||||
|
||||
// If the text going into bbcode() has a plain URL in it, i.e.
|
||||
// with no [url] tags around it, it will come out of parseString()
|
||||
// looking like: <http://url.com>, which gets removed by strip_tags().
|
||||
@@ -291,12 +281,24 @@ function bb_to_markdown($Text, $options = []) {
|
||||
* If the HTML text can not get parsed it will return an empty string.
|
||||
*
|
||||
* @param string $html The HTML code to convert
|
||||
* @param array $options an array of options to pass to the environment
|
||||
* @return string Markdown representation of the given HTML text, empty on error
|
||||
*/
|
||||
function html2markdown($html,$options = []) {
|
||||
function html2markdown($html, $options = []) {
|
||||
$markdown = '';
|
||||
|
||||
$internal_errors = libxml_use_internal_errors(true);
|
||||
if(! $options) {
|
||||
$options = [
|
||||
'header_style' => 'setext', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
|
||||
'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
|
||||
'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
|
||||
'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style
|
||||
'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style
|
||||
'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
|
||||
'hard_break' => false, // Set to true to turn <br> into `\n` instead of ` \n`
|
||||
'list_item_style' => '-', // Set the default character for each <li> in a <ul>. Can be '-', '*', or '+'
|
||||
];
|
||||
}
|
||||
|
||||
$environment = Environment::createDefaultEnvironment($options);
|
||||
$environment->addConverter(new TableConverter());
|
||||
@@ -308,8 +310,6 @@ function html2markdown($html,$options = []) {
|
||||
logger("Invalid HTML. HTMLToMarkdown library threw an exception.");
|
||||
}
|
||||
|
||||
libxml_use_internal_errors($internal_errors);
|
||||
|
||||
return $markdown;
|
||||
}
|
||||
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,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'))
|
||||
@@ -153,7 +156,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-2].+? [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));
|
||||
@@ -233,7 +236,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
|
||||
return $ret;
|
||||
|
||||
if(! array_key_exists('request_target',$opts)) {
|
||||
$opts['request_target'] = 'get ' . get_request_string($url);
|
||||
$opts['request_target'] = 'post ' . get_request_string($url);
|
||||
}
|
||||
|
||||
@curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
@@ -286,6 +289,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'))
|
||||
@@ -318,8 +324,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-2].+? [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));
|
||||
@@ -690,99 +695,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[1],0,1) == '=') {
|
||||
$owidth = intval(substr($mtch[2],1));
|
||||
if(intval($owidth) > 0 && intval($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.
|
||||
*
|
||||
|
||||
@@ -221,7 +221,11 @@ function oembed_fetch_url($embedurl){
|
||||
|
||||
if(strpos(strtolower($embedurl),'.pdf') !== false) {
|
||||
$action = 'allow';
|
||||
$j = [ 'html' => '<object data="' . $embedurl . '" type="application/pdf" width="500" height="720">' . '<a href="' . $embedurl . '">' . t('View PDF') . '</a></object>', 'width' => 500, 'height' => 720, 'type' => 'pdf' ];
|
||||
$j = [
|
||||
'html' => '<object data="' . $embedurl . '" type="application/pdf" style="width: 100%; height: 300px;"></object>',
|
||||
'title' => t('View PDF'),
|
||||
'type' => 'pdf'
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
@@ -272,6 +276,7 @@ function oembed_fetch_url($embedurl){
|
||||
}
|
||||
|
||||
$j['embedurl'] = $embedurl;
|
||||
$j['zrl'] = $is_matrix;
|
||||
|
||||
// logger('fetch return: ' . print_r($j,true));
|
||||
|
||||
@@ -335,7 +340,11 @@ function oembed_format_object($j){
|
||||
|
||||
case "rich": {
|
||||
// not so safe..
|
||||
$ret.= $jhtml;
|
||||
if($j['zrl']) {
|
||||
$ret = ((preg_match('/^<div[^>]+>(.*?)<\/div>$/is',$j['html'],$o)) ? $o[1] : $j['html']);
|
||||
} else {
|
||||
$ret.= $jhtml;
|
||||
};
|
||||
}; break;
|
||||
}
|
||||
|
||||
|
||||
@@ -350,8 +350,7 @@ abstract class photo_driver {
|
||||
$p['allow_gid'] = (($arr['allow_gid']) ? $arr['allow_gid'] : '');
|
||||
$p['deny_cid'] = (($arr['deny_cid']) ? $arr['deny_cid'] : '');
|
||||
$p['deny_gid'] = (($arr['deny_gid']) ? $arr['deny_gid'] : '');
|
||||
$p['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
|
||||
$p['edited'] = (($arr['edited']) ? $arr['edited'] : $p['created']);
|
||||
$p['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
|
||||
$p['title'] = (($arr['title']) ? $arr['title'] : '');
|
||||
$p['description'] = (($arr['description']) ? $arr['description'] : '');
|
||||
$p['photo_usage'] = intval($arr['photo_usage']);
|
||||
@@ -365,13 +364,15 @@ abstract class photo_driver {
|
||||
if(! intval($p['imgscale']))
|
||||
logger('save: ' . print_r($arr,true), LOGGER_DATA);
|
||||
|
||||
$x = q("select id from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1",
|
||||
$x = q("select id, created from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1",
|
||||
dbesc($p['resource_id']),
|
||||
intval($p['uid']),
|
||||
dbesc($p['xchan']),
|
||||
intval($p['imgscale'])
|
||||
);
|
||||
|
||||
if($x) {
|
||||
$p['created'] = (($x['created']) ? $x['created'] : $p['edited']);
|
||||
$r = q("UPDATE photo set
|
||||
aid = %d,
|
||||
uid = %d,
|
||||
@@ -412,7 +413,7 @@ abstract class photo_driver {
|
||||
intval($p['width']),
|
||||
(intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())),
|
||||
intval($p['os_storage']),
|
||||
intval(strlen($this->imageString())),
|
||||
(intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())),
|
||||
intval($p['imgscale']),
|
||||
intval($p['photo_usage']),
|
||||
dbesc($p['title']),
|
||||
@@ -427,6 +428,7 @@ abstract class photo_driver {
|
||||
);
|
||||
}
|
||||
else {
|
||||
$p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']);
|
||||
$r = q("INSERT INTO photo
|
||||
( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid )
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
|
||||
@@ -443,7 +445,7 @@ abstract class photo_driver {
|
||||
intval($p['width']),
|
||||
(intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())),
|
||||
intval($p['os_storage']),
|
||||
intval(strlen($this->imageString())),
|
||||
(intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())),
|
||||
intval($p['imgscale']),
|
||||
intval($p['photo_usage']),
|
||||
dbesc($p['title']),
|
||||
@@ -464,11 +466,6 @@ abstract class photo_driver {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Guess image mimetype from filename or from Content-Type header
|
||||
*
|
||||
@@ -485,11 +482,11 @@ function guess_image_type($filename, $headers = '') {
|
||||
$h = explode("\n",$headers);
|
||||
foreach ($h as $l) {
|
||||
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
|
||||
$hdrs[$k] = $v;
|
||||
$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 (array_key_exists('content-type', $hdrs))
|
||||
$type = $hdrs['content-type'];
|
||||
}
|
||||
if (is_null($type)){
|
||||
|
||||
@@ -570,122 +567,166 @@ function delete_thing_photo($url,$ob_hash) {
|
||||
|
||||
|
||||
|
||||
function import_xchan_photo($photo,$xchan,$thing = false) {
|
||||
/**
|
||||
* @brief fetches an photo from external site and prepares its miniatures.
|
||||
*
|
||||
* @param string $photo
|
||||
* external URL to fetch base image
|
||||
* @param string $xchan
|
||||
* channel unique hash
|
||||
* @param boolean $thing
|
||||
* TRUE if this is a thing URL
|
||||
* @param boolean $force
|
||||
* TRUE if ignore image modification date check (force fetch)
|
||||
*
|
||||
* @return array of results
|
||||
* * \e string \b 0 => local URL to full image
|
||||
* * \e string \b 1 => local URL to standard thumbnail
|
||||
* * \e string \b 2 => local URL to micro thumbnail
|
||||
* * \e string \b 3 => image type
|
||||
* * \e boolean \b 4 => TRUE if fetch failure
|
||||
* * \e string \b 5 => modification date
|
||||
*/
|
||||
|
||||
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
|
||||
$album = (($thing) ? 'Things' : 'Contact Photos');
|
||||
function import_xchan_photo($photo,$xchan,$thing = false,$force = false) {
|
||||
|
||||
logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
|
||||
$modified = '';
|
||||
|
||||
if($thing)
|
||||
$hash = photo_new_resource();
|
||||
else {
|
||||
$r = q("select resource_id from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
|
||||
dbesc($xchan),
|
||||
intval(PHOTO_XCHAN)
|
||||
);
|
||||
if($r) {
|
||||
$hash = $r[0]['resource_id'];
|
||||
}
|
||||
else {
|
||||
$hash = photo_new_resource();
|
||||
}
|
||||
}
|
||||
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
|
||||
$album = (($thing) ? 'Things' : 'Contact Photos');
|
||||
|
||||
$photo_failure = false;
|
||||
$img_str = '';
|
||||
logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
|
||||
|
||||
if($photo) {
|
||||
$filename = basename($photo);
|
||||
if($thing) {
|
||||
$hash = photo_new_resource();
|
||||
}
|
||||
else {
|
||||
$r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
|
||||
dbesc($xchan),
|
||||
intval(PHOTO_XCHAN)
|
||||
);
|
||||
if($r) {
|
||||
$hash = $r[0]['resource_id'];
|
||||
$modified = $r[0]['edited'];
|
||||
$type = $r[0]['mimetype'];
|
||||
}
|
||||
else {
|
||||
$hash = photo_new_resource();
|
||||
}
|
||||
}
|
||||
|
||||
$result = z_fetch_url($photo,true);
|
||||
$photo_failure = false;
|
||||
$img_str = '';
|
||||
|
||||
if($result['success']) {
|
||||
$img_str = $result['body'];
|
||||
$type = guess_image_type($photo, $result['header']);
|
||||
if($photo) {
|
||||
$filename = basename($photo);
|
||||
|
||||
$h = explode("\n",$result['header']);
|
||||
if($h) {
|
||||
foreach($h as $hl) {
|
||||
if(stristr($hl,'content-type:')) {
|
||||
if(! stristr($hl,'image/')) {
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
if($force || $modified == '') {
|
||||
$result = z_fetch_url($photo,true);
|
||||
}
|
||||
else {
|
||||
$h = array('headers' => array("If-Modified-Since: " . gmdate("D, d M Y H:i:s", strtotime($modified . "Z")) . " GMT"));
|
||||
$result = z_fetch_url($photo,true,0,$h);
|
||||
}
|
||||
|
||||
if(! $photo_failure) {
|
||||
$img = photo_factory($img_str, $type);
|
||||
if($img->is_valid()) {
|
||||
$width = $img->getWidth();
|
||||
$height = $img->getHeight();
|
||||
|
||||
if($width && $height) {
|
||||
if(($width / $height) > 1.2) {
|
||||
// crop out the sides
|
||||
$margin = $width - $height;
|
||||
$img->cropImage(300,($margin / 2),0,$height,$height);
|
||||
}
|
||||
elseif(($height / $width) > 1.2) {
|
||||
// crop out the bottom
|
||||
$margin = $height - $width;
|
||||
$img->cropImage(300,0,0,$width,$width);
|
||||
if($result['success']) {
|
||||
$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()));
|
||||
|
||||
}
|
||||
else {
|
||||
$img->scaleImageSquare(300);
|
||||
}
|
||||
if(is_null($type))
|
||||
$photo_failure = true;
|
||||
}
|
||||
elseif($result['return_code'] == 304) {
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
}
|
||||
else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
$photo_failure = true;
|
||||
}
|
||||
else
|
||||
$photo_failure = true;
|
||||
|
||||
$p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'imgscale' => 4);
|
||||
if(! $photo_failure && $result['return_code'] != 304) {
|
||||
$img = photo_factory($img_str, $type);
|
||||
if($img->is_valid()) {
|
||||
$width = $img->getWidth();
|
||||
$height = $img->getHeight();
|
||||
|
||||
$r = $img->save($p);
|
||||
if($width && $height) {
|
||||
if(($width / $height) > 1.2) {
|
||||
// crop out the sides
|
||||
$margin = $width - $height;
|
||||
$img->cropImage(300,($margin / 2),0,$height,$height);
|
||||
}
|
||||
elseif(($height / $width) > 1.2) {
|
||||
// crop out the bottom
|
||||
$margin = $height - $width;
|
||||
$img->cropImage(300,0,0,$width,$width);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
}
|
||||
else {
|
||||
$img->scaleImageSquare(300);
|
||||
}
|
||||
|
||||
$img->scaleImage(80);
|
||||
$p['imgscale'] = 5;
|
||||
|
||||
$r = $img->save($p);
|
||||
}
|
||||
else
|
||||
$photo_failure = true;
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$img->scaleImage(48);
|
||||
$p['imgscale'] = 6;
|
||||
|
||||
$r = $img->save($p);
|
||||
$p = array(
|
||||
'xchan' => $xchan,
|
||||
'resource_id' => $hash,
|
||||
'filename' => basename($photo),
|
||||
'album' => $album,
|
||||
'photo_usage' => $flags,
|
||||
'imgscale' => 4,
|
||||
'edited' => $modified
|
||||
);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
$r = $img->save($p);
|
||||
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
}
|
||||
else {
|
||||
logger('import_xchan_photo: invalid image from ' . $photo);
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
if($photo_failure) {
|
||||
$photo = z_root() . '/' . get_default_profile_photo();
|
||||
$thumb = z_root() . '/' . get_default_profile_photo(80);
|
||||
$micro = z_root() . '/' . get_default_profile_photo(48);
|
||||
$type = 'image/png';
|
||||
}
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
return(array($photo,$thumb,$micro,$type,$photo_failure));
|
||||
$img->scaleImage(80);
|
||||
$p['imgscale'] = 5;
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$img->scaleImage(48);
|
||||
$p['imgscale'] = 6;
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
}
|
||||
else {
|
||||
logger('import_xchan_photo: invalid image from ' . $photo);
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
if($photo_failure) {
|
||||
$default = get_default_profile_photo();
|
||||
$photo = z_root() . '/' . $default;
|
||||
$thumb = z_root() . '/' . get_default_profile_photo(80);
|
||||
$micro = z_root() . '/' . get_default_profile_photo(48);
|
||||
$type = 'image/png';
|
||||
$modified = gmdate('Y-m-d H:i:s', filemtime($default));
|
||||
}
|
||||
|
||||
logger('HTTP code: ' . $result['return_code'] . '; modified: ' . $modified . '; failure: ' . ($photo_failure ? 'yes' : 'no') . '; URL: ' . $photo, LOGGER_DEBUG);
|
||||
return(array($photo,$thumb,$micro,$type,$photo_failure,$modified));
|
||||
|
||||
}
|
||||
|
||||
@@ -700,16 +741,8 @@ function import_channel_photo_from_url($photo,$aid,$uid) {
|
||||
$img_str = $result['body'];
|
||||
$type = guess_image_type($photo, $result['header']);
|
||||
|
||||
$h = explode("\n",$result['header']);
|
||||
if($h) {
|
||||
foreach($h as $hl) {
|
||||
if(stristr($hl,'content-type:')) {
|
||||
if(! stristr($hl,'image/')) {
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(is_null($type))
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -31,8 +31,13 @@ class photo_imagick extends photo_driver {
|
||||
if(! $data)
|
||||
return;
|
||||
|
||||
$this->image->readImageBlob($data);
|
||||
|
||||
try {
|
||||
$this->image->readImageBlob($data);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
logger('imagick readImageBlob() exception:' . print_r($e,true));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the image to the format it will be saved to
|
||||
@@ -205,4 +210,4 @@ class photo_imagick extends photo_driver {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1011,23 +1011,3 @@ function profile_photo_set_profile_perms($uid, $profileid = 0) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_image_from_url($url,&$mimetype) {
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_fetch_url($url,true,$redirects,[ 'novalidate' => true ]);
|
||||
if($x['success']) {
|
||||
$hdrs = [];
|
||||
$h = explode("\n",$x['header']);
|
||||
foreach ($h as $l) {
|
||||
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
|
||||
$hdrs[strtolower($k)] = $v;
|
||||
}
|
||||
if (array_key_exists('content-type', $hdrs))
|
||||
$mimetype = $hdrs['content-type'];
|
||||
|
||||
return $x['body'];
|
||||
}
|
||||
|
||||
return EMPTY_STR;
|
||||
}
|
||||
@@ -633,6 +633,19 @@ function attribute_contains($attr, $s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log to syslog
|
||||
*
|
||||
* @param string $msg Message to log
|
||||
* @param int $priority - compatible with syslog
|
||||
*/
|
||||
function hz_syslog($msg, $priority = LOG_INFO) {
|
||||
openlog("hz-log", LOG_PID | LOG_PERROR, LOG_LOCAL0);
|
||||
syslog($priority, $msg);
|
||||
closelog();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Logging function for Hubzilla.
|
||||
*
|
||||
@@ -3204,6 +3217,28 @@ function array2XML($obj, $array) {
|
||||
}
|
||||
}
|
||||
|
||||
function array_path_exists($str,$arr) {
|
||||
|
||||
$ptr = $arr;
|
||||
$search = explode('/', $str);
|
||||
|
||||
if($search) {
|
||||
foreach($search as $s) {
|
||||
if(array_key_exists($s,$ptr)) {
|
||||
$ptr = $ptr[$s];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Inserts an array into $table.
|
||||
*
|
||||
@@ -3219,8 +3254,16 @@ function create_table_from_array($table, $arr, $binary_fields = []) {
|
||||
if(! ($arr && $table))
|
||||
return false;
|
||||
|
||||
$columns = db_columns($table);
|
||||
|
||||
$clean = [];
|
||||
foreach($arr as $k => $v) {
|
||||
|
||||
if(! in_array($k,$columns)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$matches = false;
|
||||
if(preg_match('/([^a-zA-Z0-9\-\_\.])/',$k,$matches)) {
|
||||
return false;
|
||||
@@ -3288,8 +3331,6 @@ function cleanup_bbcode($body) {
|
||||
|
||||
$body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
|
||||
|
||||
$body = scale_external_images($body,false);
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
@@ -3404,7 +3445,7 @@ function get_forum_channels($uid) {
|
||||
|
||||
$sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
|
||||
|
||||
$r = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name",
|
||||
$r = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_addr, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
@@ -3459,3 +3500,4 @@ function print_val($v) {
|
||||
return $v;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Zotlabs\Zot6\HTTPSig;
|
||||
|
||||
|
||||
function xchan_store_lowlevel($arr) {
|
||||
|
||||
@@ -39,6 +41,13 @@ function xchan_store_lowlevel($arr) {
|
||||
|
||||
function xchan_store($arr) {
|
||||
|
||||
$update_photo = false;
|
||||
$update_name = false;
|
||||
|
||||
if(! ($arr['guid'] || $arr['hash'])) {
|
||||
$arr = json_decode(file_get_contents('php://input'),true);
|
||||
}
|
||||
|
||||
logger('xchan_store: ' . print_r($arr,true));
|
||||
|
||||
if(! $arr['hash'])
|
||||
@@ -49,57 +58,90 @@ function xchan_store($arr) {
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($arr['hash'])
|
||||
);
|
||||
if($r)
|
||||
return true;
|
||||
if(! $r) {
|
||||
|
||||
if(! $arr['network'])
|
||||
$arr['network'] = 'unknown';
|
||||
if(! $arr['name'])
|
||||
$arr['name'] = 'unknown';
|
||||
if(! $arr['url'])
|
||||
$arr['url'] = z_root();
|
||||
if(! $arr['photo'])
|
||||
$arr['photo'] = z_root() . '/' . get_default_profile_photo();
|
||||
$update_photo = true;
|
||||
|
||||
if(! $arr['network'])
|
||||
$arr['network'] = 'unknown';
|
||||
if(! $arr['name'])
|
||||
$arr['name'] = 'unknown';
|
||||
if(! $arr['url'])
|
||||
$arr['url'] = z_root();
|
||||
if(! $arr['photo'])
|
||||
$arr['photo'] = z_root() . '/' . get_default_profile_photo();
|
||||
|
||||
if($arr['network'] === 'zot') {
|
||||
if((! $arr['key']) || (! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key']))) {
|
||||
logger('Unable to verify signature for ' . $arr['hash']);
|
||||
return false;
|
||||
if($arr['network'] === 'zot6') {
|
||||
if((! $arr['key']) || (! Libzot::verify($arr['id'],$arr['id_sig'],$arr['key']))) {
|
||||
logger('Unable to verify signature for ' . $arr['hash']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$x = [];
|
||||
foreach($arr as $k => $v) {
|
||||
if($k === 'key') {
|
||||
$x['xchan_pubkey'] = $v;
|
||||
continue;
|
||||
}
|
||||
if($k === 'photo') {
|
||||
continue;
|
||||
if($arr['network'] === 'zot') {
|
||||
if((! $arr['key']) || (! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key']))) {
|
||||
logger('Unable to verify signature for ' . $arr['hash']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$columns = db_columns('xchan');
|
||||
|
||||
$x = [];
|
||||
foreach($arr as $k => $v) {
|
||||
if($k === 'key') {
|
||||
$x['xchan_pubkey'] = HTTPSig::convertKey(escape_tags($v));;
|
||||
continue;
|
||||
}
|
||||
if($k === 'photo') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$x['xchan_' . $k] = $v;
|
||||
if(in_array($columns,'xchan_' . $k))
|
||||
$x['xchan_' . $k] = escape_tags($v);
|
||||
}
|
||||
|
||||
$x['xchan_name_date'] = datetime_convert();
|
||||
$x['xchan_photo_date'] = datetime_convert();
|
||||
$x['xchan_system'] = false;
|
||||
|
||||
$result = xchan_store_lowlevel($x);
|
||||
|
||||
if(! $result)
|
||||
return $result;
|
||||
}
|
||||
else {
|
||||
if($r[0]['network'] === 'zot6') {
|
||||
return true;
|
||||
}
|
||||
if($r[0]['xchan_photo_date'] < datetime_convert('UTC','UTC',$arr['photo_date'])) {
|
||||
$update_photo = true;
|
||||
}
|
||||
if($r[0]['xchan_name_date'] < datetime_convert('UTC','UTC',$arr['name_date'])) {
|
||||
$update_name = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($update_photo && $arr['photo']) {
|
||||
$photos = import_xchan_photo($arr['photo'],$arr['hash']);
|
||||
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($arr['hash'])
|
||||
);
|
||||
}
|
||||
if($update_name && $arr['name']) {
|
||||
$x = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
|
||||
dbesc(escape_tags($arr['name'])),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($arr['hash'])
|
||||
);
|
||||
}
|
||||
|
||||
$x['xchan_name_date'] = datetime_convert();
|
||||
|
||||
$r = xchan_store_lowlevel($x);
|
||||
|
||||
if(! $r)
|
||||
return $r;
|
||||
|
||||
$photos = import_xchan_photo($arr['photo'],$arr['hash']);
|
||||
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($arr['hash'])
|
||||
);
|
||||
return $r;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1187,13 +1187,13 @@ function zot_fetch($arr) {
|
||||
|
||||
$zret = zot6_check_sig();
|
||||
|
||||
if($zret['success'] && $zret['hubloc'] && $zret['hubloc']['hubloc_guid'] === $data['sender']['guid'] && $data['msg']) {
|
||||
if($zret['success'] && $zret['hubloc'] && $zret['hubloc']['hubloc_guid'] === $arr['sender']['guid'] && $arr['msg']) {
|
||||
logger('zot6_delivery',LOGGER_DEBUG);
|
||||
logger('zot6_data: ' . print_r($data,true),LOGGER_DATA);
|
||||
logger('zot6_data: ' . print_r($arr,true),LOGGER_DATA);
|
||||
|
||||
$ret['collected'] = true;
|
||||
|
||||
$import = [ 'success' => true, 'body' => json_encode( [ 'success' => true, 'pickup' => [ [ 'notify' => $data, 'message' => json_decode($data['msg'],true) ] ] ] ) ];
|
||||
$import = [ 'success' => true, 'body' => json_encode( [ 'success' => true, 'pickup' => [ [ 'notify' => $arr, 'message' => json_decode($arr['msg'],true) ] ] ] ) ];
|
||||
$hubs = [ $zret['hubloc'] ] ;
|
||||
}
|
||||
|
||||
@@ -3507,8 +3507,41 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
|
||||
|
||||
if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) {
|
||||
foreach($arr['config'] as $cat => $k) {
|
||||
foreach($arr['config'][$cat] as $k => $v)
|
||||
set_pconfig($channel['channel_id'],$cat,$k,$v);
|
||||
|
||||
$pconfig_updated = [];
|
||||
$pconfig_del = [];
|
||||
|
||||
foreach($arr['config'][$cat] as $k => $v) {
|
||||
|
||||
if (strpos($k,'pcfgud:')===0) {
|
||||
|
||||
$realk = substr($k,7);
|
||||
$pconfig_updated[$realk] = $v;
|
||||
unset($arr['config'][$cat][$k]);
|
||||
|
||||
}
|
||||
|
||||
if (strpos($k,'pcfgdel:')===0) {
|
||||
$realk = substr($k,8);
|
||||
$pconfig_del[$realk] = datetime_convert();
|
||||
unset($arr['config'][$cat][$k]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($arr['config'][$cat] as $k => $v) {
|
||||
|
||||
if (!isset($pconfig_updated[$k])) {
|
||||
$pconfig_updated[$k] = NULL;
|
||||
}
|
||||
|
||||
set_pconfig($channel['channel_id'],$cat,$k,$v,$pconfig_updated[$k]);
|
||||
|
||||
}
|
||||
|
||||
foreach($pconfig_del as $k => $updated) {
|
||||
del_pconfig($channel['channel_id'],$cat,$k,$updated);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -910,7 +910,6 @@ CREATE TABLE IF NOT EXISTS `outq` (
|
||||
KEY `outq_priority` (`outq_priority`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pchan (
|
||||
`pchan_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`pchan_guid` char(191) NOT NULL DEFAULT '',
|
||||
@@ -922,15 +921,16 @@ CREATE TABLE IF NOT EXISTS pchan (
|
||||
KEY `pchan_hash` (`pchan_hash`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pconfig` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`uid` int(11) NOT NULL DEFAULT 0 ,
|
||||
`cat` char(191) NOT NULL DEFAULT '',
|
||||
`k` char(191) NOT NULL DEFAULT '',
|
||||
`v` mediumtext NOT NULL,
|
||||
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `access` (`uid`,`cat`,`k`)
|
||||
UNIQUE KEY `access` (`uid`,`cat`,`k`),
|
||||
KEY `pconfig_updated` (`updated`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `photo` (
|
||||
|
||||
@@ -891,7 +891,6 @@ create index "outq_async" on outq ("outq_async");
|
||||
create index "outq_delivered" on outq ("outq_delivered");
|
||||
create index "outq_priority" on outq ("outq_priority");
|
||||
|
||||
|
||||
CREATE TABLE "pchan" (
|
||||
"pchan_id" serial NOT NULL,
|
||||
"pchan_guid" text NOT NULL,
|
||||
@@ -900,7 +899,6 @@ CREATE TABLE "pchan" (
|
||||
"pchan_prvkey" text NOT NULL,
|
||||
PRIMARY KEY ("pchan_id")
|
||||
);
|
||||
|
||||
create index "pchan_guid" on pchan ("pchan_guid");
|
||||
create index "pchan_hash" on pchan ("pchan_hash");
|
||||
|
||||
@@ -910,9 +908,11 @@ CREATE TABLE "pconfig" (
|
||||
"cat" text NOT NULL,
|
||||
"k" text NOT NULL,
|
||||
"v" text NOT NULL,
|
||||
"updated" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
|
||||
PRIMARY KEY ("id"),
|
||||
UNIQUE ("uid","cat","k")
|
||||
);
|
||||
create index "pconfig_updated_idx" on pconfig ("updated");
|
||||
|
||||
CREATE TABLE "photo" (
|
||||
"id" serial NOT NULL,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -52,12 +52,12 @@ class MarkdownTest extends UnitTestCase {
|
||||
' ',
|
||||
''
|
||||
],
|
||||
/* it is not clear why this test fails
|
||||
|
||||
'strong, b, em, i, bib' => [
|
||||
'<strong>strong</strong> <b>bold</b> <em>em</em> <i>italic</i> <b>bo<i>italic</i>ld</b>',
|
||||
'**strong** **bold** _em_ _italic_ **bo_italic_ld**'
|
||||
'**strong** **bold** *em* *italic* **bo*italic*ld**'
|
||||
],
|
||||
*/
|
||||
|
||||
'empty tags' => [
|
||||
'text1 <b></b> text2 <i></i>',
|
||||
'text1 text2'
|
||||
@@ -70,10 +70,6 @@ class MarkdownTest extends UnitTestCase {
|
||||
'& lt < gt >',
|
||||
'& lt < gt >'
|
||||
],
|
||||
'our escaped HTML entities' => [
|
||||
'&_lt_; &_gt_; &_amp_;',
|
||||
'&\_lt\_; &\_gt\_; &\_amp\_;'
|
||||
],
|
||||
'linebreak' => [
|
||||
"line1<br>line2\nline3",
|
||||
"line1 \nline2 line3"
|
||||
@@ -84,15 +80,15 @@ class MarkdownTest extends UnitTestCase {
|
||||
],
|
||||
'unordered list' => [
|
||||
'<ul><li>Item 1</li><li>Item 2</li><li>Item <b>3</b></li></ul>',
|
||||
"- Item 1\n- Item 2\n- Item 3"
|
||||
"- Item 1\n- Item 2\n- Item **3**"
|
||||
],
|
||||
'ordered list' => [
|
||||
'<ol><li>Item 1</li><li>Item 2</li><li>Item <b>3</b></li></ol>',
|
||||
"1. Item 1\n2. Item 2\n3. Item 3"
|
||||
"1. Item 1\n2. Item 2\n3. Item **3**"
|
||||
],
|
||||
'nested lists' => [
|
||||
'<ul><li>Item 1<ol><li>Item 1a</li><li>Item <b>1b</b></ol></li><li>Item 2</li></ul>',
|
||||
"- Item 1\n 1. Item 1a\n 2. Item 1b\n- Item 2"
|
||||
"- Item 1\n 1. Item 1a\n 2. Item **1b**\n- Item 2"
|
||||
],
|
||||
'img' => [
|
||||
'<img src="/path/to/img.png" alt="alt text" title="title text">',
|
||||
@@ -118,12 +114,10 @@ class MarkdownTest extends UnitTestCase {
|
||||
'<code><p>HTML text</p></code>',
|
||||
'`<p>HTML text</p>`'
|
||||
],
|
||||
/* it is not clear why this test fails
|
||||
'pre' => [
|
||||
'<pre> line with spaces </pre>',
|
||||
'` line with spaces `'
|
||||
'<pre> one line with spaces </pre>',
|
||||
"```\n one line with spaces \n```"
|
||||
],
|
||||
*/
|
||||
'div p' => [
|
||||
'<div>div</div><div><p>p</p></div>',
|
||||
"<div>div</div><div>p\n\n</div>"
|
||||
|
||||
15
util/addons
15
util/addons
@@ -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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,22 @@
|
||||
# jQuery File Upload Plugin
|
||||
|
||||
## Demo
|
||||
[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
|
||||
|
||||
## Description
|
||||
File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
|
||||
Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
|
||||
|
||||
## Demo
|
||||
[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
|
||||
|
||||
## ⚠️ Security Notice
|
||||
Security related releases:
|
||||
|
||||
* [v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1) Mitigates some [Potential vulnerabilities with PHP+ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick).
|
||||
* [v9.24.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.24.1) Fixes a [Remote code execution vulnerability in the PHP component](VULNERABILITIES.md#remote-code-execution-vulnerability-in-the-php-component).
|
||||
* v[9.10.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/9.10.1) Fixes an [Open redirect vulnerability in the GAE components](VULNERABILITIES.md#open-redirect-vulnerability-in-the-gae-components).
|
||||
* Commit [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a) (*fixed in all tagged releases*) Fixes a [Cross-site scripting vulnerability in the Iframe Transport](VULNERABILITIES.md#cross-site-scripting-vulnerability-in-the-iframe-transport).
|
||||
|
||||
Please read the [SECURITY](SECURITY.md) document for instructions on how to securely configure your Webserver for file uploads.
|
||||
|
||||
## Setup
|
||||
* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
|
||||
* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
|
||||
@@ -15,7 +25,7 @@ Supports cross-domain, chunked and resumable file uploads and client-side image
|
||||
* **Multiple file upload:**
|
||||
Allows to select multiple files at once and upload them simultaneously.
|
||||
* **Drag & Drop support:**
|
||||
Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
|
||||
Allows to upload files by dragging them from your desktop or file manager and dropping them on your browser window.
|
||||
* **Upload progress bar:**
|
||||
Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
|
||||
* **Cancelable uploads:**
|
||||
133
vendor/blueimp/jquery-file-upload/SECURITY.md
vendored
Normal file
133
vendor/blueimp/jquery-file-upload/SECURITY.md
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
# File Upload Security
|
||||
For an in-depth understanding of the potential security risks of providing file uploads and possible mitigations, please refer to the [OWASP - Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload) documentation.
|
||||
|
||||
To securely setup the project to serve uploaded files, please refer to the sample [Secure file upload serving configurations](#secure-file-upload-serving-configurations).
|
||||
|
||||
To mitigate potential vulnerabilities in image processing libraries, please refer to the [Secure image processing configurations](#secure-image-processing-configurations).
|
||||
|
||||
By default, all sample upload handlers allow only upload of image files, which mitigates some attack vectors, but should not be relied on as the only protection.
|
||||
|
||||
Please also have a look at the [list of fixed vulnerabilities](VULNERABILITIES.md) in jQuery File Upload, which relates mostly to the sample server-side upload handlers and how they have been configured.
|
||||
|
||||
## Purpose of this project
|
||||
Please note that this project is not a complete file management product, but foremost a client-side file upload library for [jQuery](https://jquery.com/).
|
||||
The server-side sample upload handlers are just examples to demonstrate the client-side file upload functionality.
|
||||
|
||||
To make this very clear, there is **no user authentication** by default:
|
||||
* **everyone can upload files**
|
||||
* **everyone can delete uploaded files**
|
||||
|
||||
In some cases this can be acceptable, but for most projects you will want to extend the sample upload handlers to integrate user authentication, or implement your own.
|
||||
|
||||
It is also up to you to configure your Webserver to securely serve the uploaded files, e.g. using the [sample server configurations](#secure-file-upload-serving-configurations).
|
||||
|
||||
## Mitigations against file upload risks
|
||||
|
||||
### Prevent code execution on the server
|
||||
To prevent execution of scripts or binaries on server-side, the upload directory must be configured to not execute files in the upload directory (e.g. `server/php/files` as the default for the PHP upload handler) and only treat uploaded files as static content.
|
||||
|
||||
The recommended way to do this is to configure the upload directory path to point outside of the web application root.
|
||||
Then the Webserver can be configured to serve files from the upload directory with their default static files handler only.
|
||||
|
||||
Limiting file uploads to a whitelist of safe file types (e.g. image files) also mitigates this issue, but should not be the only protection.
|
||||
|
||||
### Prevent code execution in the browser
|
||||
To prevent execution of scripts on client-side, the following headers must
|
||||
be sent when delivering generic uploaded files to the client:
|
||||
|
||||
```
|
||||
Content-Type: application/octet-stream
|
||||
X-Content-Type-Options: nosniff
|
||||
```
|
||||
|
||||
The `Content-Type: application/octet-stream` header instructs browsers to display a download dialog instead of parsing it and possibly executing script content e.g. in HTML files.
|
||||
|
||||
The `X-Content-Type-Options: nosniff` header prevents browsers to try to detect the file mime type despite the given content-type header.
|
||||
|
||||
For known safe files, the content-type header can be adjusted using a **whitelist**, e.g. sending `Content-Type: image/png` for PNG files.
|
||||
|
||||
### Prevent distribution of malware
|
||||
To prevent attackers from uploading and distributing malware (e.g. computer viruses), it is recommended to limit file uploads only to a whitelist of safe file types.
|
||||
|
||||
Please note that the detection of file types in the sample file upload handlers is based on the file extension and not the actual file content. This makes it still possible for attackers to upload malware by giving their files an image file extension, but should prevent automatic execution on client computers when opening those files.
|
||||
|
||||
It does not protect at all from exploiting vulnerabilities in image display programs, nor from users renaming file extensions to inadvertently execute the contained malicious code.
|
||||
|
||||
## Secure file upload serving configurations
|
||||
The following configurations serve uploaded files as static files with the proper headers as [mitigation against file upload risks](#mitigations-against-file-upload-risks).
|
||||
Please do not simply copy&paste these configurations, but make sure you understand what they are doing and that you have implemented them correctly.
|
||||
|
||||
> Always test your own setup and make sure that it is secure!
|
||||
|
||||
e.g. try uploading PHP scripts (as "example.php", "example.php.png" and "example.png") to see if they get executed by your Webserver.
|
||||
|
||||
### Apache config
|
||||
Add the following directive to the Apache config, replacing the directory path with the absolute path to the upload directory:
|
||||
|
||||
```ApacheConf
|
||||
<Directory "/path/to/project/server/php/files">
|
||||
# To enable the Headers module, execute the following command and reload Apache:
|
||||
# sudo a2enmod headers
|
||||
|
||||
# The following directives prevent the execution of script files
|
||||
# in the context of the website.
|
||||
# They also force the content-type application/octet-stream and
|
||||
# force browsers to display a download dialog for non-image files.
|
||||
SetHandler default-handler
|
||||
ForceType application/octet-stream
|
||||
Header set Content-Disposition attachment
|
||||
|
||||
# The following unsets the forced type and Content-Disposition headers
|
||||
# for known image files:
|
||||
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
|
||||
ForceType none
|
||||
Header unset Content-Disposition
|
||||
</FilesMatch>
|
||||
|
||||
# The following directive prevents browsers from MIME-sniffing the content-type.
|
||||
# This is an important complement to the ForceType directive above:
|
||||
Header set X-Content-Type-Options nosniff
|
||||
</Directory>
|
||||
```
|
||||
|
||||
### NGINX config
|
||||
Add the following directive to the NGINX config, replacing the directory path with the absolute path to the upload directory:
|
||||
|
||||
```Nginx
|
||||
location ^~ /path/to/project/server/php/files {
|
||||
root html;
|
||||
default_type application/octet-stream;
|
||||
types {
|
||||
image/gif gif;
|
||||
image/jpeg jpg;
|
||||
image/png png;
|
||||
}
|
||||
add_header X-Content-Type-Options 'nosniff';
|
||||
if ($request_filename ~ /(((?!\.(jpg)|(png)|(gif)$)[^/])+$)) {
|
||||
add_header Content-Disposition 'attachment; filename="$1"';
|
||||
# Add X-Content-Type-Options again, as using add_header in a new context
|
||||
# dismisses all previous add_header calls:
|
||||
add_header X-Content-Type-Options 'nosniff';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Secure image processing configurations
|
||||
The following configuration mitigates [potential image processing vulnerabilities with ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick) by limiting the attack vectors to a small subset of image types (`GIF/JPEG/PNG`).
|
||||
|
||||
Please also consider using alternative, safer image processing libraries like [libvips](https://github.com/libvips/libvips) or [imageflow](https://github.com/imazen/imageflow).
|
||||
|
||||
## ImageMagick config
|
||||
It is recommended to disable all non-required ImageMagick coders via [policy.xml](https://wiki.debian.org/imagemagick/security).
|
||||
To do so, locate the ImageMagick `policy.xml` configuration file and add the following policies:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- ... -->
|
||||
<policymap>
|
||||
<!-- ... -->
|
||||
<policy domain="delegate" rights="none" pattern="*" />
|
||||
<policy domain="coder" rights="none" pattern="*" />
|
||||
<policy domain="coder" rights="read | write" pattern="{GIF,JPEG,PNG}" />
|
||||
</policymap>
|
||||
```
|
||||
65
vendor/blueimp/jquery-file-upload/VULNERABILITIES.md
vendored
Normal file
65
vendor/blueimp/jquery-file-upload/VULNERABILITIES.md
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# ⚠️ List of fixed vulnerabilities
|
||||
|
||||
## Potential vulnerabilities with PHP+ImageMagick
|
||||
> Mitigated: 2018-10-25 (GMT)
|
||||
|
||||
The sample [PHP upload handler](server/php/UploadHandler.php) before [v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1) did not validate file signatures before invoking [ImageMagick](https://www.imagemagick.org/) (via [Imagick](http://php.net/manual/en/book.imagick.php)).
|
||||
Verifying those [magic bytes](https://en.wikipedia.org/wiki/List_of_file_signatures) mitigates potential vulnerabilities when handling input files other than `GIF/JPEG/PNG`.
|
||||
|
||||
Please also configure ImageMagick to only enable the coders required for `GIF/JPEG/PNG` processing, e.g. with the sample [ImageMagick config](SECURITY.md#imagemagick-config).
|
||||
|
||||
**Further information:**
|
||||
* Commit containing the mitigation: [fe44d34](https://github.com/blueimp/jQuery-File-Upload/commit/fe44d34be43be32c6b8d507932f318dababb25dd)
|
||||
* [ImageTragick](https://imagetragick.com/)
|
||||
* [CERT Vulnerability Note VU#332928](https://www.kb.cert.org/vuls/id/332928)
|
||||
* [ImageMagick CVE entries](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=imagemagick)
|
||||
|
||||
## Remote code execution vulnerability in the PHP component
|
||||
> Fixed: 2018-10-23 (GMT)
|
||||
|
||||
The sample [PHP upload handler](server/php/UploadHandler.php) before [v9.24.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.24.1) allowed to upload all file types by default.
|
||||
This opens up a remote code execution vulnerability, unless the server is configured to not execute (PHP) files in the upload directory (`server/php/files`).
|
||||
|
||||
The provided [.htaccess](server/php/files/.htaccess) file includes instructions for Apache to disable script execution, however [.htaccess support](https://httpd.apache.org/docs/current/howto/htaccess.html) is disabled by default since Apache `v2.3.9` via [AllowOverride Directive](https://httpd.apache.org/docs/current/mod/core.html#allowoverride).
|
||||
|
||||
**You are affected if you:**
|
||||
1. A) Uploaded jQuery File Upload < `v9.24.1` on a Webserver that executes files with `.php` as part of the file extension (e.g. "example.php.png"), e.g. Apache with `mod_php` enabled and the following directive (*not a recommended configuration*):
|
||||
```ApacheConf
|
||||
AddHandler php5-script .php
|
||||
```
|
||||
B) Uploaded jQuery File Upload < `v9.22.1` on a Webserver that executes files with the file extension `.php`, e.g. Apache with `mod_php` enabled and the following directive:
|
||||
```ApacheConf
|
||||
<FilesMatch \.php$>
|
||||
SetHandler application/x-httpd-php
|
||||
</FilesMatch>
|
||||
```
|
||||
2. Did not actively configure your Webserver to not execute files in the upload directory (`server/php/files`).
|
||||
3. Are running Apache `v2.3.9+` with the default `AllowOverride` Directive set to `None` or another Webserver with no `.htaccess` support.
|
||||
|
||||
**How to fix it:**
|
||||
1. Upgrade to the latest version of jQuery File Upload.
|
||||
2. Configure your Webserver to not execute files in the upload directory, e.g. with the [sample Apache configuration](SECURITY.md#apache-config)
|
||||
|
||||
**Further information:**
|
||||
* Commits containing the security fix: [aeb47e5](https://github.com/blueimp/jQuery-File-Upload/commit/aeb47e51c67df8a504b7726595576c1c66b5dc2f), [ad4aefd](https://github.com/blueimp/jQuery-File-Upload/commit/ad4aefd96e4056deab6fea2690f0d8cf56bb2d7d)
|
||||
* [Full disclosure post on Hacker News](https://news.ycombinator.com/item?id=18267309).
|
||||
* [CVE-2018-9206](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9206)
|
||||
* [OWASP - Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload)
|
||||
|
||||
## Open redirect vulnerability in the GAE components
|
||||
> Fixed: 2015-06-12 (GMT)
|
||||
|
||||
The sample Google App Engine upload handlers before v[9.10.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/9.10.1) accepted any URL as redirect target, making it possible to use the Webserver's domain for phishing attacks.
|
||||
|
||||
**Further information:**
|
||||
* Commit containing the security fix: [f74d2a8](https://github.com/blueimp/jQuery-File-Upload/commit/f74d2a8c3e3b1e8e336678d2899facd5bcdb589f)
|
||||
* [OWASP - Unvalidated Redirects and Forwards Cheat Sheet](https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet)
|
||||
|
||||
## Cross-site scripting vulnerability in the Iframe Transport
|
||||
> Fixed: 2012-08-09 (GMT)
|
||||
|
||||
The [redirect page](cors/result.html) for the [Iframe Transport](js/jquery.iframe-transport.js) before commit [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a) (*fixed in all tagged releases*) allowed executing arbitrary JavaScript in the context of the Webserver.
|
||||
|
||||
**Further information:**
|
||||
* Commit containing the security fix: [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a)
|
||||
* [OWASP - Cross-site Scripting (XSS)](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS))
|
||||
@@ -22,7 +22,7 @@
|
||||
<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- Bootstrap styles -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<!-- Generic page styles -->
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<!-- blueimp Gallery styles -->
|
||||
@@ -177,8 +177,8 @@
|
||||
<a class="play-pause"></a>
|
||||
<ol class="indicator"></ol>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" integrity="sha384-r6jjWwxAypHaESwS5an5J9dkfzwQuKVNV9FZM9B6fnt8PFuY0cVwLhV7BltCZhLy" crossorigin="anonymous"></script>
|
||||
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
|
||||
<script src="js/vendor/jquery.ui.widget.js"></script>
|
||||
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
|
||||
@@ -186,7 +186,7 @@
|
||||
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
|
||||
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
|
||||
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<!-- blueimp Gallery script -->
|
||||
<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
|
||||
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
|
||||
@@ -20,7 +20,7 @@
|
||||
<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- Bootstrap styles -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<!-- Generic page styles -->
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
|
||||
@@ -96,15 +96,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
|
||||
<script src="js/vendor/jquery.ui.widget.js"></script>
|
||||
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
|
||||
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
|
||||
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
|
||||
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
|
||||
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
|
||||
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
|
||||
<script src="js/jquery.iframe-transport.js"></script>
|
||||
<!-- The basic File Upload plugin -->
|
||||
@@ -20,7 +20,7 @@
|
||||
<meta name="description" content="File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- Bootstrap styles -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<!-- Generic page styles -->
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
|
||||
@@ -96,7 +96,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
|
||||
<script src="js/vendor/jquery.ui.widget.js"></script>
|
||||
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
|
||||
@@ -104,7 +104,7 @@
|
||||
<!-- The basic File Upload plugin -->
|
||||
<script src="js/jquery.fileupload.js"></script>
|
||||
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
/*jslint unparam: true */
|
||||
/*global window, $ */
|
||||
0
library/blueimp_upload/bower-version-update.js → vendor/blueimp/jquery-file-upload/bower-version-update.js
vendored
Executable file → Normal file
0
library/blueimp_upload/bower-version-update.js → vendor/blueimp/jquery-file-upload/bower-version-update.js
vendored
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blueimp-file-upload",
|
||||
"version": "9.23.0",
|
||||
"version": "9.28.0",
|
||||
"title": "jQuery File Upload",
|
||||
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images.",
|
||||
"keywords": [
|
||||
39
vendor/blueimp/jquery-file-upload/composer.json
vendored
Normal file
39
vendor/blueimp/jquery-file-upload/composer.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "blueimp/jquery-file-upload"
|
||||
, "description": "File Upload widget for jQuery."
|
||||
, "keywords": ["jquery",
|
||||
"file",
|
||||
"upload",
|
||||
"widget",
|
||||
"multiple",
|
||||
"selection",
|
||||
"drag",
|
||||
"drop",
|
||||
"progress",
|
||||
"preview",
|
||||
"cross-domain",
|
||||
"cross-site",
|
||||
"chunk",
|
||||
"resume",
|
||||
"gae",
|
||||
"go",
|
||||
"python",
|
||||
"php",
|
||||
"bootstrap"]
|
||||
, "homepage": "https://github.com/blueimp/jQuery-File-Upload"
|
||||
, "authors": [
|
||||
{
|
||||
"name": "Sebastian Tschan",
|
||||
"homepage": "https://blueimp.net"
|
||||
}
|
||||
]
|
||||
, "support": {
|
||||
"forum": "https://groups.google.com/forum/#!forum/jquery-fileupload"
|
||||
}
|
||||
, "license": "MIT"
|
||||
, "autoload": {
|
||||
"classmap": [
|
||||
"server/php/UploadHandler.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery File Upload Plugin postMessage API</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
@@ -22,7 +22,7 @@
|
||||
<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- Bootstrap styles -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<!-- Generic page styles -->
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<!-- blueimp Gallery styles -->
|
||||
@@ -216,7 +216,7 @@
|
||||
</tr>
|
||||
{% } %}
|
||||
</script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
|
||||
<script src="js/vendor/jquery.ui.widget.js"></script>
|
||||
<!-- The Templates plugin is included to render the upload/download listings -->
|
||||
@@ -226,7 +226,7 @@
|
||||
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
|
||||
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
|
||||
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<!-- blueimp Gallery script -->
|
||||
<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
|
||||
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
|
||||
@@ -22,7 +22,7 @@
|
||||
<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- jQuery UI styles -->
|
||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/dark-hive/jquery-ui.css" id="theme">
|
||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/dark-hive/jquery-ui.css" integrity="sha384-ufZtQaOYGuy/CibAC5jmelOpBu3H78Js7HrXSLo4LGccHUrGGHXt+uaTcDbio3kI" crossorigin="anonymous">
|
||||
<!-- Generic page styles -->
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<!-- Demo styles -->
|
||||
@@ -201,8 +201,8 @@
|
||||
</tr>
|
||||
{% } %}
|
||||
</script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha384-Dziy8F2VlJQLMShA6FHWNul/veM9bCkRUaLqr199K94ntO5QUrLJBEbYegdSkkqX" crossorigin="anonymous"></script>
|
||||
<!-- The Templates plugin is included to render the upload/download listings -->
|
||||
<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
|
||||
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blueimp-file-upload",
|
||||
"version": "9.23.0",
|
||||
"version": "9.28.0",
|
||||
"title": "jQuery File Upload",
|
||||
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
|
||||
"keywords": [
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user