Compare commits

...

55 Commits
7.2.1 ... 7.4

Author SHA1 Message Date
Mario
e63f043841 Merge branch '7.4RC' 2022-06-01 07:00:21 +00:00
Mario
33dd0c83e3 version 7.4 2022-06-01 06:59:23 +00:00
Mario
32dad136f8 Merge branch 'dev' into 7.4RC 2022-06-01 06:58:19 +00:00
Mario
073ed52538 update changelog 2022-06-01 06:58:05 +00:00
Mario
eef828cf3e fix version after merge 2022-05-31 09:38:54 +00:00
Mario
d0b5930a3a Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2022-05-31 08:42:54 +00:00
Mario
c66ad9ccc8 update changelog 2022-05-31 08:42:27 +00:00
Max Kostikov
9959a15c8e Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!2019
2022-05-28 13:31:24 +00:00
Max Kostikov
f0e4b4dc84 Update Russian translation 2022-05-28 15:28:40 +02:00
Mario
f62f808368 bump dev version 2022-05-25 08:45:21 +00:00
Mario
530a521679 version and strings 2022-05-25 08:41:25 +00:00
Mario
50782dfb83 prevent php error and add some doco 2022-05-25 08:34:29 +00:00
Mario
27a142d5c5 cleanup 2022-05-25 08:17:37 +00:00
Mario
6d00b2e63d bump php version requirement 2022-05-25 08:14:59 +00:00
hubzilla
7be1415a3a Merge pull request 'Update Spanish' (#11) from mjfriaza/hubzilla:dev into dev
Reviewed-on: https://codeberg.org/hubzilla/hubzilla/pulls/11
2022-05-25 09:54:22 +02:00
Mario
0a30b12f7d move wiki related templates to addon 2022-05-25 07:02:15 +00:00
Mario
3058cbfbb2 categories widgets cleanup 2022-05-24 09:31:30 +00:00
Mario
ae780c977b move article and card categories widgets to addons 2022-05-24 09:18:41 +00:00
Mario
e146a67f4b fix photo permission if a photo description is available and use the filename as default photo description if uploading via the editor 2022-05-23 18:56:09 +00:00
Mario
162d86983a streamline inbound attachment handling and fix regression from issue #1679 2022-05-23 09:26:29 +00:00
Mario
8534366a31 move photo flag feature entry to core 2022-05-21 08:25:14 +00:00
Mario
d1c6617dc9 missing files after composer updates 2022-05-20 09:21:23 +00:00
Mario
6f994709b9 do not show deprecated warnings by default 2022-05-19 08:27:09 +00:00
Mario
55d833a9c8 update composer libs 2022-05-19 08:18:15 +00:00
Mario
8ba4745097 update to remove core apps (wiki, cards, articles) which have been moved to addons 2022-05-19 08:04:39 +00:00
Mario
940a0c8b10 add a hidden config for the hs2019 http sig algo 2022-05-19 07:36:57 +00:00
Mario
8928b24e23 rendering fixes 2022-05-19 07:22:10 +00:00
Mario
ae9a9191f3 implement starring of pubstream items 2022-05-18 08:47:45 +00:00
mjfriaza
cb553bd016 Update Spanish 2022-05-17 14:01:28 +02:00
mjfriaza
a75c61d71e Merge remote-tracking branch 'upstream/dev' into dev 2022-05-17 13:44:06 +02:00
Mario
c1dc16a89d make sure we use source.content when rendering events to correctly render observer related content. fix wrong media types. 2022-05-16 20:44:53 +00:00
Mario
66436ce4a2 fix php errors 2022-05-14 19:04:05 +00:00
Mario
62b1ff4ba1 add the title in forum post reshares 2022-05-14 18:30:39 +00:00
Mario
304d136437 do not set allowed to true if verb is ACTIVITY_SHARE and slightly changed logic for conv fetches 2022-05-13 19:13:47 +00:00
Mario
1b4268b9b0 do not stringify integer value 2022-05-11 11:52:22 +00:00
Mario
a7968e6525 update queries in mod search - fixes #1677 2022-05-11 11:50:29 +00:00
Mario
e59cc3d404 deal with pleroma reactions 2022-05-10 12:15:29 +00:00
Mario
3a2d126877 use rev instead of _updated and the unix timestamp is less likely to cause issues in the future 2022-05-09 08:27:50 +00:00
Mario
ee3d6fcfee use addr for webfinger and name for the real name in the userinfo array 2022-05-09 08:23:55 +00:00
Mario
09d929bd56 add the update date to the icon url. some platforms will not update if the icon url remains static 2022-05-07 13:42:14 +00:00
Mario
bd55ae15f2 cleanup channel apps 2022-05-07 07:09:31 +00:00
Mario
2ca80118bf more cleanup 2022-05-06 19:10:28 +00:00
Mario
04eb20ac35 some cleanup after moving articles and cards to addons 2022-05-06 14:58:27 +00:00
Mario
f299391aa1 fix core issue #1676 and a liked/disliked/commented confusion 2022-05-06 08:24:17 +00:00
Mario
c334fc9d22 move wiki to addons 2022-05-06 07:29:59 +00:00
Mario
8520088376 move articles to addon - also remove the pdl 2022-05-04 19:26:45 +00:00
Mario
9ada8518dc move articles to addon 2022-05-04 19:26:05 +00:00
Mario
f0c09b374c move cards to addon 2022-05-04 18:46:45 +00:00
Mario Vavti
c5f33baf27 version 7.2.2 2022-04-26 11:12:43 +02:00
Mario Vavti
2efcdd92e0 Merge branch 'dev' 2022-04-26 11:11:53 +02:00
Mario Vavti
38fda98b6d changelog and version 2022-04-26 11:11:17 +02:00
Mario Vavti
f9fd195c24 Merge branch 'dev' 2022-04-26 11:08:10 +02:00
Mario Vavti
01e82090b2 hubloc in AS has been moved from data to meta a while ago 2022-04-26 11:07:23 +02:00
Mario Vavti
39602ede37 version bump 2022-04-25 22:53:04 +02:00
mjfriaza
481ecee9e8 Update Spanish 2021-06-01 11:57:11 +02:00
439 changed files with 25389 additions and 43028 deletions

View File

@@ -1,3 +1,41 @@
Hubzilla 7.4 (2022-06-01)
Updated russian translations
Raise min PHP version to 8.0
Rewrite inbound attachment handling
Move photo flag feature from addon to core
Adjust default production php logging
Update composer libs
Add a hidden config to enable the hs2019 http signature algorithm
Allow starring of pubstream items
Update spanish translations
Add the title in forum post reshares if applicable
Implement inbound pleroma reactions
Add real name info to the navbar template data
Add the updated date to the icon url so that other platforms will pick it up on change
Move wiki from core to addon
Move articles from core to addon
Move cards from core to addon
Addons
Rendezvous: add missing default value to sql schema
Wiki: moved from core to addons
Articles: moved from core to addons
Cards: moved from core to addons
Photoflag: moved to core
Sse: fix issue where notifications were emited for created tasks
Bugfixes
- Fix issue where inbound activitypub items lost image descriptions (issue 1679)
- Fix issue where observer tags were not rendered correctly in event items (issue 1674)
- Fix forum posts leaked into network stream
- Fix tags not found in search if not logged in (issue 1677)
- Fix dislikes causing stuck notifications (issue 1676)
Hubzilla 7.2.2 (2022-04-26)
- Fix item_verified not set due to data structure changes
Hubzilla 7.2.1 (2022-04-25)
- Fix changing profile image from new member widget - issue #1671
- Fix regression with incoming poll answers from activitypub introduced in 7.2

View File

@@ -670,24 +670,36 @@ class Activity {
return $ret;
}
static function decode_attachment($item) {
public static function decode_attachment($item) {
$ret = [];
if (array_key_exists('attachment', $item) && is_array($item['attachment'])) {
foreach ($item['attachment'] as $att) {
$entry = [];
if (array_key_exists('href', $att))
$entry['href'] = $att['href'];
elseif (array_key_exists('url', $att))
$entry['href'] = $att['url'];
if (array_key_exists('mediaType', $att))
$entry['type'] = $att['mediaType'];
elseif (array_key_exists('type', $att) && $att['type'] === 'Image')
$entry['type'] = 'image/jpeg';
if ($entry)
$ret[] = $entry;
$ptr = $item['attachment'];
if (!array_key_exists(0, $ptr)) {
$ptr = [$ptr];
}
foreach ($ptr as $att) {
$entry = [];
if (array_key_exists('href', $att) && $att['href']) {
$entry['href'] = $att['href'];
} elseif (array_key_exists('url', $att) && $att['url']) {
$entry['href'] = $att['url'];
}
if (array_key_exists('mediaType', $att) && $att['mediaType']) {
$entry['type'] = $att['mediaType'];
} elseif (array_key_exists('type', $att) && $att['type'] === 'Image') {
$entry['type'] = 'image/jpeg';
}
if (array_key_exists('name', $att) && $att['name']) {
$entry['name'] = html2plain(purify_html($att['name']), 256);
}
if ($entry) {
$ret[] = $entry;
}
}
} elseif (isset($item['attachment']) && is_string($item['attachment'])) {
btlogger('not an array: ' . $item['attachment']);
}
return $ret;
@@ -1013,7 +1025,7 @@ class Activity {
'type' => 'Image',
'mediaType' => (($p['xchan_photo_mimetype']) ? $p['xchan_photo_mimetype'] : 'image/png'),
'updated' => datetime_convert('UTC', 'UTC', $p['xchan_photo_date'], ATOM_TIME),
'url' => $p['xchan_photo_l'],
'url' => $p['xchan_photo_l'] . '?rev=' . strtotime($p['xchan_photo_date']),
'height' => 300,
'width' => 300,
];
@@ -2195,20 +2207,20 @@ class Activity {
$s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
$s['commented'] = $s['created'];
}
elseif (array_key_exists('published', $act->obj)) {
elseif (is_array($act->obj) && array_key_exists('published', $act->obj)) {
$s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
$s['commented'] = $s['created'];
}
if (array_key_exists('updated', $act->data)) {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->data['updated']);
}
elseif (array_key_exists('updated', $act->obj)) {
elseif (is_array($act->obj) && array_key_exists('updated', $act->obj)) {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->obj['updated']);
}
if (array_key_exists('expires', $act->data)) {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->data['expires']);
}
elseif (array_key_exists('expires', $act->obj)) {
elseif (is_array($act->obj) && array_key_exists('expires', $act->obj)) {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
}
@@ -2270,9 +2282,18 @@ class Activity {
$s['mid'] = $act->obj['id'];
$s['parent_mid'] = $act->obj['id'];
}
if ($act->type === 'emojiReaction') {
$content['content'] = (($act->tgt && $act->tgt['type'] === 'Image') ? '[img=32x32]' . $act->tgt['url'] . '[/img]' : '&#x' . $act->tgt['name'] . ';');
}
if (in_array($act->type, ['EmojiReaction', 'EmojiReact'])) {
// Pleroma reactions
$t = trim(self::get_textfield($act->data, 'content'));
if (mb_strlen($t) === 1) {
$content['content'] = $t;
}
}
}
$s['item_thread_top'] = 0;
@@ -2408,7 +2429,6 @@ class Activity {
}
}
}
}
$a = self::decode_attachment($act->obj);
@@ -2423,8 +2443,11 @@ class Activity {
if (array_key_exists('type', $act->obj)) {
if ($act->obj['type'] === 'Note' && $s['attach']) {
$s['body'] = self::bb_attach($s['attach'], $s['body']) . $s['body'];
// Objects that might have media attachments which aren't already provided in the content element.
// We'll check specific media objects separately.
if (in_array($act->obj['type'], ['Article', 'Document', 'Event', 'Note', 'Page', 'Place', 'Question']) && isset($s['attach']) && $s['attach']) {
$s = self::bb_attach($s);
}
if ($act->obj['type'] === 'Question' && in_array($act->type, ['Create', 'Update'])) {
@@ -2513,13 +2536,13 @@ class Activity {
usort($mps,[ '\Zotlabs\Lib\Activity', 'vid_sort' ]);
foreach ($mps as $m) {
if (intval($m['height']) < 500 && Activity::media_not_in_body($m['href'],$s['body'])) {
$s['body'] = $tag . $m['href'] . '[/video]' . "\n\n" . $s['body'];
$s['body'] = $tag . $m['href'] . '[/video]' . "\r\n" . $s['body'];
break;
}
}
}
elseif (is_string($act->obj['url']) && Activity::media_not_in_body($act->obj['url'],$s['body'])) {
$s['body'] = $tag . $act->obj['url'] . '[/video]' . "\n\n" . $s['body'];
$s['body'] = $tag . $act->obj['url'] . '[/video]' . "\r\n" . $s['body'];
}
}
@@ -2545,13 +2568,13 @@ class Activity {
}
foreach ($ptr as $vurl) {
if (in_array($vurl['mediaType'], $atypes) && self::media_not_in_body($vurl['href'], $s['body'])) {
$s['body'] = '[audio]' . $vurl['href'] . '[/audio]' . "\n\n" . $s['body'];
$s['body'] = '[audio]' . $vurl['href'] . '[/audio]' . "\r\n" . $s['body'];
break;
}
}
}
elseif (is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'], $s['body'])) {
$s['body'] = '[audio]' . $act->obj['url'] . '[/audio]' . "\n\n" . $s['body'];
$s['body'] = '[audio]' . $act->obj['url'] . '[/audio]' . "\r\n" . $s['body'];
}
}
@@ -2571,7 +2594,7 @@ class Activity {
}
foreach ($ptr as $vurl) {
if (strpos($s['body'], $vurl['href']) === false) {
$bb_imgs = '[zmg]' . $vurl['href'] . '[/zmg]' . "\n\n";
$bb_imgs = '[zmg]' . $vurl['href'] . '[/zmg]' . "\r\n";
break;
}
}
@@ -2579,7 +2602,7 @@ class Activity {
}
elseif (is_string($act->obj['url'])) {
if (strpos($s['body'], $act->obj['url']) === false) {
$s['body'] .= '[zmg]' . $act->obj['url'] . '[/zmg]' . "\n\n" . $s['body'];
$s['body'] .= '[zmg]' . $act->obj['url'] . '[/zmg]' . "\r\n" . $s['body'];
}
}
}
@@ -2616,10 +2639,10 @@ class Activity {
if ($purl) {
$li = z_fetch_url(z_root() . '/linkinfo?binurl=' . bin2hex($purl));
if ($li['success'] && $li['body']) {
$s['body'] .= "\n" . $li['body'];
$s['body'] .= "\r\n" . $li['body'];
}
else {
$s['body'] .= "\n\n" . $purl;
$s['body'] .= "\r\n" . $purl;
}
}
}
@@ -3574,38 +3597,76 @@ class Activity {
return;
}
static function bb_attach($attach, $body) {
public static function bb_attach($item) {
$ret = false;
foreach ($attach as $a) {
if (!(is_array($item['attach']) && $item['attach'])) {
return $item;
}
foreach ($item['attach'] as $a) {
if (array_key_exists('type', $a) && stripos($a['type'], 'image') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
// don't add inline image if it's an svg and we already have an inline svg
if ($a['type'] === 'image/svg+xml' && strpos($item['body'], '[/svg]')) {
continue;
}
if (self::media_not_in_body($a['href'], $item['body'])) {
if (isset($a['name']) && $a['name']) {
$alt = htmlspecialchars($a['name'], ENT_QUOTES);
$item['body'] = '[img=' . $a['href'] . ']' . $alt . '[/img]' . "\r\n" . $item['body'];
} else {
$item['body'] = '[img]' . $a['href'] . '[/img]' . "\r\n" . $item['body'];
}
}
}
if (array_key_exists('type', $a) && stripos($a['type'], 'video') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[video]' . $a['href'] . '[/video]';
if (self::media_not_in_body($a['href'], $item['body'])) {
$item['body'] = '[video]' . $a['href'] . '[/video]' . "\r\n" . $item['body'];
}
}
if (array_key_exists('type', $a) && stripos($a['type'], 'audio') !== false) {
if (self::media_not_in_body($a['href'], $body)) {
$ret .= "\n\n" . '[audio]' . $a['href'] . '[/audio]';
if (self::media_not_in_body($a['href'], $item['body'])) {
$item['body'] = '[audio]' . $a['href'] . '[/audio]' . "\r\n" . $item['body'];
}
}
//if (array_key_exists('type', $a) && stripos($a['type'], 'activity') !== false) {
//if (self::media_not_in_body($a['href'], $item['body'])) {
//$item = self::get_quote($a['href'], $item);
//}
//}
}
return $ret;
return $item;
}
// check for the existence of existing media link in body
static function media_not_in_body($s, $body) {
if ((strpos($body, ']' . $s . '[/img]') === false) &&
// check for the existence of existing media link in body
public static function media_not_in_body($s, $body) {
$s_alt = htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
if (
(strpos($body, ']' . $s . '[/img]') === false) &&
(strpos($body, '[img=' . $s . ']') === false) &&
(strpos($body, ']' . $s . '[/zmg]') === false) &&
(strpos($body, '[zmg=' . $s . ']') === false) &&
(strpos($body, ']' . $s . '[/video]') === false) &&
(strpos($body, ']' . $s . '[/audio]') === false)) {
(strpos($body, ']' . $s . '[/zvideo]') === false) &&
(strpos($body, ']' . $s . '[/audio]') === false) &&
(strpos($body, ']' . $s . '[/zaudio]') === false) &&
(strpos($body, ']' . $s_alt . '[/img]') === false) &&
(strpos($body, '[img=' . $s_alt . ']') === false) &&
(strpos($body, ']' . $s_alt . '[/zmg]') === false) &&
(strpos($body, '[zmg=' . $s_alt . ']') === false) &&
(strpos($body, ']' . $s_alt . '[/video]') === false) &&
(strpos($body, ']' . $s_alt . '[/zvideo]') === false) &&
(strpos($body, ']' . $s_alt . '[/audio]') === false) &&
(strpos($body, ']' . $s_alt . '[/zaudio]') === false)
) {
return true;
}
return false;

View File

@@ -70,9 +70,12 @@ class ActivityStreams {
}
}
// This indicates only that we have sucessfully decoded JSON.
$this->valid = true;
if (array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
// Special handling for Mastodon "delete actor" activities which will often fail to verify
// because the key cannot be fetched. We will catch this condition elsewhere.
if (is_array($this->data) && array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor'];
$this->valid = false;
@@ -81,6 +84,7 @@ class ActivityStreams {
}
// Attempt to assemble an Activity from what we were given.
if ($this->is_valid()) {
$this->id = $this->get_property_obj('id');
$this->type = $this->get_primary_type();

View File

@@ -256,8 +256,8 @@ class Enotify {
$itemlink = $params['link'];
if (array_key_exists('item',$params) && activity_match($params['item']['verb'],ACTIVITY_LIKE)) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ACTIVITY_LIKE) || activity_match($params['item']['verb'], ACTIVITY_DISLIKE))) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE) || !feature_enabled($recip['channel_id'], 'dislike')) {
logger('notification: not a visible activity. Ignoring.');
pop_lang();
return;
@@ -291,22 +291,29 @@ class Enotify {
);
}
if (!$p) {
pop_lang();
return;
}
xchan_query($p);
//@@FIXME $p can be null (line 285)
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
$parent_item = $p[0];
$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
// "your post"
if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
$dest_str = sprintf(t('%1$s liked [zrl=%2$s]your %3$s[/zrl]'),
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$verb,
$itemlink,
$item_post_type);
$item_post_type
);
else {
pop_lang();
return;
@@ -824,6 +831,14 @@ class Enotify {
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
}
if($item['verb'] === ACTIVITY_LIKE) {
$itemem_text = sprintf( t('liked %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
}
if($item['verb'] === ACTIVITY_DISLIKE) {
$itemem_text = sprintf( t('disliked %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
}
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
$itemem_text = t('shared a file with you');
}

View File

@@ -1292,7 +1292,7 @@ class Libzot {
}
}
if ($AS->data['hubloc']) {
if ($AS->meta['hubloc']) {
$arr['item_verified'] = true;
}
@@ -1627,7 +1627,7 @@ class Libzot {
// doesn't exist.
if ($perm === 'send_stream') {
if ($force || get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false) || $arr['verb'] === ACTIVITY_SHARE) {
if ($force || get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false)) {
$allowed = true;
}
}
@@ -1673,6 +1673,10 @@ class Libzot {
$DR->update('comment parent not found');
$result[] = $DR->get();
if ($relay || $request || $local_public) {
continue;
}
// We don't seem to have a copy of this conversation or at least the parent
// - so request a copy of the entire conversation to date.
// Don't do this if it's a relay post as we're the ones who are supposed to
@@ -1684,10 +1688,10 @@ class Libzot {
// the top level post is unlikely to be imported and
// this is just an exercise in futility.
if ((!$relay) && (!$request) && (!$local_public)
&& perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
if (perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
self::fetch_conversation($channel, $arr['parent_mid']);
}
continue;
}
@@ -2010,7 +2014,7 @@ class Libzot {
$arr['owner_xchan'] = $a['signature']['signer'];
}
if ($AS->data['hubloc'] || $arr['author_xchan'] === $arr['owner_xchan']) {
if ($AS->meta['hubloc'] || $arr['author_xchan'] === $arr['owner_xchan']) {
$arr['item_verified'] = true;
}

View File

@@ -8,7 +8,7 @@ class MessageFilter {
public static function evaluate($item, $incl, $excl) {
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/x-multicode'));
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/bbcode'));
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
$lang = null;

View File

@@ -1,322 +0,0 @@
<?php
namespace Zotlabs\Lib;
use Zotlabs\Lib\Libsync;
define ( 'NWIKI_ITEM_RESOURCE_TYPE', 'nwiki' );
class NativeWiki {
public static function listwikis($channel, $observer_hash) {
$sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
$wikis = q("SELECT * FROM item
WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
intval($channel['channel_id'])
);
if($wikis) {
foreach($wikis as &$w) {
$w['json_allow_cid'] = acl2json($w['allow_cid']);
$w['json_allow_gid'] = acl2json($w['allow_gid']);
$w['json_deny_cid'] = acl2json($w['deny_cid']);
$w['json_deny_gid'] = acl2json($w['deny_gid']);
$w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
$w['htmlName'] = escape_tags($w['rawName']);
//$w['urlName'] = urlencode(urlencode($w['rawName']));
$w['urlName'] = self::name_encode($w['rawName']);
$w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
$w['typelock'] = get_iconfig($w, 'wiki', 'typelock');
$w['lockstate'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? 'lock' : 'unlock');
}
}
// TODO: query db for wikis the observer can access. Return with two lists, for read and write access
return array('wikis' => $wikis);
}
public static function create_wiki($channel, $observer_hash, $wiki, $acl) {
$resource_id = new_uuid();
$uuid = new_uuid();
$ac = $acl->get();
$mid = z_root() . '/item/' . $uuid;
$arr = array(); // Initialize the array of parameters for the post
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
$arr['aid'] = $channel['channel_account_id'];
$arr['uuid'] = $uuid;
$arr['uid'] = $channel['channel_id'];
$arr['mid'] = $mid;
$arr['parent_mid'] = $mid;
$arr['item_hidden'] = $item_hidden;
$arr['resource_type'] = NWIKI_ITEM_RESOURCE_TYPE;
$arr['resource_id'] = $resource_id;
$arr['owner_xchan'] = $channel['channel_hash'];
$arr['author_xchan'] = $observer_hash;
$arr['plink'] = $mid;
$arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['title'] = $wiki['htmlName']; // name of new wiki;
$arr['allow_cid'] = $ac['allow_cid'];
$arr['allow_gid'] = $ac['allow_gid'];
$arr['deny_cid'] = $ac['deny_cid'];
$arr['deny_gid'] = $ac['deny_gid'];
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['item_private'] = intval($acl->is_private());
$arr['verb'] = ACTIVITY_CREATE;
$arr['obj_type'] = 'Document';
$arr['body'] = '[table][tr][td][h1]New Wiki[/h1][/td][/tr][tr][td][zrl=' . $wiki_url . ']' . $wiki['htmlName'] . '[/zrl][/td][/tr][/table]';
$arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_wiki'),true);
// Save the wiki name information using iconfig. This is shareable.
if(! set_iconfig($arr, 'wiki', 'rawName', $wiki['rawName'], true)) {
return array('item' => null, 'success' => false);
}
if(! set_iconfig($arr, 'wiki', 'mimeType', $wiki['mimeType'], true)) {
return array('item' => null, 'success' => false);
}
set_iconfig($arr,'wiki','typelock',$wiki['typelock'],true);
$post = item_store($arr);
$item_id = $post['item_id'];
if($item_id) {
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'activity', $item_id));
return array('item' => $post['item'], 'item_id' => $item_id, 'success' => true);
}
else {
return array('item' => null, 'success' => false);
}
}
public static function update_wiki($channel_id, $observer_hash, $arr, $acl) {
$w = self::get_wiki($channel_id, $observer_hash, $arr['resource_id']);
$item = $w['wiki'];
if(! $item) {
return array('item' => null, 'success' => false);
}
$x = $acl->get();
$item['allow_cid'] = $x['allow_cid'];
$item['allow_gid'] = $x['allow_gid'];
$item['deny_cid'] = $x['deny_cid'];
$item['deny_gid'] = $x['deny_gid'];
$item['item_private'] = intval($acl->is_private());
$update_title = false;
if($item['title'] !== $arr['updateRawName']) {
$update_title = true;
$item['title'] = $arr['updateRawName'];
}
$update = item_store_update($item);
$item_id = $update['item_id'];
// update acl for any existing wiki pages
q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d where resource_type = 'nwikipage' and resource_id = '%s'",
dbesc($item['allow_cid']),
dbesc($item['allow_gid']),
dbesc($item['deny_cid']),
dbesc($item['deny_gid']),
dbesc($item['item_private']),
dbesc($arr['resource_id'])
);
if($update['item_id']) {
info( t('Wiki updated successfully'));
if($update_title) {
// Update the wiki name information using iconfig.
if(! set_iconfig($update['item_id'], 'wiki', 'rawName', $arr['updateRawName'], true)) {
return array('item' => null, 'success' => false);
}
}
return array('item' => $update['item'], 'item_id' => $update['item_id'], 'success' => $update['success']);
}
else {
return array('item' => null, 'success' => false);
}
}
public static function sync_a_wiki_item($uid,$id,$resource_id) {
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ",
intval($uid),
intval($id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
if($r) {
$q = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s'",
dbesc($r[0]['resource_id'])
);
if($q) {
$r = array_merge($r,$q);
}
xchan_query($r);
$sync_item = fetch_post_tags($r);
if($sync_item) {
$pkt = [];
foreach($sync_item as $w) {
$pkt[] = encode_item($w,true);
}
Libsync::build_sync_packet($uid,array('wiki' => $pkt));
}
}
}
public static function delete_wiki($channel_id,$observer_hash,$resource_id) {
$w = self::get_wiki($channel_id,$observer_hash,$resource_id);
if(! $w['wiki']) {
return [ 'success' => false ];
}
else {
$r = q("SELECT id FROM item WHERE uid = %s AND resource_id = '%s'",
intval($channel_id),
dbesc($resource_id)
);
$ids = array_column($r, 'id');
drop_items($ids, true, DROPITEM_PHASE1);
info(t('Wiki files deleted successfully'));
return [ 'success' => true ];
}
}
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
$sql_extra ORDER BY id LIMIT 1",
intval($channel_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
if(! $item) {
return [ 'wiki' => null ];
}
else {
$w = $item[0]; // wiki item table record
// Get wiki metadata
$rawName = get_iconfig($w, 'wiki', 'rawName');
$mimeType = get_iconfig($w, 'wiki', 'mimeType');
$typelock = get_iconfig($w, 'wiki', 'typelock');
return array(
'wiki' => $w,
'rawName' => $rawName,
'htmlName' => escape_tags($rawName),
//'urlName' => urlencode(urlencode($rawName)),
'urlName' => self::name_encode($rawName),
'mimeType' => $mimeType,
'typelock' => $typelock
);
}
}
public static function exists_by_name($uid, $urlName) {
$sql_extra = item_permissions_sql($uid);
$item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
AND item_deleted = 0 $sql_extra limit 1",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
//dbesc(urldecode($urlName)),
dbesc(self::name_decode($urlName)),
intval($uid)
);
if($item) {
return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
}
else {
return array('id' => null, 'resource_id' => null);
}
}
public static function get_permissions($resource_id, $owner_id, $observer_hash) {
// TODO: For now, only the owner can edit
$sql_extra = item_permissions_sql($owner_id, $observer_hash);
if(local_channel() && local_channel() == $owner_id) {
return [ 'read' => true, 'write' => true, 'success' => true ];
}
$r = q("SELECT * FROM item WHERE uid = %d and resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
intval($owner_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
if(! $r) {
return array('read' => false, 'write' => false, 'success' => true);
}
else {
$write = perm_is_allowed($owner_id, $observer_hash,'write_wiki');
return array('read' => true, 'write' => $write, 'success' => true);
}
}
public static function name_encode ($string) {
$string = html_entity_decode($string);
$encoding = mb_internal_encoding();
mb_internal_encoding("UTF-8");
$ret = mb_ereg_replace_callback ('[^A-Za-z0-9\-\_\.\~]',function ($char) {
$charhex = unpack('H*',$char[0]);
$ret = '('.$charhex[1].')';
return $ret;
}
,$string);
mb_internal_encoding($encoding);
return $ret;
}
public static function name_decode ($string) {
$encoding = mb_internal_encoding();
mb_internal_encoding("UTF-8");
$ret = mb_ereg_replace_callback ('(\(([0-9a-f]+)\))',function ($chars) {
return pack('H*',$chars[2]);
}
,$string);
mb_internal_encoding($encoding);
return $ret;
}
}

View File

@@ -1,725 +0,0 @@
<?php
namespace Zotlabs\Lib;
use App;
use Zotlabs\Access\PermissionLimits;
class NativeWikiPage {
static public function page_list($channel_id, $observer_hash, $resource_id) {
// TODO: Create item table records for pages so that metadata like title can be applied
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$pages[] = [
'resource_id' => '',
'title' => 'Home',
'url' => 'Home',
'link_id' => 'id_wiki_home_0'
];
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
$sql_extra order by title asc",
dbesc($resource_id),
intval($channel_id)
);
if ($r) {
$x = [];
$y = [];
foreach ($r as $rv) {
if (!in_array($rv['mid'], $x)) {
$y[] = $rv;
$x[] = $rv['mid'];
}
}
$items = fetch_post_tags($y, true);
foreach ($items as $page_item) {
$title = get_iconfig($page_item['id'], 'nwikipage', 'pagetitle', t('(No Title)'));
if (urldecode($title) !== 'Home') {
$pages[] = [
'resource_id' => $resource_id,
'title' => escape_tags($title),
//'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
'url' => NativeWiki::name_encode($title),
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
];
}
}
}
return ['pages' => $pages, 'wiki' => $w];
}
static public function create_page($channel, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
logger('mimetype: ' . $mimetype);
if (!in_array($mimetype, ['text/markdown', 'text/bbcode', 'text/plain', 'text/html']))
$mimetype = 'text/markdown';
$w = NativeWiki::get_wiki($channel['channel_id'], $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
// backslashes won't work well in the javascript functions
$name = str_replace('\\', '', $name);
$uuid = new_uuid();
$mid = z_root() . '/item/' . $uuid;
// create an empty activity
$arr = [];
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
$arr['mid'] = $mid;
$arr['parent_mid'] = $w['wiki']['mid'];
$arr['parent'] = $w['wiki']['parent'];
$arr['uuid'] = $uuid;
$arr['item_hidden'] = $w['wiki']['item_hidden'];
$arr['plink'] = $mid;
$arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['author_xchan'] = $observer_hash;
$arr['mimetype'] = $mimetype;
$arr['title'] = $name;
$arr['resource_type'] = 'nwikipage';
$arr['resource_id'] = $resource_id;
$arr['allow_cid'] = $w['wiki']['allow_cid'];
$arr['allow_gid'] = $w['wiki']['allow_gid'];
$arr['deny_cid'] = $w['wiki']['deny_cid'];
$arr['deny_gid'] = $w['wiki']['deny_gid'];
$arr['item_private'] = $w['wiki']['item_private'];
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['verb'] = ACTIVITY_CREATE;
$arr['obj_type'] = 'Document';
// TODO: add an object?
$arr['public_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'], 'view_wiki'), true);
// We may wish to change this some day.
$arr['item_unpublished'] = 1;
set_iconfig($arr, 'nwikipage', 'pagetitle', (($name) ? $name : t('(No Title)')), true);
$p = item_store($arr, false, false);
if ($p['item_id']) {
$page = [
'rawName' => $name,
'htmlName' => escape_tags($name),
//'urlName' => urlencode($name),
'urlName' => NativeWiki::name_encode($name)
];
return ['page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true];
}
return ['success' => false, 'message' => t('Wiki page create failed.')];
}
static public function rename_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$pageNewName = ((array_key_exists('pageNewName', $arr)) ? $arr['pageNewName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Wiki not found.'), 'success' => false];
}
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageNewName)
);
if ($ic) {
return ['success' => false, 'message' => t('Destination name already exists')];
}
$ids = [];
$ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
set_iconfig($c['item_id'], 'nwikipage', 'pagetitle', $pageNewName);
$ids[] = $c['item_id'];
}
$str_ids = implode(',', $ids);
q("update item set title = '%s' where id in ($str_ids)",
dbesc($pageNewName)
);
$page = [
'rawName' => $pageNewName,
'htmlName' => escape_tags($pageNewName),
//'urlName' => urlencode(escape_tags($pageNewName))
'urlName' => NativeWiki::name_encode($pageNewName)
];
return ['success' => true, 'page' => $page];
}
return ['success' => false, 'message' => t('Page not found')];
}
static public function get_page_content($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? intval($arr['channel_id']) : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$item = self::load_page($arr);
if ($item) {
$content = $item['body'];
return [
'content' => $content,
'mimeType' => $w['mimeType'],
'pageMimeType' => $item['mimetype'],
'message' => '',
'success' => true
];
}
return ['content' => null, 'message' => t('Error reading page content'), 'success' => false];
}
static public function page_history($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['history' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$items = self::load_page_history($arr);
$history = [];
if ($items) {
$processed = 0;
foreach ($items as $item) {
if ($processed > 1000)
break;
$processed++;
$history[] = [
'revision' => $item['revision'],
'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited']),
'name' => $item['author']['xchan_name'],
'title' => get_iconfig($item, 'nwikipage', 'commit_msg')
];
}
return ['success' => true, 'history' => $history];
}
return ['success' => false];
}
static public function load_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision', $arr)) ? $arr['revision'] : (-1));
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
$ic = q("select * from iconfig left join item on iconfig.iid = item.id where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
if ($revision == (-1))
$sql_extra .= " order by revision desc ";
elseif ($revision)
$sql_extra .= " and revision = " . intval($revision) . " ";
$r = null;
if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) $sql_extra limit 1",
dbesc($resource_id),
intval($channel_id)
);
if ($r) {
$items = fetch_post_tags($r, true);
return $items[0];
}
}
return null;
}
static public function load_page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
$ic = q("select * from iconfig left join item on iconfig.iid = item.id where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
$sql_extra .= " order by revision desc ";
$r = null;
if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) and item_deleted = 0 $sql_extra",
dbesc($resource_id),
intval($channel_id)
);
if ($r) {
xchan_query($r);
$items = fetch_post_tags($r, true);
return $items;
}
}
return null;
}
static public function save_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content', $arr)) ? $arr['content'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
// fetch the most recently saved revision.
$item = self::load_page($arr);
if (!$item) {
return ['message' => t('Page not found'), 'success' => false];
}
$mimetype = $item['mimetype'];
// change just the fields we need to change to create a revision;
unset($item['id']);
unset($item['author']);
$item['parent'] = 0;
$item['body'] = $content;
$item['author_xchan'] = $observer_hash;
$item['revision'] = (($arr['revision']) ? intval($arr['revision']) + 1 : intval($item['revision']) + 1);
$item['edited'] = datetime_convert();
$item['mimetype'] = $mimetype;
if ($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
for ($x = 0; $x < count($item['iconfig']); $x++) {
unset($item['iconfig'][$x]['id']);
unset($item['iconfig'][$x]['iid']);
}
}
$ret = item_store($item, false, false);
if ($ret['item_id'])
return ['message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true];
else
return ['message' => t('Page update failed.'), 'success' => false];
}
static public function delete_page($arr) {
$pageUrlName = (array_key_exists('pageUrlName', $arr) ? $arr['pageUrlName'] : '');
$resource_id = (array_key_exists('resource_id', $arr) ? $arr['resource_id'] : '');
$observer_hash = (array_key_exists('observer_hash', $arr) ? $arr['observer_hash'] : '');
$channel_id = (array_key_exists('channel_id', $arr) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['success' => false, 'message' => t('Error reading wiki')];
}
$ids = [];
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
$ids[] = intval($c['iid']);
}
}
if ($ids) {
drop_items($ids, true, DROPITEM_PHASE1);
return ['success' => true];
}
return ['success' => false, 'message' => t('Nothing deleted')];
}
static public function revert_page($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$commitHash = ((array_key_exists('commitHash', $arr)) ? $arr['commitHash'] : null);
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
if (!$commitHash) {
return ['message' => 'No commit was provided', 'success' => false];
}
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => 'Error reading wiki', 'success' => false];
}
$x = $arr;
if (intval($commitHash) > 0) {
unset($x['commitHash']);
$x['revision'] = intval($commitHash) - 1;
$loaded = self::load_page($x);
if ($loaded) {
$content = $loaded['body'];
return ['content' => $content, 'success' => true];
}
return ['success' => false];
}
}
static public function compare_page($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$compareCommit = ((array_key_exists('compareCommit', $arr)) ? $arr['compareCommit'] : 0);
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
$x = $arr;
$x['revision'] = (-1);
$currpage = self::load_page($x);
if ($currpage)
$currentContent = $currpage['body'];
$x['revision'] = $compareCommit;
$comppage = self::load_page($x);
if ($comppage)
$compareContent = $comppage['body'];
if ($currpage && $comppage) {
require_once('library/class.Diff.php');
$diff = \Diff::toTable(\Diff::compare($currentContent, $compareContent));
return ['success' => true, 'diff' => $diff];
}
return ['success' => false, 'message' => t('Compare: object not found.')];
}
static public function commit($arr) {
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
if (array_key_exists('resource_id', $arr)) {
$resource_id = $arr['resource_id'];
}
else {
return ['message' => t('Wiki resource_id required for git commit'), 'success' => false];
}
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
$page = self::load_page($arr);
if ($page) {
set_iconfig($page['id'], 'nwikipage', 'commit_msg', escape_tags($commit_msg), true);
return ['success' => true, 'item_id' => $page['id'], 'page' => $page];
}
return ['success' => false, 'message' => t('Page not found.')];
}
static public function convert_links($s, $wikiURL) {
if (strpos($s, '[[') !== false) {
preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
$pages = $pageURLs = [];
foreach ($match[1] as $m) {
// TODO: Why do we need to double urlencode for this to work?
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
$titleUri = explode('|', $m);
$page = $titleUri[0] ?? '';
$title = $titleUri[1] ?? $page;
$pageURLs[] = NativeWiki::name_encode(escape_tags($page));
$pages[] = $title;
}
$idx = 0;
while (strpos($s, '[[') !== false) {
$replace = '<a href="' . $wikiURL . '/' . $pageURLs[$idx] . '">' . $pages[$idx] . '</a>';
$s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
$idx++;
}
}
return $s;
}
static public function render_page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = self::page_history([
'channel_id' => App::$profile_uid,
'observer_hash' => get_observer_hash(),
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
return replace_macros(get_markup_template('nwiki_page_history.tpl'), [
'$pageHistory' => $pageHistory['history'],
'$permsWrite' => $arr['permsWrite'],
'$name_lbl' => t('Name'),
'$msg_label' => t('Message', 'wiki_history'),
'$date_lbl' => t('Date'),
'$revert_btn' => t('Revert'),
'$compare_btn' => t('Compare')
]);
}
/**
* Replace the instances of the string [toc] with a list element that will be populated by
* a table of contents by the JavaScript library
* @param string $s
* @return string
*/
static public function generate_toc($s) {
if (strpos($s, '[toc]') !== false) {
//$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
$toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
$s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
}
return $s;
}
/**
* Converts a select set of bbcode tags. Much of the code is copied from include/bbcode.php
* @param string $s
* @return string
*/
static public function bbcode($s) {
$s = str_replace(['[baseurl]', '[sitename]'], [z_root(), get_config('system', 'sitename')], $s);
$s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_callback', $s);
$s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_necallback', $s);
$observer = App::get_observer();
if ($observer) {
$s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
$s2 = '</span>';
$obsBaseURL = $observer['xchan_connurl'];
$obsBaseURL = preg_replace("/\/poco\/.*$/", '', $obsBaseURL);
$s = str_replace('[observer.baseurl]', $obsBaseURL, $s);
$s = str_replace('[observer.url]', $observer['xchan_url'], $s);
$s = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $s);
$s = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $s);
$s = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $s);
$s = str_replace('[observer.photo]', '', $s);
}
else {
$s = str_replace('[observer.baseurl]', '', $s);
$s = str_replace('[observer.url]', '', $s);
$s = str_replace('[observer.name]', '', $s);
$s = str_replace('[observer.address]', '', $s);
$s = str_replace('[observer.webname]', '', $s);
$s = str_replace('[observer.photo]', '', $s);
}
return $s;
}
static public function get_file_ext($arr) {
if ($arr['mimetype'] === 'text/bbcode')
return '.bb';
elseif ($arr['mimetype'] === 'text/markdown')
return '.md';
elseif ($arr['mimetype'] === 'text/plain')
return '.txt';
}
// This function is derived from
// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
static public function toc($content) {
// ensure using only "\n" as line-break
$source = str_replace(["\r\n", "\r"], "\n", $content);
// look for markdown TOC items
preg_match_all(
'/^(?:=|-|#).*$/m',
$source,
$matches,
PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
);
// preprocess: iterate matched lines to create an array of items
// where each item is an array(level, text)
$file_size = strlen($source);
foreach ($matches[0] as $item) {
$found_mark = substr($item[0], 0, 1);
if ($found_mark == '#') {
// text is the found item
$item_text = $item[0];
$item_level = strrpos($item_text, '#') + 1;
$item_text = substr($item_text, $item_level);
}
else {
// text is the previous line (empty if <hr>)
$item_offset = $item[1];
$prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
$item_text =
substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
$item_text = trim($item_text);
$item_level = $found_mark == '=' ? 1 : 2;
}
if (!trim($item_text) or strpos($item_text, '|') !== FALSE) {
// item is an horizontal separator or a table header, don't mind
continue;
}
$raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
}
$o = '';
foreach ($raw_toc as $t) {
$level = intval($t['level']);
$text = $t['text'];
switch ($level) {
case 1:
$li = '* ';
break;
case 2:
$li = ' * ';
break;
case 3:
$li = ' * ';
break;
case 4:
$li = ' * ';
break;
default:
$li = '* ';
break;
}
$o .= $li . $text . "\n";
}
return $o;
}
}

View File

@@ -162,24 +162,11 @@ class ThreadItem {
$mode = $conv->get_mode();
switch($item['item_type']) {
case ITEM_TYPE_CARD:
$edlink = 'card_edit';
break;
case ITEM_TYPE_ARTICLE:
$edlink = 'article_edit';
break;
default:
$edlink = 'editpost';
break;
}
if(local_channel() && $observer['xchan_hash'] === $item['author_xchan'])
$edpost = array(z_root() . '/' . $edlink . '/' . $item['id'], t('Edit'));
$edpost = array(z_root() . '/editpost/' . $item['id'], t('Edit'));
else
$edpost = false;
if($observer && $observer['xchan_hash']
&& ($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
@@ -297,7 +284,7 @@ class ThreadItem {
if($this->is_toplevel()) {
// FIXME check this permission
if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
if($conv->get_profile_owner() === local_channel() || intval($item['item_private']) === 0) {
$star = array(
'toggle' => t("Toggle Star Status"),

View File

@@ -69,12 +69,12 @@ class ThreadStream {
case 'cards':
$this->profile_owner = \App::$profile['profile_uid'];
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
$this->reload = $_SESSION['return_url'];
//$this->reload = $_SESSION['return_url'];
break;
case 'articles':
$this->profile_owner = \App::$profile['profile_uid'];
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
$this->reload = $_SESSION['return_url'];
//$this->reload = $_SESSION['return_url'];
break;
case 'display':
// in this mode we set profile_owner after initialisation (from conversation()) and then

View File

@@ -1,138 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Article_edit extends \Zotlabs\Web\Controller {
function get() {
// Figure out which post we're editing
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1",
intval($post_id),
intval(ITEM_TYPE_ARTICLE)
);
if($itm) {
$item_id = q("select * from iconfig where cat = 'system' and k = 'ARTICLE' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$card_title = $item_id[0]['v'];
}
else {
notice( t('Item not found') . EOL);
return;
}
$owner = $itm[0]['uid'];
$uid = local_channel();
$observer = \App::get_observer();
$channel = channelx_by_n($owner);
if(! $channel) {
notice( t('Channel not found.') . EOL);
return;
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
$category = '';
$catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : '');
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
if($itm[0]['attach']) {
$j = json_decode($itm[0]['attach'],true);
if($j) {
foreach($j as $jj) {
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
}
}
}
$mimetype = $itm[0]['mimetype'];
$content = $itm[0]['body'];
$rp = 'articles/' . $channel['channel_address'];
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> 'bbcode',
'return_path' => $rp,
'webpage' => ITEM_TYPE_ARTICLE,
'button' => t('Edit'),
'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'),
'weblink' => t('Insert web link'),
'hide_voting' => false,
'hide_future' => false,
'hide_location' => false,
'hide_expire' => false,
'showacl' => true,
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
'permissions' => $itm[0],
'lockstate' => (($itm[0]['allow_cid'] || $itm[0]['allow_gid'] || $itm[0]['deny_cid'] || $itm[0]['deny_gid']) ? 'lock' : 'unlock'),
'ptyp' => $itm[0]['type'],
'mimeselect' => false,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'summary' => htmlspecialchars($itm[0]['summary'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $card_title,
'profile_uid' => (intval($channel['channel_id'])),
'catsenabled' => $catsenabled,
'category' => $category,
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x, false, 'Article_edit');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Article'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$cancel' => t('Cancel'),
'$editor' => $editor
));
return $o;
}
}

View File

@@ -1,232 +0,0 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/opengraph.php');
class Articles extends Controller {
function init() {
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
} else {
return;
}
}
profile_load($which);
}
function get($update = 0, $load = false) {
if(observer_prohibited(true)) {
return login();
}
if(! App::$profile) {
notice( t('Requested profile is not available.') . EOL );
App::$error = 404;
return;
}
if(! Apps::system_app_installed(App::$profile_uid, 'Articles')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$papp = Apps::get_papp('Articles');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Articles');
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
if($category) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
}
$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']) : '');
$which = argv(1);
$selected_card = ((argc() > 2) ? argv(2) : '');
$_SESSION['return_url'] = App::$query_string;
$uid = local_channel();
$owner = App::$profile_uid;
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = ($uid && $uid == $owner);
$channel = channelx_by_n($owner);
if($channel) {
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
}
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(perm_is_allowed($owner,$ob_hash,'write_pages')) {
$x = [
'webpage' => ITEM_TYPE_ARTICLE,
'is_owner' => true,
'content_label' => t('Add Article'),
'button' => t('Save'),
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? true : false),
'visitor' => true,
'hide_location' => false,
'hide_voting' => false,
'profile_uid' => intval($owner),
'mimetype' => 'text/bbcode',
'mimeselect' => false,
'layoutselect' => false,
'expanded' => false,
'novoting' => false,
'catsenabled' => feature_enabled($owner,'categories'),
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
];
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
$editor = status_editor($a,$x,false,'Articles');
}
else {
$editor = '';
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$sql_extra = item_permissions_sql($owner);
$sql_item = '';
if($selected_card) {
$r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.v = '%s' limit 1",
dbesc($selected_card)
);
if($r) {
$sql_item = "and item.id = " . intval($r[0]['iid']) . " ";
}
}
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
$order = 'post';
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
if($datequery || $datequery2) {
$sql_extra2 .= " and item.item_thread_top != 0 ";
}
$r = q("select * from item
where item.uid = %d and item_type = %d
$sql_extra $sql_extra2 $sql_item order by item.created desc $pager_sql",
intval($owner),
intval(ITEM_TYPE_ARTICLE)
);
$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 ";
if($r) {
$pager_total = count($r);
$parents_str = ids_to_querystr($r,'id');
$r = q("SELECT item.*, item.id AS item_id
FROM item
WHERE item.uid = %d $item_normal
AND item.parent IN ( %s )
$sql_extra $sql_extra2 ",
intval(App::$profile['profile_uid']),
dbesc($parents_str)
);
if($r) {
xchan_query($r);
$items = fetch_post_tags($r, true);
$items = conv_sort($items,'updated');
}
else
$items = [];
}
// Add Opengraph markup
opengraph_add_meta((! empty($items) ? $r[0] : []), $channel);
$mode = 'articles';
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
$page_mode = 'pager_list';
else
$page_mode = 'traditional';
$content = conversation($items,$mode,false,$page_mode);
$o = replace_macros(get_markup_template('cards.tpl'), [
'$title' => t('Articles'),
'$editor' => $editor,
'$content' => $content,
'$pager' => alt_pager($pager_total)
]);
return $o;
}
}

View File

@@ -1,140 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Card_edit extends \Zotlabs\Web\Controller {
function get() {
// Figure out which post we're editing
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1",
intval($post_id),
intval(ITEM_TYPE_CARD)
);
if($itm) {
$item_id = q("select * from iconfig where cat = 'system' and k = 'CARD' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$card_title = $item_id[0]['v'];
}
else {
notice( t('Item not found') . EOL);
return;
}
$owner = $itm[0]['uid'];
$uid = local_channel();
$observer = \App::get_observer();
$channel = channelx_by_n($owner);
if(! $channel) {
notice( t('Channel not found.') . EOL);
return;
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
$category = '';
$catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : '');
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
if($itm[0]['attach']) {
$j = json_decode($itm[0]['attach'],true);
if($j) {
foreach($j as $jj) {
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
}
}
}
$mimetype = $itm[0]['mimetype'];
$content = $itm[0]['body'];
$rp = 'cards/' . $channel['channel_address'];
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> 'bbcode',
'return_path' => $rp,
'webpage' => ITEM_TYPE_CARD,
'button' => t('Edit'),
'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'),
'weblink' => t('Insert web link'),
'hide_voting' => false,
'hide_future' => false,
'hide_location' => false,
'hide_expire' => false,
'showacl' => true,
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
'permissions' => $itm[0],
'lockstate' => (($itm[0]['allow_cid'] || $itm[0]['allow_gid'] || $itm[0]['deny_cid'] || $itm[0]['deny_gid']) ? 'lock' : 'unlock'),
'ptyp' => $itm[0]['type'],
'mimeselect' => false,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'summary' => htmlspecialchars($itm[0]['summary'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $card_title,
'profile_uid' => (intval($channel['channel_id'])),
'catsenabled' => $catsenabled,
'category' => $category,
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x, false, 'Card_edit');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Card'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$cancel' => t('Cancel'),
'$editor' => $editor
));
return $o;
}
}

View File

@@ -1,214 +0,0 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
/**
* @brief Provides the Cards module.
*
*/
class Cards extends Controller {
public function init() {
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($which);
}
/**
* {@inheritDoc}
* @see \\Zotlabs\\Web\\Controller::get()
*
* @return string Parsed HTML from template 'cards.tpl'
*/
public function get($update = 0, $load = false) {
if(observer_prohibited(true)) {
return login();
}
if(! App::$profile) {
notice( t('Requested profile is not available.') . EOL );
App::$error = 404;
return;
}
if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$papp = Apps::get_papp('Cards');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Cards');
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
if($category) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
}
$which = argv(1);
$selected_card = ((argc() > 2) ? argv(2) : '');
$_SESSION['return_url'] = App::$query_string;
$uid = local_channel();
$owner = App::$profile_uid;
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner, $ob_hash, 'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = ($uid && $uid == $owner);
$channel = channelx_by_n($owner);
if($channel) {
$channel_acl = [
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
];
}
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(perm_is_allowed($owner, $ob_hash, 'write_pages')) {
$x = [
'webpage' => ITEM_TYPE_CARD,
'is_owner' => true,
'content_label' => t('Add Card'),
'button' => t('Save'),
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? true : false),
'visitor' => true,
'hide_location' => false,
'hide_voting' => false,
'profile_uid' => intval($owner),
'mimetype' => 'text/bbcode',
'mimeselect' => false,
'layoutselect' => false,
'expanded' => false,
'novoting' => false,
'catsenabled' => feature_enabled($owner, 'categories'),
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
];
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
$editor = status_editor($a, $x, false, 'Cards');
}
else {
$editor = '';
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$sql_extra = item_permissions_sql($owner);
$sql_item = '';
if($selected_card) {
$r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.v = '%s' limit 1",
dbesc($selected_card)
);
if($r) {
$sql_item = "and item.id = " . intval($r[0]['iid']) . " ";
}
}
$r = q("select * from item
where uid = %d and item_type = %d
$sql_extra $sql_item order by item.created desc $pager_sql",
intval($owner),
intval(ITEM_TYPE_CARD)
);
$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 ";
$items_result = [];
if($r) {
$pager_total = count($r);
$parents_str = ids_to_querystr($r, 'id');
$items = q("SELECT item.*, item.id AS item_id
FROM item
WHERE item.uid = %d $item_normal
AND item.parent IN ( %s )
$sql_extra $sql_extra2 ",
intval(App::$profile['profile_uid']),
dbesc($parents_str)
);
if($items) {
xchan_query($items);
$items = fetch_post_tags($items, true);
$items_result = conv_sort($items, 'updated');
}
}
$mode = 'cards';
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
$page_mode = 'pager_list';
else
$page_mode = 'traditional';
$content = conversation($items_result, $mode, false, $page_mode);
$o = replace_macros(get_markup_template('cards.tpl'), [
'$title' => t('Cards'),
'$editor' => $editor,
'$content' => $content,
'$pager' => alt_pager($pager_total)
]);
return $o;
}
}

View File

@@ -143,48 +143,8 @@ class Display extends \Zotlabs\Web\Controller {
return '';
}
}
if($target_item['item_type'] == ITEM_TYPE_ARTICLE) {
$x = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
);
$y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and item.id = %d limit 1",
intval($target_item['uid']),
intval($target_item['parent'])
);
if($x && $y) {
goaway(z_root() . '/articles/' . $x[0]['channel_address'] . '/' . $y[0]['v']);
}
else {
notice( t('Page not found.') . EOL);
return '';
}
}
if($target_item['item_type'] == ITEM_TYPE_CARD) {
$x = q("select * from channel where channel_id = %d limit 1",
intval($target_item['uid'])
);
$y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'CARD' and item.id = %d limit 1",
intval($target_item['uid']),
intval($target_item['parent'])
);
if($x && $y) {
goaway(z_root() . '/cards/' . $x[0]['channel_address'] . '/' . $y[0]['v']);
}
else {
notice( t('Page not found.') . EOL);
return '';
}
}
if ($target_item['item_type'] == ITEM_TYPE_CUSTOM) {
call_hooks('item_custom_display',$target_item);
notice( t('Page not found.') . EOL);
return '';
}
call_hooks('item_custom_display', $target_item);
$simple_update = '';
if($update && $_SESSION['loadtime'])

View File

@@ -743,6 +743,8 @@ class Item extends Controller {
$webpage = $parent_item['item_type'];
}
if ((!$allow_empty) && (!strlen($body))) {
if ($preview)
killme();
@@ -807,7 +809,6 @@ class Item extends Controller {
$post_tags = [];
if ($mimetype === 'text/bbcode') {
require_once('include/text.php');
@@ -919,15 +920,7 @@ class Item extends Controller {
$cats = explode(',', $categories);
foreach ($cats as $cat) {
if ($webpage == ITEM_TYPE_CARD) {
$catlink = z_root() . '/cards/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat));
}
elseif ($webpage == ITEM_TYPE_ARTICLE) {
$catlink = z_root() . '/articles/' . $channel['channel_address'] . '?f=&cat=' . urlencode(trim($cat));
}
else {
$catlink = $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat));
}
$catlink = $owner_xchan['xchan_url'] . '?f=&cat=' . urlencode(trim($cat));
$post_tags[] = [
'uid' => $profile_uid,
@@ -1040,7 +1033,7 @@ class Item extends Controller {
$parent_mid = $parent_item['mid'];
// Fallback so that we alway have a thr_parent
// Fallback so that we always have a thr_parent
if (!$thr_parent)
$thr_parent = $mid;
@@ -1048,36 +1041,7 @@ class Item extends Controller {
$item_thread_top = ((!$parent) ? 1 : 0);
// fix permalinks for cards
if ($webpage == ITEM_TYPE_CARD) {
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid);
}
if (($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_CARD)) {
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.iid = %d limit 1",
intval($parent_item['id'])
);
if ($r) {
$plink = z_root() . '/cards/' . $channel['channel_address'] . '/' . $r[0]['v'];
}
}
if ($webpage == ITEM_TYPE_ARTICLE) {
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . (($pagetitle) ? $pagetitle : $uuid);
}
if (($parent_item) && ($parent_item['item_type'] == ITEM_TYPE_ARTICLE)) {
$r = q("select v from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.iid = %d limit 1",
intval($parent_item['id'])
);
if ($r) {
$plink = z_root() . '/articles/' . $channel['channel_address'] . '/' . $r[0]['v'];
}
}
if ((!$plink) && ($item_thread_top)) {
// $plink = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . gen_link_id($mid);
// $plink = substr($plink,0,190);
$plink = $mid;
}

View File

@@ -177,49 +177,46 @@ class Search extends Controller {
}
$item_normal = item_normal_search();
$pub_sql = public_permissions_sql($observer_hash);
require_once('include/channel.php');
$sys = get_sys_channel();
if (($update) && ($load)) {
$itemspage = get_pconfig(local_channel(), 'system', 'itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
// in case somebody turned off public access to sys channel content with permissions
$item_normal = item_normal_search();
$pub_sql = item_permissions_sql(0, $observer_hash);
if (!perm_is_allowed($sys['channel_id'], $observer_hash, 'view_stream'))
$sys['xchan_hash'] .= 'disabled';
$sys = get_sys_channel();
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner uid can't match
$sys_id = perm_is_allowed($sys['channel_id'], $observer_hash, 'view_stream') ? $sys['channel_id'] : 0;
if ($load) {
$r = null;
if (local_channel()) {
$r = q("SELECT mid, MAX(id) as item_id from item
WHERE ((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item_private = 0 )
OR ( item.uid = %d )) OR item.owner_xchan = '%s' )
$r = q("SELECT mid, MAX(id) AS item_id FROM item
WHERE (( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item.item_private = 0 )
OR ( item.uid = %d ))
$item_normal
$sql_extra
group by mid, created order by created desc $pager_sql ",
intval(local_channel()),
dbesc($sys['xchan_hash'])
GROUP BY mid, created ORDER BY created DESC $pager_sql ",
intval(local_channel())
);
}
if ($r === null) {
$r = q("SELECT mid, MAX(id) as item_id from item
WHERE (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
AND item.deny_gid = '' AND item_private = 0 )
and owner_xchan in ( " . stream_perms_xchans(($observer) ? (PERMS_NETWORK | PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
$pub_sql ) OR owner_xchan = '%s')
if (!$r) {
$r = q("SELECT mid, MAX(id) AS item_id FROM item
WHERE (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' AND item.deny_gid = '' AND item.item_private = 0 )
AND item.uid IN ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK | PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
$pub_sql ) OR item.uid = %d)
$item_normal
$sql_extra
group by mid, created order by created desc $pager_sql",
dbesc($sys['xchan_hash'])
GROUP BY mid, created ORDER BY created DESC $pager_sql",
intval($sys_id)
);
}
if ($r) {
$str = ids_to_querystr($r, 'item_id');
$r = dbq("select *, id as item_id from item where id in ( " . $str . ") order by created desc");
@@ -232,13 +229,12 @@ class Search extends Controller {
}
$items = [];
if ($r) {
xchan_query($r);
$items = fetch_post_tags($r, true);
}
else {
$items = [];
}
if ($format === 'json') {
$result = [];

View File

@@ -387,8 +387,8 @@ class Setup extends \Zotlabs\Web\Controller {
function check_php(&$phpath, &$checks) {
$help = '';
if(version_compare(PHP_VERSION, '7.1') < 0) {
$help .= t('PHP version 7.1 or greater is required.');
if(version_compare(PHP_VERSION, '8.0') < 0) {
$help .= t('PHP version 8.0 or greater is required.');
$this->check_add($checks, t('PHP version'), false, true, $help);
}

View File

@@ -160,8 +160,12 @@ class Sse_bs extends Controller {
$offset = self::$offset;
$sql_extra = '';
if(! (self::$vnotify & VNOTIFY_LIKE))
if (!(self::$vnotify & VNOTIFY_LIKE)) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
elseif (!feature_enabled(self::$uid, 'dislike')) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
$sql_extra2 = '';
if(self::$xchans)
@@ -236,8 +240,12 @@ class Sse_bs extends Controller {
$offset = self::$offset;
$sql_extra = '';
if(! (self::$vnotify & VNOTIFY_LIKE))
if (!(self::$vnotify & VNOTIFY_LIKE)) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
elseif (!feature_enabled(self::$uid, 'dislike')) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
$sql_extra2 = '';
if(self::$xchans)
@@ -311,8 +319,12 @@ class Sse_bs extends Controller {
$offset = self::$offset;
$sql_extra = '';
if(! (self::$vnotify & VNOTIFY_LIKE))
if (!(self::$vnotify & VNOTIFY_LIKE)) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
elseif (!feature_enabled(self::$uid, 'dislike')) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
$sql_extra2 = '';
if(self::$xchans)
@@ -398,8 +410,12 @@ class Sse_bs extends Controller {
$sys = get_sys_channel();
$sql_extra = '';
if(! (self::$vnotify & VNOTIFY_LIKE))
if (!(self::$vnotify & VNOTIFY_LIKE)) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
elseif (!feature_enabled(self::$uid, 'dislike')) {
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
$sql_extra2 = '';
if(self::$xchans)

View File

@@ -1,31 +1,46 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Libsync;
class Starred extends \Zotlabs\Web\Controller {
function init() {
$starred = 0;
if(! local_channel())
killme();
if(argc() > 1)
$message_id = intval(argv(1));
if(! $message_id)
killme();
$r = q("SELECT item_starred FROM item WHERE uid = %d AND id = %d LIMIT 1",
$sys = get_sys_channel();
$r = q("SELECT * FROM item WHERE (uid = %d OR uid = %d) AND id = %d
and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
intval(local_channel()),
intval($sys['channel_id']),
intval($message_id)
);
if(! count($r))
if ($r) {
if ($r[0]['uid'] === $sys['channel_id']) {
$r = [ copy_of_pubitem(App::get_channel(), $r[0]['mid']) ];
}
}
if(!$r)
killme();
// reset $message_id to the fetched copy of message if applicable
$message_id = $r[0]['id'];
$item_starred = (intval($r[0]['item_starred']) ? 0 : 1);
$r = q("UPDATE item SET item_starred = %d WHERE uid = %d and id = %d",
intval($item_starred),
intval(local_channel()),
@@ -38,8 +53,8 @@ class Starred extends \Zotlabs\Web\Controller {
if($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet(local_channel(),[
'item' => [
Libsync::build_sync_packet(local_channel(),[
'item' => [
encode_item($sync_item[0],true)
]
]);
@@ -49,5 +64,5 @@ class Starred extends \Zotlabs\Web\Controller {
echo json_encode(array('result' => $item_starred));
killme();
}
}

View File

@@ -1,873 +0,0 @@
<?php /** @file */
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\PermissionDescription;
use Zotlabs\Lib\NativeWiki;
use Zotlabs\Lib\NativeWikiPage;
use Zotlabs\Lib\MarkdownSoap;
use Michelf\MarkdownExtra;
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
require_once('include/bbcode.php');
class Wiki extends Controller {
private $wiki = null;
function init() {
// Determine which channel's wikis to display to the observer
$nick = null;
if (argc() > 1)
$nick = argv(1); // if the channel name is in the URL, use that
if (! $nick && local_channel()) { // if no channel name was provided, assume the current logged in channel
$channel = \App::get_channel();
if ($channel && $channel['channel_address']) {
$nick = $channel['channel_address'];
goaway(z_root() . '/wiki/' . $nick);
}
}
if (! $nick) {
notice( t('Profile Unavailable.') . EOL);
goaway(z_root());
}
profile_load($nick);
}
function get() {
if(observer_prohibited(true)) {
return login();
}
if(! Apps::system_app_installed(App::$profile_uid, 'Wiki')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$papp = Apps::get_papp('Wiki');
return Apps::app_render($papp, 'module');
}
if(! perm_is_allowed(\App::$profile_uid,get_observer_hash(),'view_wiki')) {
notice( t('Permission denied.') . EOL);
return;
}
// TODO: Combine the interface configuration into a unified object
// Something like $interface = array('new_page_button' => false, 'new_wiki_button' => false, ...)
$wiki_owner = false;
$showNewWikiButton = false;
$pageHistory = array();
$local_observer = null;
$resource_id = '';
// init() should have forced the URL to redirect to /wiki/channel so assume argc() > 1
$nick = argv(1);
$owner = channelx_by_nick($nick); // The channel who owns the wikis being viewed
if(! $owner) {
notice( t('Invalid channel') . EOL);
goaway('/' . argv(0));
}
$observer_hash = get_observer_hash();
// Determine if the observer is the channel owner so the ACL dialog can be populated
if (local_channel() === intval($owner['channel_id'])) {
$wiki_owner = true;
nav_set_selected('Wiki');
// Obtain the default permission settings of the channel
$owner_acl = array(
'allow_cid' => $owner['channel_allow_cid'],
'allow_gid' => $owner['channel_allow_gid'],
'deny_cid' => $owner['channel_deny_cid'],
'deny_gid' => $owner['channel_deny_gid']
);
// Initialize the ACL to the channel default permissions
$x = array(
'lockstate' => (( $owner['channel_allow_cid'] ||
$owner['channel_allow_gid'] ||
$owner['channel_deny_cid'] ||
$owner['channel_deny_gid'])
? 'lock' : 'unlock'
),
'acl' => populate_acl($owner_acl, false, PermissionDescription::fromGlobalPermission('view_wiki')),
'allow_cid' => acl2json($owner_acl['allow_cid']),
'allow_gid' => acl2json($owner_acl['allow_gid']),
'deny_cid' => acl2json($owner_acl['deny_cid']),
'deny_gid' => acl2json($owner_acl['deny_gid']),
'bang' => ''
);
}
else {
// Not the channel owner
$owner_acl = $x = array();
}
$is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false);
$o = '';
// Download a wiki
if((argc() > 3) && (argv(2) === 'download') && (argv(3) === 'wiki')) {
$resource_id = argv(4);
$w = NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id);
// $w = NativeWiki::get_wiki($owner,$observer_hash,$resource_id);
if(! $w['htmlName']) {
notice(t('Error retrieving wiki') . EOL);
}
$zip_folder_name = random_string(10);
$zip_folderpath = '/tmp/' . $zip_folder_name;
if(!mkdir($zip_folderpath, 0770, false)) {
logger('Error creating zip file export folder: ' . $zip_folderpath, LOGGER_NORMAL);
notice(t('Error creating zip file export folder') . EOL);
}
$zip_filename = $w['urlName'];
$zip_filepath = '/tmp/' . $zip_folder_name . '/' . $zip_filename;
// Generate the zip file
$zip = new \ZipArchive;
$r = $zip->open($zip_filepath, \ZipArchive::CREATE);
if($r === true) {
$pages = [];
$i = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' order by revision desc",
dbesc($resource_id)
);
if($i) {
foreach($i as $iv) {
if(in_array($iv['mid'],$pages))
continue;
if($iv['mimetype'] === 'text/plain') {
$content = html_entity_decode($iv['body'],ENT_COMPAT,'UTF-8');
}
elseif($iv['mimetype'] === 'text/bbcode') {
$content = html_entity_decode($iv['body'],ENT_COMPAT,'UTF-8');
}
elseif($iv['mimetype'] === 'text/markdown') {
$content = html_entity_decode(MarkdownSoap::unescape($iv['body']),ENT_COMPAT,'UTF-8');
}
$fname = get_iconfig($iv['id'],'nwikipage','pagetitle') . NativeWikiPage::get_file_ext($iv);
$zip->addFromString($fname,$content);
$pages[] = $iv['mid'];
}
}
}
$zip->close();
// Output the file for download
header('Content-disposition: attachment; filename="' . $zip_filename . '.zip"');
header('Content-Type: application/zip');
$success = readfile($zip_filepath);
if(!$success) {
logger('Error downloading wiki: ' . $resource_id);
notice(t('Error downloading wiki: ' . $resource_id) . EOL);
}
// delete temporary files
rrmdir($zip_folderpath);
killme();
}
switch(argc()) {
case 2:
$wikis = NativeWiki::listwikis($owner, get_observer_hash());
if($wikis) {
$o .= replace_macros(get_markup_template('wikilist.tpl'), array(
'$header' => t('Wikis'),
'$channel' => $owner['channel_address'],
'$wikis' => $wikis['wikis'],
// If the observer is the local channel owner, show the wiki controls
'$owner' => ((local_channel() && local_channel() === intval(\App::$profile['uid'])) ? true : false),
'$edit' => t('Edit'),
'$download' => t('Download'),
'$view' => t('View'),
'$create' => t('Create New'),
'$submit' => t('Submit'),
'$wikiName' => array('wikiName', t('Wiki name')),
'$mimeType' => array('mimeType', t('Content type'), '', '', ['text/markdown' => t('Markdown'), 'text/bbcode' => t('BBcode'), 'text/plain' => t('Text') ]),
'$name' => t('Name'),
'$type' => t('Type'),
'$unlocked' => t('Any&nbsp;type'),
'$lockstate' => (x($x,'lockstate') ? $x['lockstate'] : ''),
'$acl' => (x($x,'acl') ? $x['acl'] : ''),
'$allow_cid' => (x($x,'allow_cid') ? $x['allow_cid'] : ''),
'$allow_gid' => (x($x,'allow_gid') ? $x['allow_gid'] : ''),
'$deny_cid' => (x($x,'deny_cid') ? $x['deny_cid'] : ''),
'$deny_gid' => (x($x,'deny_gid') ? $x['deny_gid'] : ''),
'$typelock' => array('typelock', t('Lock content type'), '', '', array(t('No'), t('Yes'))),
'$notify' => array('postVisible', t('Create a status post for this wiki'), '', '', array(t('No'), t('Yes'))),
'$edit_wiki_name' => t('Edit Wiki Name')
));
return $o;
}
break;
case 3:
// /wiki/channel/wiki -> No page was specified, so redirect to Home.md
//$wikiUrlName = urlencode(argv(2));
$wikiUrlName = NativeWiki::name_encode(argv(2));
goaway(z_root() . '/' . argv(0) . '/' . argv(1) . '/' . $wikiUrlName . '/Home');
case 4:
default:
// GET /wiki/channel/wiki/page
// Fetch the wiki info and determine observer permissions
//$wikiUrlName = urldecode(argv(2));
$wikiUrlName = NativeWiki::name_decode(argv(2));
$page_name = '';
$ignore_language = false;
for($x = 3; $x < argc(); $x ++) {
if($page_name === '' && argv($x) === '-') {
$ignore_language = true;
continue;
}
if($page_name) {
$page_name .= '/';
}
$page_name .= argv($x);
}
//$pageUrlName = urldecode($page_name);
$pageUrlName = NativeWiki::name_decode($page_name);
$langPageUrlName = \App::$language . '/' . $pageUrlName;
$w = NativeWiki::exists_by_name($owner['channel_id'], $wikiUrlName);
if(! $w['resource_id']) {
notice(t('Wiki not found') . EOL);
goaway(z_root() . '/' . argv(0) . '/' . argv(1));
}
$resource_id = $w['resource_id'];
if(! $wiki_owner) {
// Check for observer permissions
$observer_hash = get_observer_hash();
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['read']) {
notice(t('Permission denied.') . EOL);
goaway(z_root() . '/' . argv(0) . '/' . argv(1));
return; //not reached
}
$wiki_editor = (($perms['write']) ? true : false);
}
else {
$wiki_editor = true;
}
//$wikiheaderName = urldecode($wikiUrlName);
$wikiheaderName = escape_tags(NativeWiki::name_decode($wikiUrlName));
//$wikiheaderPage = urldecode($pageUrlName);
$wikiheaderPage = escape_tags(NativeWiki::name_decode($pageUrlName));
$renamePage = (($wikiheaderPage === 'Home') ? '' : t('Rename page'));
$sharePage = t('Share');
$p = [];
if(! $ignore_language) {
$p = NativeWikiPage::get_page_content(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $langPageUrlName));
}
if(! ($p && $p['success'])) {
$p = NativeWikiPage::get_page_content(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
}
if(! ($p && $p['success'])) {
$x = new \Zotlabs\Widget\Wiki_pages();
$html = $x->create_missing_page([
'resource_id' => $resource_id,
'channel_id' => $owner['channel_id'],
'channel_address' => $owner['channel_address'],
'refresh' => true
]);
//json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true));
notice( t('Error retrieving page content') . EOL);
//goaway(z_root() . '/' . argv(0) . '/' . argv(1) );
$renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName));
$showPageControls = $wiki_editor;
}
else {
$mimeType = $p['pageMimeType'];
$sampleContent = (($mimeType == 'text/bbcode') ? '[h3]' . t('New page') . '[/h3]' : '### ' . t('New page'));
if($mimeType === 'text/plain')
$sampleContent = t('New page');
$content = (($p['content'] == '') ? $sampleContent : $p['content']);
$hookinfo = ['content' => $content, 'mimetype' => $mimeType];
call_hooks('wiki_preprocess',$hookinfo);
$content = $hookinfo['content'];
// Render the Markdown-formatted page content in HTML
if($mimeType == 'text/bbcode') {
$renderedContent = zidify_links(smilies(bbcode($content)));
$renderedContent = NativeWikiPage::convert_links($renderedContent,argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName));
}
elseif($mimeType === 'text/plain') {
$renderedContent = str_replace(["\n",' ',"\t"],[EOL,'&nbsp;','&nbsp;&nbsp;&nbsp;&nbsp;'],htmlentities($content,ENT_COMPAT,'UTF-8',false));
}
elseif($mimeType === 'text/markdown') {
$content = MarkdownSoap::unescape($content);
//$html = NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(NativeWikiPage::bbcode($content))));
//$renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName);
$html = NativeWikiPage::convert_links($content, argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName));
$renderedContent = NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(NativeWikiPage::bbcode($html))));
}
$showPageControls = $wiki_editor;
}
break;
// default: // Strip the extraneous URL components
// goaway('/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . $pageUrlName);
}
$wikiModalID = random_string(3);
$wikiModal = replace_macros(get_markup_template('generic_modal.tpl'), array(
'$id' => $wikiModalID,
'$title' => t('Revision Comparison'),
'$ok' => (($showPageControls) ? t('Revert') : ''),
'$cancel' => t('Cancel')
));
$types = [ 'text/bbcode' => t('BBcode'), 'text/markdown' => t('Markdown'), 'text/plain' => 'Text' ];
$currenttype = $types[$mimeType];
$placeholder = t('Short description of your changes (optional)');
$zrl = z_root() . '/wiki/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . NativeWiki::name_encode($pageUrlName);
$o .= replace_macros(get_markup_template('wiki.tpl'),array(
'$wikiheaderName' => $wikiheaderName,
'$wikiheaderPage' => $wikiheaderPage,
'$renamePage' => $renamePage,
'$sharePage' => $sharePage,
'$shareLink' => urlencode('#^[zrl=' . $zrl . ']' . '[ ' . $owner['channel_name'] . ' ] ' . $wikiheaderName . ' - ' . $wikiheaderPage . '[/zrl]'),
'$showPageControls' => $showPageControls,
'$editOrSourceLabel' => (($showPageControls) ? t('Edit') : t('Source')),
'$tools_label' => 'Page Tools',
'$channel_address' => $owner['channel_address'],
'$channel_id' => $owner['channel_id'],
'$resource_id' => $resource_id,
'$page' => $pageUrlName,
'$mimeType' => $mimeType,
'$typename' => $currenttype,
'$content' => $content,
'$renderedContent' => $renderedContent,
'$pageRename' => array('pageRename', t('New page name'), '', ''),
'$commitMsg' => array('commitMsg', '', '', '', '', 'placeholder="' . $placeholder . '"'),
'$wikiModal' => $wikiModal,
'$wikiModalID' => $wikiModalID,
'$commit' => 'HEAD',
'$embedPhotos' => t('Embed image from photo albums'),
'$embedPhotosModalTitle' => t('Embed an image from your albums'),
'$embedPhotosModalCancel' => t('Cancel'),
'$embedPhotosModalOK' => t('OK'),
'$modalchooseimages' => t('Choose images to embed'),
'$modalchoosealbum' => t('Choose an album'),
'$modaldiffalbum' => t('Choose a different album'),
'$modalerrorlist' => t('Error getting album list'),
'$modalerrorlink' => t('Error getting photo link'),
'$modalerroralbum' => t('Error getting album'),
'$view_lbl' => t('View'),
'$history_lbl' => t('History')
));
if($p['pageMimeType'] === 'text/markdown')
head_add_js('/library/ace/ace.js'); // Ace Code Editor
return $o;
}
function post() {
require_once('include/bbcode.php');
$nick = argv(1);
$owner = channelx_by_nick($nick);
$observer_hash = get_observer_hash();
if(! $owner) {
notice( t('Permission denied.') . EOL);
return;
}
// /wiki/channel/preview
// Render mardown-formatted text in HTML for preview
if((argc() > 2) && (argv(2) === 'preview')) {
$content = $_POST['content'];
$resource_id = $_POST['resource_id'];
$w = NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id);
$wikiURL = argv(0) . '/' . argv(1) . '/' . $w['urlName'];
$mimeType = $_POST['mimetype'];
if($mimeType === 'text/bbcode') {
$html = zidify_links(smilies(bbcode($content)));
$html = NativeWikiPage::convert_links($html,$wikiURL);
}
elseif($mimeType === 'text/markdown') {
$linkconverted = NativeWikiPage::convert_links($content,$wikiURL);
$bb = NativeWikiPage::bbcode($linkconverted);
$x = new MarkdownSoap($bb);
$md = $x->clean();
$md = MarkdownSoap::unescape($md);
$html = MarkdownExtra::defaultTransform($md);
$html = NativeWikiPage::generate_toc(zidify_text($html));
}
elseif($mimeType === 'text/plain') {
$html = str_replace(["\n",' ',"\t"],[EOL,'&nbsp;','&nbsp;&nbsp;&nbsp;&nbsp;'],htmlentities($content,ENT_COMPAT,'UTF-8',false));
}
json_return_and_die(array('html' => $html, 'success' => true));
}
// Create a new wiki
// /wiki/channel/create/wiki
if ((argc() > 3) && (argv(2) === 'create') && (argv(3) === 'wiki')) {
// Only the channel owner can create a wiki, at least until we create a
// more detail permissions framework
if (local_channel() !== intval($owner['channel_id'])) {
goaway('/' . argv(0) . '/' . $nick . '/');
}
$wiki = array();
// backslashes won't work well in the javascript functions
$name = str_replace('\\','',$_POST['wikiName']);
// Generate new wiki info from input name
$wiki['postVisible'] = ((intval($_POST['postVisible'])) ? 1 : 0);
$wiki['rawName'] = $name;
$wiki['htmlName'] = escape_tags($name);
//$wiki['urlName'] = urlencode(urlencode($name));
$wiki['urlName'] = NativeWiki::name_encode($name);
$wiki['mimeType'] = $_POST['mimeType'];
$wiki['typelock'] = $_POST['typelock'];
if($wiki['urlName'] === '') {
notice( t('Error creating wiki. Invalid name.') . EOL);
goaway('/wiki');
return; //not reached
}
$exists = NativeWiki::exists_by_name($owner['channel_id'], $wiki['urlName']);
if($exists['id']) {
notice( t('A wiki with this name already exists.') . EOL);
goaway('/wiki');
return; //not reached
}
// Get ACL for permissions
$acl = new \Zotlabs\Access\AccessList($owner);
$acl->set_from_array($_POST);
$r = NativeWiki::create_wiki($owner, $observer_hash, $wiki, $acl);
if($r['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']);
$homePage = NativeWikiPage::create_page($owner, $observer_hash, 'Home', $r['item']['resource_id'], $wiki['mimeType']);
if(! $homePage['success']) {
notice( t('Wiki created, but error creating Home page.'));
goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']));
}
NativeWiki::sync_a_wiki_item($owner['channel_id'], $homePage['item_id'], $r['item']['resource_id']);
goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']) . '/' . NativeWiki::name_encode($homePage['page']['urlName']));
}
else {
notice( t('Error creating wiki'));
goaway(z_root() . '/wiki');
}
}
// Update a wiki
// /wiki/channel/update/wiki
if ((argc() > 3) && (argv(2) === 'update') && (argv(3) === 'wiki')) {
// Only the channel owner can update a wiki, at least until we create a
// more detail permissions framework
if (local_channel() !== intval($owner['channel_id'])) {
goaway('/' . argv(0) . '/' . $nick . '/');
}
$arr = [];
//$arr['urlName'] = urlencode(urlencode($_POST['origRawName']));
$arr['urlName'] = NativeWiki::name_encode($_POST['origRawName']);
if($_POST['updateRawName'])
$arr['updateRawName'] = $_POST['updateRawName'];
if(($arr['urlName'] || $arr['updateRawName']) === '') {
notice( t('Error updating wiki. Invalid name.') . EOL);
goaway('/wiki');
return; //not reached
}
$wiki = NativeWiki::exists_by_name($owner['channel_id'], $arr['urlName']);
if($wiki['resource_id']) {
$arr['resource_id'] = $wiki['resource_id'];
$acl = new \Zotlabs\Access\AccessList($owner);
$acl->set_from_array($_POST);
$r = NativeWiki::update_wiki($owner['channel_id'], $observer_hash, $arr, $acl);
if($r['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], $r['item_id'], $r['item']['resource_id']);
goaway(z_root() . '/wiki/' . $nick);
}
else {
notice( t('Error updating wiki'));
goaway(z_root() . '/wiki');
}
}
goaway(z_root() . '/wiki');
}
// Delete a wiki
if ((argc() > 3) && (argv(2) === 'delete') && (argv(3) === 'wiki')) {
// Only the channel owner can delete a wiki, at least until we create a
// more detail permissions framework
if (local_channel() !== intval($owner['channel_id'])) {
logger('Wiki delete permission denied.');
json_return_and_die(array('message' => t('Wiki delete permission denied.'), 'success' => false));
}
$resource_id = $_POST['resource_id'];
$deleted = NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id);
if ($deleted['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id);
json_return_and_die(array('message' => '', 'success' => true));
}
else {
logger('Error deleting wiki: ' . $resource_id . ' ' . $deleted['message']);
json_return_and_die(array('message' => t('Error deleting wiki'), 'success' => false));
}
}
// Create a page
if ((argc() === 4) && (argv(2) === 'create') && (argv(3) === 'page')) {
$mimetype = $_POST['mimetype'];
$resource_id = $_POST['resource_id'];
// Determine if observer has permission to create a page
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
json_return_and_die(array('success' => false));
}
$name = isset($_POST['pageName']) ? $_POST['pageName'] : $_POST['missingPageName']; //Get new page name
// backslashes won't work well in the javascript functions
$name = str_replace('\\','',$name);
if(NativeWiki::name_encode(escape_tags($name)) === '') {
json_return_and_die(array('message' => 'Error creating page. Invalid name (' . print_r($_POST,true) . ').', 'success' => false));
}
$page = NativeWikiPage::create_page($owner, $observer_hash, $name, $resource_id, $mimetype);
if($page['item_id']) {
$commit = NativeWikiPage::commit([
'commit_msg' => t('New page created'),
'resource_id' => $resource_id,
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'pageUrlName' => $name
]);
if($commit['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
//json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true));
json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . $page['page']['urlName'], 'success' => true));
}
else {
json_return_and_die(array('message' => 'Error making git commit','url' => '/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($page['wiki']['urlName']) . '/' . NativeWiki::name_encode($page['page']['urlName']),'success' => false));
}
}
else {
logger('Error creating page');
json_return_and_die(array('message' => 'Error creating page.', 'success' => false));
}
}
// Fetch page list for a wiki
if((argc() === 5) && (argv(2) === 'get') && (argv(3) === 'page') && (argv(4) === 'list')) {
$resource_id = $_POST['resource_id']; // resource_id for wiki in db
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(!$perms['read']) {
logger('Wiki read permission denied.' . EOL);
json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false));
}
// @FIXME - we shouldn't invoke this if it isn't in the PDL or has been over-ridden
$x = new \Zotlabs\Widget\Wiki_pages();
$page_list_html = $x->widget([
'resource_id' => $resource_id,
'channel_id' => $owner['channel_id'],
'channel_address' => $owner['channel_address'],
'refresh' => true
]);
json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true));
}
// Save a page
if ((argc() === 4) && (argv(2) === 'save') && (argv(3) === 'page')) {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
$pageHtmlName = escape_tags($_POST['name']);
$content = $_POST['content']; //Get new content
$commitMsg = $_POST['commitMsg'];
if ($commitMsg === '') {
$commitMsg = 'Updated ' . $pageHtmlName;
}
// Determine if observer has permission to save content
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
json_return_and_die(array('success' => false));
}
$saved = NativeWikiPage::save_page([
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName,
'content' => $content
]);
if($saved['success']) {
$commit = NativeWikiPage::commit([
'commit_msg' => $commitMsg,
'pageUrlName' => $pageUrlName,
'resource_id' => $resource_id,
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'revision' => (-1)
]);
if($commit['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true , 'content' => $content));
}
else {
json_return_and_die(array('message' => 'Error making git commit','success' => false));
}
}
else {
json_return_and_die(array('message' => 'Error saving page', 'success' => false));
}
}
// Update page history
// /wiki/channel/history/page
if ((argc() === 4) && (argv(2) === 'history') && (argv(3) === 'page')) {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
// Determine if observer has permission to read content
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['read']) {
logger('Wiki read permission denied.' . EOL);
json_return_and_die(array('historyHTML' => '', 'message' => 'Permission denied.', 'success' => false));
}
$historyHTML = \Zotlabs\Lib\NativeWikiPage::render_page_history(array(
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName,
'permsWrite' => $perms['write']
));
json_return_and_die(array('historyHTML' => $historyHTML, 'message' => '', 'success' => true));
}
// Delete a page
if ((argc() === 4) && (argv(2) === 'delete') && (argv(3) === 'page')) {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
if ($pageUrlName === 'Home') {
json_return_and_die(array('message' => t('Cannot delete Home'),'success' => false));
}
// Determine if observer has permission to delete pages
// currently just allow page owner
if((! local_channel()) || (local_channel() != $owner['channel_id'])) {
logger('Wiki write permission denied. ' . EOL);
json_return_and_die(array('success' => false));
}
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
json_return_and_die(array('success' => false));
}
$deleted = NativeWikiPage::delete_page([
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
if($deleted['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], 0, $resource_id);
json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true));
}
else {
json_return_and_die(array('message' => 'Error deleting page', 'success' => false));
}
}
// Revert a page
if ((argc() === 4) && (argv(2) === 'revert') && (argv(3) === 'page')) {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
$commitHash = $_POST['commitHash'];
// Determine if observer has permission to revert pages
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied.' . EOL);
json_return_and_die(array('success' => false));
}
$reverted = NativeWikiPage::revert_page([
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'commitHash' => $commitHash,
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
if($reverted['success']) {
json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true));
}
else {
json_return_and_die(array('content' => '', 'message' => 'Error reverting page', 'success' => false));
}
}
// Compare page revisions
if ((argc() === 4) && (argv(2) === 'compare') && (argv(3) === 'page')) {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['name'];
$compareCommit = $_POST['compareCommit'];
$currentCommit = $_POST['currentCommit'];
// Determine if observer has permission to revert pages
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(!$perms['read']) {
logger('Wiki read permission denied.' . EOL);
json_return_and_die(array('success' => false));
}
$compare = NativeWikiPage::compare_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
if($compare['success']) {
$diffHTML = '<table class="text-center" width="100%"><tr><td class="lead" width="50%">' . t('Current Revision') . '</td><td class="lead" width="50%">' . t('Selected Revision') . '</td></tr></table>' . $compare['diff'];
json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true));
} else {
json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false));
}
}
// Rename a page
if ((argc() === 4) && (argv(2) === 'rename') && (argv(3) === 'page')) {
$resource_id = $_POST['resource_id'];
$pageUrlName = $_POST['oldName'];
$pageNewName = str_replace('\\','',$_POST['newName']);
if ($pageUrlName === 'Home') {
json_return_and_die(array('message' => 'Cannot rename Home','success' => false));
}
if(NativeWiki::name_encode(escape_tags($pageNewName)) === '') {
json_return_and_die(array('message' => 'Error renaming page. Invalid name.', 'success' => false));
}
// Determine if observer has permission to rename pages
$perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash);
if(! $perms['write']) {
logger('Wiki write permission denied. ' . EOL);
json_return_and_die(array('success' => false));
}
$renamed = NativeWikiPage::rename_page([
'channel_id' => $owner['channel_id'],
'observer_hash' => $observer_hash,
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName,
'pageNewName' => $pageNewName
]);
if($renamed['success']) {
$commit = NativeWikiPage::commit([
'channel_id' => $owner['channel_id'],
'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'],
'resource_id' => $resource_id,
'observer_hash' => $observer_hash,
'pageUrlName' => $pageNewName
]);
if($commit['success']) {
NativeWiki::sync_a_wiki_item($owner['channel_id'], $commit['item_id'], $resource_id);
json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true));
}
else {
json_return_and_die(array('message' => 'Error making git commit','success' => false));
}
}
else {
json_return_and_die(array('message' => 'Error renaming page', 'success' => false));
}
}
//notice( t('You must be authenticated.'));
json_return_and_die(array('message' => t('You must be authenticated.'), 'success' => false));
}
}

View File

@@ -344,19 +344,13 @@ abstract class PhotoDriver {
return false;
}
/*
* PHP 7.2 allows you to use a stream resource, which should reduce/avoid
* memory exhaustion on large images.
*/
if(version_compare(PHP_VERSION, '7.2.0') >= 0) {
$f = @fopen($filename, 'rb');
} else {
$f = $filename;
}
$f = @fopen($filename, 'rb');
if($f) {
return @exif_read_data($f, null, true);
// exif_read_data accepts a stream resource in php > 7.2
$x = @exif_read_data($f, null, true);
fclose($f);
return $x;
}
return false;

23
Zotlabs/Update/_1253.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
namespace Zotlabs\Update;
class _1253 {
function run() {
dbq("START TRANSACTION");
$r = dbq("DELETE FROM app WHERE app_name IN ('Wiki', 'Cards', 'Articles') AND app_plugin = ''");
if($r) {
dbq("COMMIT");
return UPDATE_SUCCESS;
}
dbq("ROLLBACK");
return UPDATE_FAILED;
}
}

View File

@@ -502,8 +502,11 @@ class HTTPSig {
$x = self::sign($head, $prvkey, $alg);
// TODO: should we default to hs2019?
// $headerval = 'keyId="' . $keyid . '",algorithm="' . (($algorithm === 'rsa-sha256') ? 'hs2019' : $algorithm) . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
// TODO: should we default to hs2019? cavage-http-signatures-12 is not very wide spread yet
if (get_config('system', 'use_hs2019', false) && $algorithm === 'rsa-sha256') {
$algorithm = 'hs2019';
}
$headerval = 'keyId="' . $keyid . '",algorithm="' . $algorithm . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';

View File

@@ -17,36 +17,22 @@ class Categories {
function widget($arr) {
$cards = ((array_key_exists('cards',$arr) && $arr['cards']) ? true : false);
if(($cards) && (! Apps::system_app_installed(App::$profile['profile_uid'], 'Cards')))
return '';
$articles = ((array_key_exists('articles',$arr) && $arr['articles']) ? true : false);
if(($articles) && (! Apps::system_app_installed(App::$profile['profile_uid'],'Articles')))
return '';
$files = ((array_key_exists('files',$arr) && $arr['files']) ? true : false);
if((! App::$profile['profile_uid'])
|| (! perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(),(($cards || $articles) ? 'view_pages' : 'view_stream')))) {
if(!App::$profile['profile_uid'] || !perm_is_allowed(App::$profile['profile_uid'], get_observer_hash(), 'view_stream')) {
return '';
}
$cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
$srchurl = (($cards) ? App::$argv[0] . '/' . App::$argv[1] : App::$query_string);
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = str_replace(array('?f=','&f=', '/?'),array('', '', ''),$srchurl);
$cat = ((x($_REQUEST, 'cat')) ? htmlspecialchars($_REQUEST['cat'], ENT_COMPAT, 'UTF-8') : '');
$srchurl = App::$query_string;
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is', '', $srchurl), '&');
$srchurl = str_replace(['?f=','&f=', '/?'], ['', '', ''], $srchurl);
if($cards)
return cardcategories_widget($srchurl, $cat);
elseif($articles)
return articlecategories_widget($srchurl, $cat);
elseif($files)
if($files) {
return filecategories_widget($srchurl, $cat);
else
return categories_widget($srchurl, $cat);
}
return categories_widget($srchurl, $cat);
}
}

View File

@@ -10,6 +10,7 @@
namespace Zotlabs\Widget;
use App;
use Zotlabs\Lib\Apps;
class Notes {
@@ -18,6 +19,9 @@ class Notes {
if(! local_channel())
return EMPTY_STR;
if(App::$profile_uid !== local_channel())
return EMPTY_STR;
if(! Apps::system_app_installed(local_channel(), 'Notes'))
return EMPTY_STR;

View File

@@ -7,12 +7,17 @@
namespace Zotlabs\Widget;
use App;
class Tasklist {
function widget($arr) {
if (! local_channel())
return;
if(! local_channel())
return EMPTY_STR;
if(App::$profile_uid !== local_channel())
return EMPTY_STR;
$o .= '<script>var tasksShowAll = 0; $(document).ready(function() { tasksFetch(); $("#tasklist-new-form").submit(function(event) { event.preventDefault(); $.post( "tasks/new", $("#tasklist-new-form").serialize(), function(data) { tasksFetch(); $("#tasklist-new-summary").val(""); } ); return false; } )});</script>';
$o .= '<script>function taskComplete(id) { $.post("tasks/complete/"+id, function(data) { tasksFetch();}); }

View File

@@ -1,28 +0,0 @@
<?php
/**
* * Name: Wiki list
* * Description: A list of existing wikis
*/
namespace Zotlabs\Widget;
class Wiki_list {
function widget($arr) {
$channel = channelx_by_n(\App::$profile_uid);
$wikis = \Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash());
if($wikis) {
return replace_macros(get_markup_template('wikilist_widget.tpl'), array(
'$header' => t('Wikis'),
'$channel' => $channel['channel_address'],
'$wikis' => $wikis['wikis']
));
}
return '';
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* * Name: Wiki page history
* * Description: History of an existing wiki page
* * Requires: wiki
*/
namespace Zotlabs\Widget;
class Wiki_page_history {
function widget($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = \Zotlabs\Lib\NativeWikiPage::page_history([
'channel_id' => \App::$profile_uid,
'observer_hash' => get_observer_hash(),
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
return replace_macros(get_markup_template('nwiki_page_history.tpl'), array(
'$pageHistory' => $pageHistory['history'],
'$permsWrite' => $arr['permsWrite'],
'$name_lbl' => t('Name'),
'$msg_label' => t('Message','wiki_history'),
'$date_lbl' => t('Date'),
'$revert_btn' => t('Revert'),
'$compare_btn' => t('Compare')
));
}
}

View File

@@ -1,110 +0,0 @@
<?php
/**
* * Name: Wiki pages
* * Description: A list of existing pages of a wiki
* * Requires: wiki
*/
namespace Zotlabs\Widget;
use Zotlabs\Lib\NativeWiki;
class Wiki_pages {
function create_missing_page($arr) {
if(argc() < 4)
return;
$c = channelx_by_nick(argv(1));
$w = \Zotlabs\Lib\NativeWiki::exists_by_name($c['channel_id'],NativeWiki::name_decode(argv(2)));
$arr = array(
'resource_id' => $w['resource_id'],
'channel_id' => $c['channel_id'],
'channel_address' => $c['channel_address'],
'refresh' => false
);
$can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_wiki');
$can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false);
$pageName = NativeWiki::name_decode(escape_tags(argv(3)));
$wikiname = $w['urlName'];
return replace_macros(get_markup_template('wiki_page_not_found.tpl'), array(
'$resource_id' => $arr['resource_id'],
'$channel_address' => $arr['channel_address'],
'$wikiname' => $wikiname,
'$canadd' => $can_create,
'$candel' => $can_delete,
'$addnew' => t('Add new page'),
'$typelock' => $typelock,
'$lockedtype' => $w['mimeType'],
'$mimetype' => mimetype_select(0,$w['mimeType'],
[ 'text/markdown' => t('Markdown'), 'text/bbcode' => t('BBcode'), 'text/plain' => t('Text') ]),
'$pageName' => array('missingPageName', 'Create Page' , $pageName),
'$refresh' => $arr['refresh'],
'$options' => t('Options'),
'$submit' => t('Submit')
));
}
function widget($arr) {
if(argc() < 3)
return;
if(! $arr['resource_id']) {
$c = channelx_by_nick(argv(1));
$w = \Zotlabs\Lib\NativeWiki::exists_by_name($c['channel_id'],NativeWiki::name_decode(argv(2)));
$arr = array(
'resource_id' => $w['resource_id'],
'channel_id' => $c['channel_id'],
'channel_address' => $c['channel_address'],
'refresh' => false
);
}
$wikiname = '';
$pages = array();
$p = \Zotlabs\Lib\NativeWikiPage::page_list($arr['channel_id'],get_observer_hash(),$arr['resource_id']);
if($p['pages']) {
$pages = $p['pages'];
$w = $p['wiki'];
// Wiki item record is $w['wiki']
$wikiname = $w['urlName'];
if (!$wikiname) {
$wikiname = '';
}
$typelock = $w['typelock'];
}
$can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_wiki');
$can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false);
return replace_macros(get_markup_template('wiki_page_list.tpl'), array(
'$resource_id' => $arr['resource_id'],
'$header' => t('Wiki Pages'),
'$channel_address' => $arr['channel_address'],
'$wikiname' => $wikiname,
'$pages' => $pages,
'$canadd' => $can_create,
'$candel' => $can_delete,
'$addnew' => t('Add new page'),
'$typelock' => $typelock,
'$lockedtype' => $w['mimeType'],
'$mimetype' => mimetype_select(0,$w['mimeType'],
[ 'text/markdown' => t('Markdown'), 'text/bbcode' => t('BBcode'), 'text/plain' => t('Text') ]),
'$pageName' => array('pageName', t('Page name')),
'$refresh' => $arr['refresh'],
'$options' => t('Options'),
'$submit' => t('Submit')
));
}
}

View File

@@ -1,7 +0,0 @@
version: 3
url: $baseurl/articles/$nick
name: Articles
requires: local_channel
photo: icon:file-text-o
categories: nav_featured_app, Productivity
desc: Create interactive articles

View File

@@ -1,7 +0,0 @@
version: 3
url: $baseurl/cards/$nick
name: Cards
requires: local_channel
photo: icon:list
categories: nav_featured_app, Productivity
desc: Create interactive personal planning cards.

View File

@@ -1,7 +0,0 @@
version: 3
url: $baseurl/wiki/$nick
requires: local_channel
name: Wiki
photo: icon:pencil-square-o
categories: nav_featured_app, Productivity
desc: A simple yet powerful wiki for your channel.

View File

@@ -60,10 +60,10 @@ require_once('include/bbcode.php');
require_once('include/items.php');
define('PLATFORM_NAME', 'hubzilla');
define('STD_VERSION', '7.2.1');
define('STD_VERSION', '7.4');
define('ZOT_REVISION', '6.0');
define('DB_UPDATE_VERSION', 1252);
define('DB_UPDATE_VERSION', 1253);
define('PROJECT_BASE', __DIR__);
@@ -695,11 +695,7 @@ function sys_boot() {
function startup() {
error_reporting(E_ALL & ~E_NOTICE);
if (version_compare(PHP_VERSION, '8.0.0') >= 0) {
error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE);
}
error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE & ~E_DEPRECATED);
// Some hosting providers block/disable this
@set_time_limit(0);

897
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -59,7 +59,6 @@ function fileas_widget($baseurl,$selected = '') {
));
}
function categories_widget($baseurl,$selected = '') {
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
@@ -124,96 +123,6 @@ function categories_widget($baseurl,$selected = '') {
return '';
}
function cardcategories_widget($baseurl,$selected = '') {
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
return '';
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
$item_normal = "and item.item_hidden = 0 and item.item_type = 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 ";
$terms = array();
$r = q("select distinct(term.term)
from term join item on term.oid = item.id
where item.uid = %d
and term.uid = item.uid
and term.ttype = %d
and term.otype = %d
and item.owner_xchan = '%s'
$item_normal
$sql_extra
order by term.term asc",
intval(App::$profile['profile_uid']),
intval(TERM_CATEGORY),
intval(TERM_OBJ_POST),
dbesc(App::$profile['channel_hash'])
);
if($r && count($r)) {
foreach($r as $rr)
$terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : ''));
return replace_macros(get_markup_template('categories_widget.tpl'),array(
'$title' => t('Categories'),
'$desc' => '',
'$sel_all' => (($selected == '') ? 'selected' : ''),
'$all' => t('Everything'),
'$terms' => $terms,
'$base' => $baseurl,
));
}
return '';
}
function articlecategories_widget($baseurl,$selected = '') {
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
return '';
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
$item_normal = "and item.item_hidden = 0 and item.item_type = 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 ";
$terms = array();
$r = q("select distinct(term.term)
from term join item on term.oid = item.id
where item.uid = %d
and term.uid = item.uid
and term.ttype = %d
and term.otype = %d
and item.owner_xchan = '%s'
$item_normal
$sql_extra
order by term.term asc",
intval(App::$profile['profile_uid']),
intval(TERM_CATEGORY),
intval(TERM_OBJ_POST),
dbesc(App::$profile['channel_hash'])
);
if($r && count($r)) {
foreach($r as $rr)
$terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : ''));
return replace_macros(get_markup_template('categories_widget.tpl'),array(
'$title' => t('Categories'),
'$desc' => '',
'$sel_all' => (($selected == '') ? 'selected' : ''),
'$all' => t('Everything'),
'$terms' => $terms,
'$base' => $baseurl,
));
}
return '';
}
function filecategories_widget($baseurl,$selected = '') {
$perms = permissions_sql(App::$profile['profile_uid']);

View File

@@ -773,7 +773,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
$conv_link_module = 'hq';
}
$conv_link = ((in_array($item['item_type'],[ ITEM_TYPE_CARD, ITEM_TYPE_ARTICLE] )) ? $item['plink'] : z_root() . '/' . $conv_link_module . '/' . gen_link_id($conv_link_mid));
$conv_link = z_root() . '/' . $conv_link_module . '/' . gen_link_id($conv_link_mid);
$contact = [];

View File

@@ -85,7 +85,7 @@ function format_event_obj($jobject) {
'startTime' => (($arr['adjust']) ? datetime_convert('UTC','UTC',$arr['dtstart'], ATOM_TIME) : datetime_convert('UTC','UTC',$arr['dtstart'],'Y-m-d\\TH:i:s-00:00')),
'content' => bbcode($arr['description']),
'location' => [ 'type' => 'Place', 'content' => $arr['location'] ],
'source' => [ 'content' => format_event_bbcode($arr), 'mediaType' => 'text/x-multicode' ],
'source' => [ 'content' => format_event_bbcode($arr), 'mediaType' => 'text/bbcode' ],
'url' => [ [ 'mediaType' => 'text/calendar', 'href' => z_root() . '/events/ical/' . $event['event_hash'] ] ],
'actor' => Activity::encode_person($r[0],false),
];
@@ -141,8 +141,15 @@ function format_event_obj($jobject) {
'$event_tz' => ['label' => t('Timezone'), 'value' => (($tz === date_default_timezone_get()) ? '' : $tz)]
));
$description = [];
if (strpos($object['source']['content'], '[/event-description]') !== false) {
preg_match("/\[event\-description\](.*?)\[\/event\-description\]/ism", $object['source']['content'], $description);
}
$event['content'] = replace_macros(get_markup_template('event_item_content.tpl'), array(
'$description' => $object['content'],
'$description' => ((isset($description[1]))? zidify_links(smilies(bbcode($description[1]))) : EMPTY_STR),
'$location_label' => t('Location:'),
'$location' => ((array_path_exists('location/name', $object)) ? zidify_links(smilies(bbcode($object['location']['name']))) : EMPTY_STR)
));
@@ -1215,7 +1222,7 @@ function event_store_item($arr, $event) {
'startTime' => (($arr['adjust']) ? datetime_convert('UTC', 'UTC', $arr['dtstart'], ATOM_TIME) : datetime_convert('UTC', 'UTC', $arr['dtstart'], 'Y-m-d\\TH:i:s-00:00')),
'content' => bbcode($arr['description']),
'location' => [ 'type' => 'Place', 'name' => $arr['location'] ],
'source' => [ 'content' => format_event_bbcode($arr), 'mediaType' => 'text/x-multicode' ],
'source' => [ 'content' => format_event_bbcode($arr), 'mediaType' => 'text/bbcode' ],
'url' => [ [ 'mediaType' => 'text/calendar', 'href' => z_root() . '/events/ical/' . $event['event_hash'] ] ],
'actor' => Activity::encode_person($r[0], false),
'attachment' => Activity::encode_attachment($r[0]),
@@ -1375,7 +1382,7 @@ function event_store_item($arr, $event) {
'startTime' => (($arr['adjust']) ? datetime_convert('UTC', 'UTC', $arr['dtstart'], ATOM_TIME) : datetime_convert('UTC', 'UTC', $arr['dtstart'], 'Y-m-d\\TH:i:s-00:00')),
'content' => bbcode($arr['description']),
'location' => [ 'type' => 'Place', 'name' => bbcode($arr['location']) ],
'source' => [ 'content' => format_event_bbcode($arr), 'mediaType' => 'text/x-multicode' ],
'source' => [ 'content' => format_event_bbcode($arr), 'mediaType' => 'text/bbcode' ],
'url' => [ [ 'mediaType' => 'text/calendar', 'href' => z_root() . '/events/ical/' . $event['event_hash'] ] ],
'actor' => Activity::encode_person($z, false),
'attachment' => Activity::encode_attachment($item_arr),

View File

@@ -373,6 +373,14 @@ function get_features($filtered = true, $level = (-1)) {
t('If location data is available on uploaded photos, link this to a map.'),
false,
get_config('feature_lock','photo_location'),
],
[
'adult_photo_flagging',
t('Flag Adult Photos'),
t('Provide photo edit option to hide inappropriate photos from default album view'),
false,
get_config('feature_lock','adult_photo_flagging'),
]
],

View File

@@ -3219,6 +3219,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
}
$arr['title'] = $item['title'];
$arr['tgt_type'] = $item['tgt_type'];
$arr['target'] = $item['target'];
@@ -4830,7 +4831,10 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body,
$match = null;
// match img and zmg image links
if(preg_match_all("/\[[zi]mg(.*?)\](.*?)\[\/[zi]mg\]/",$body,$match)) {
$images = $match[2];
// The URI can be in both places
$images = array_merge($match[1], $match[2]);
if($images) {
foreach($images as $image) {
if(! stristr($image,z_root() . '/photo/'))
@@ -4848,6 +4852,7 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body,
dbesc($image_uri),
intval($uid)
);
if($r && $r[0]['folder']) {
$f = q("select * from attach where hash = '%s' and is_dir = 1 and uid = %d limit 1",
dbesc($r[0]['folder']),

View File

@@ -83,7 +83,8 @@ function nav($template = 'default') {
if ($observer) {
$userinfo = [
'icon' => $observer['xchan_photo_m'] . '?rev=' . strtotime($observer['xchan_photo_date']),
'name' => $observer['xchan_addr'],
'addr' => $observer['xchan_addr'],
'name' => $observer['xchan_name'],
];
}
@@ -499,29 +500,6 @@ function channel_apps($is_owner = false, $nickname = null) {
];
}
if ($p['view_pages'] && Apps::system_app_installed($uid, 'Cards')) {
$tabs[] = [
'label' => t('Cards'),
'url' => z_root() . '/cards/' . $nickname,
'sel' => ((argv(0) == 'cards') ? 'active' : ''),
'title' => t('View Cards'),
'id' => 'cards-tab',
'icon' => 'list'
];
}
if ($p['view_pages'] && Apps::system_app_installed($uid, 'Articles')) {
$tabs[] = [
'label' => t('Articles'),
'url' => z_root() . '/articles/' . $nickname,
'sel' => ((argv(0) == 'articles') ? 'active' : ''),
'title' => t('View Articles'),
'id' => 'articles-tab',
'icon' => 'file-text-o'
];
}
if ($has_webpages && Apps::system_app_installed($uid, 'Webpages')) {
$tabs[] = [
'label' => t('Webpages'),
@@ -533,7 +511,6 @@ function channel_apps($is_owner = false, $nickname = null) {
];
}
if ($p['view_wiki'] && Apps::system_app_installed($uid, 'Wiki')) {
$tabs[] = [
'label' => t('Wikis'),

View File

@@ -359,13 +359,13 @@ function photo_upload($channel, $observer, $args) {
$scale = 1;
$width = $url[1]['width'];
$height = $url[1]['height'];
$tag = (($r1) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]');
$tag = (($r1) ? '[zmg=' . $url[1]['href'] . ']' : '[zmg]');
}
else {
$scale = 2;
$width = $url[2]['width'];
$height = $url[2]['height'];
$tag = (($r2) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]');
$tag = (($r2) ? '[zmg=' .$url[2]['href'] . ']' : '[zmg]');
}
$author_link = '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $channel['channel_name'] . '[/zrl]';
@@ -379,7 +379,7 @@ function photo_upload($channel, $observer, $args) {
$summary = (($args['body']) ? $args['body'] : '') . '[footer]' . $activity_format . '[/footer]';
$obj_body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
. $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]'
. $tag . $filename . '[/zmg]'
. '[/zrl]';
$url[] = [

View File

@@ -1,22 +1,22 @@
Software Installation
We've tried very hard to ensure that this software will run on commodity
hosting platforms - such as those used to host Wordpress blogs and Drupal
hosting platforms - such as those used to host Wordpress blogs and Drupal
websites. It will run on most any Linux VPS system. Windows LAMP platforms
such as XAMPP and WAMP are not officially supported at this time - however
we welcome patches if you manage to get it working.
such as XAMPP and WAMP are not officially supported at this time - however
we welcome patches if you manage to get it working.
Be aware that this software is more than a simple web application. It is a
complex communications and content management system which more closely
resembles an email server than a web server. For reliability and performance,
messages are delivered in the background and are queued for later delivery
Be aware that this software is more than a simple web application. It is a
complex communications and content management system which more closely
resembles an email server than a web server. For reliability and performance,
messages are delivered in the background and are queued for later delivery
when sites are down. This kind of functionality requires a bit more of the
host system than the typical blog. Not every PHP/MySQL hosting provider will
be able to support Hubzilla. Many will - but please review the requirements
and confirm these with your hosting provider prior to installation. (And
and confirm these with your hosting provider prior to installation. (And
preferably before entering into a long-term contract.)
If you encounter installation issues, please let us know via the issue
If you encounter installation issues, please let us know via the issue
tracker at https://framagit.org/hubzilla where you downloaded the software.
Please be as clear as you can about your operating environment and provide as
much detail as possible about any error messages you may see, so that we can
@@ -27,14 +27,14 @@ our best to solve any general code issues.
**Before you begin**
**Before you begin**
Choose a domain name or subdomain name for your server.
The software can only be installed into the root of a domain or
sub-domain, and can not be installed using alternate TCP ports. These
sub-domain, and can not be installed using alternate TCP ports. These
restrictions may be relaxed in the future, but will be inconvenient to work
with, so we still STRONGLY recommend you abide by them.
with, so we still STRONGLY recommend you abide by them.
Decide if you will use SSL and obtain an SSL certificate before software
installation. You SHOULD use SSL. If you use SSL, you MUST use a
@@ -46,19 +46,19 @@ site for the first time, please use the SSL ("https://") URL if SSL is
available. This will avoid problems later. The installation routine will not
allow you to use a non browser-valid certificate.
This restriction is incorporated because public posts from you may contain
This restriction is incorporated because public posts from you may contain
references to images on your own hub. Other members viewing their stream on
other hubs will get warnings if your certificate is not trusted by their web
browser. This will confuse many people because this is a decentralised network
and they will get the warning about your hub while viewing their own hub and
may think their own hub has an issue. These warnings are very technical and
may think their own hub has an issue. These warnings are very technical and
scary to some folks, many of whom will not know how to proceed except to
follow the browser advice. This is disruptive to the community. That said, we
recognise the issues surrounding the current certificate infrastructure and
agree there are many problems, but that doesn't change the requirement.
agree there are many problems, but that doesn't change the requirement.
Free "browser-valid" certificates are available from providers such as StartSSL
and LetsEncrypt.
and LetsEncrypt.
If you do NOT use SSL, there may be a delay of up to a minute for the initial
install script - while we check the SSL port to see if anything responds there.
@@ -66,10 +66,10 @@ When communicating with new sites, Hubzilla always attempts connection on the
SSL port first, before falling back to a less secure connection. If you do not
use SSL, your webserver MUST NOT listen on port 443 at all.
If you use LetsEncrypt to provide certificates and create a file under
If you use LetsEncrypt to provide certificates and create a file under
.well-known/acme-challenge so that LetsEncrypt can verify your domain
ownership, please remove or rename the .well-known directory as soon as the
certificate is generated. The software will provide its own handler for
certificate is generated. The software will provide its own handler for
".well-known" services when it is installed, and an existing directory in this
location may prevent some of these services from working correctly. This
should not be a problem with Apache, but may be an issue with nginx or other
@@ -78,40 +78,40 @@ web server platforms.
**Installation**
1. Requirements
- Apache with mod-rewrite enabled and "AllowOverride All" so you can use a
- Apache with mod-rewrite enabled and "AllowOverride All" so you can use a
local .htaccess file. Some folks have successfully used nginx and lighttpd.
Example config scripts are available for these platforms in the install
directory. Apache and nginx have the most support.
Example config scripts are available for these platforms in the install
directory. Apache and nginx have the most support.
- PHP 7.1 or later.
- PHP 8.0 or later.
- PHP *command line* access with register_argc_argv set to true in the
php.ini file - and with no hosting provider restrictions on the use of
- PHP *command line* access with register_argc_argv set to true in the
php.ini file - and with no hosting provider restrictions on the use of
exec() and proc_open().
- curl, gd (with at least jpeg and png support), mysqli, mbstring, xml,
xmlreader (FreeBSD), zip and openssl extensions. The imagick extension MAY be used
instead of gd, but is not required and MAY also be disabled via
configuration option.
- curl, gd (with at least jpeg and png support), mysqli, mbstring, xml,
xmlreader (FreeBSD), zip and openssl extensions. The imagick extension MAY be used
instead of gd, but is not required and MAY also be disabled via
configuration option.
- some form of email server or email gateway such that PHP mail() works.
- Mysql 5.5.3 or later or MariaDB or postgres database server.
- ability to schedule jobs with cron.
- Installation into a top-level domain or sub-domain (without a
- Installation into a top-level domain or sub-domain (without a
directory/path component in the URL) is REQUIRED.
2. Unpack the project files into the root of your web server document area.
If you copy the directory tree to your webserver, make sure that you
also copy .htaccess - as "dot" files are often hidden and aren't normally
If you copy the directory tree to your webserver, make sure that you
also copy .htaccess - as "dot" files are often hidden and aren't normally
copied.
- If you are able to do so, we recommend using git to clone the source
repository rather than to use a packaged tar or zip file. This makes the
software much easier to update. The Linux command to clone the repository
- If you are able to do so, we recommend using git to clone the source
repository rather than to use a packaged tar or zip file. This makes the
software much easier to update. The Linux command to clone the repository
into a directory "mywebsite" would be
git clone https://framagit.org/hubzilla/core.git mywebsite
@@ -120,7 +120,7 @@ web server platforms.
git pull
- make sure folders *store/[data]/smarty3* and *store* exist and are
- make sure folders *store/[data]/smarty3* and *store* exist and are
writable by the webserver
mkdir -p "store/[data]/smarty3"
@@ -134,7 +134,7 @@ web server platforms.
difficult without opening a trouble ticket with your provider. The
above permissions will allow the software to work, but are not
optimal.]
- For installing addons
- First you should be **on** your website folder
@@ -142,12 +142,12 @@ web server platforms.
cd mywebsite
- Then you should clone the addon repository (separately). We'll give this repository
a nickname of 'hzaddons'. You can pull in other hubzilla addon repositories by
a nickname of 'hzaddons'. You can pull in other hubzilla addon repositories by
giving them different nicknames.
util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons
- For keeping the addon tree updated, you should be on your top level website
- For keeping the addon tree updated, you should be on your top level website
directory and issue an update command for that repository.
cd mywebsite
@@ -163,53 +163,53 @@ web server platforms.
3. Create an empty database and note the access details (hostname, username,
password, database name). The PDO database libraries will fallback to socket
3. Create an empty database and note the access details (hostname, username,
password, database name). The PDO database libraries will fallback to socket
communication if the hostname is 'localhost' and some people have reported
issues with the socket implementation. Use it if your requirements mandate.
issues with the socket implementation. Use it if your requirements mandate.
Otherwise if the database is served on the local server, use '127.0.0.1' for
the hostname.
the hostname.
Internally we now use the PDO library for database connections. If you
Internally we now use the PDO library for database connections. If you
encounter a database configuration which cannot be expressed on the setup form
(for instance using MySQL with an unusual socket location); you can supply
the PDO connection string as the database hostname. For instance
:/path/to/socket.file
You should still fill in all other applicable form values as needed.
You should still fill in all other applicable form values as needed.
4. If you know in advance that it will be impossible for the web server to
write or create files in your web directory, create an empty file called
4. If you know in advance that it will be impossible for the web server to
write or create files in your web directory, create an empty file called
.htconfig.php and make it writable by the web server.
5. Visit your website with a web browser and follow the instructions. Please
5. Visit your website with a web browser and follow the instructions. Please
note any error messages and correct these before continuing. If you are using
SSL with a known signature authority, use the https: link to your
website.
website.
6. *If* the automated installation fails for any reason, check the following:
- ".htconfig.php" exists
If not, edit htconfig.php and change system settings. Rename
- ".htconfig.php" exists
If not, edit htconfig.php and change system settings. Rename
to .htconfig.php
- Database is populated.
If not, import the contents of "install/schema_xxxxx.sql" with phpmyadmin
If not, import the contents of "install/schema_xxxxx.sql" with phpmyadmin
or mysql command line (replace 'xxxxx' with your DB type).
7. At this point visit your website again, and register your personal account.
Registration errors should all be recoverable automatically.
7. At this point visit your website again, and register your personal account.
Registration errors should all be recoverable automatically.
If you get any *critical* failure at this point, it generally indicates the
database was not installed correctly. You might wish to move/rename
.htconfig.php to another name and empty (called 'dropping') the database
database was not installed correctly. You might wish to move/rename
.htconfig.php to another name and empty (called 'dropping') the database
tables, so that you can start fresh.
In order for your account to be given administrator access, it should be the
first account created, and the email address provided during registration
must match the "administrator email" address you provided during
must match the "administrator email" address you provided during
installation. Otherwise to give an account administrator access,
add 4096 to the account_roles for that account in the database.
add 4096 to the account_roles for that account in the database.
For your site security there is no way to provide administrator access
using web forms.
@@ -220,29 +220,29 @@ using web forms.
****************************************************************************
****************************************************************************
8. Set up a cron job or scheduled task to run the Cron manager once every 10-15
8. Set up a cron job or scheduled task to run the Cron manager once every 10-15
minutes to perform background processing and maintenance. Example:
cd /base/directory; /path/to/php Zotlabs/Daemon/Master.php Cron
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
If you are using a Linux server, run "crontab -e" and add a line like the
If you are using a Linux server, run "crontab -e" and add a line like the
one shown, substituting for your unique paths and settings:
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php Zotlabs/Daemon/Master.php Cron > /dev/null 2>&1
You can generally find the location of PHP by executing "which php". If you
have troubles with this section please contact your hosting provider for
You can generally find the location of PHP by executing "which php". If you
have troubles with this section please contact your hosting provider for
assistance. Hubzilla will not work correctly if you cannot perform this step.
You should also be sure that App::$config['system']['php_path'] is set correctly
in your .htconfig.php file, it should look like (changing it to the correct
You should also be sure that App::$config['system']['php_path'] is set correctly
in your .htconfig.php file, it should look like (changing it to the correct
PHP location):
App::$config['system']['php_path'] = '/usr/local/php56/bin/php';
App::$config['system']['php_path'] = '/usr/local/php80/bin/php';
#####################################################################
If things don't work...
@@ -251,54 +251,54 @@ App::$config['system']['php_path'] = '/usr/local/php56/bin/php';
#####################################################################
- If you get the message
- If you get the message
"System is currently unavailable. Please try again later"
#####################################################################
Check your database settings. It usually means your database could not be
Check your database settings. It usually means your database could not be
opened or accessed. If the database resides on the same machine, check that
the database server name is "127.0.0.1" or the word "localhost".
the database server name is "127.0.0.1" or the word "localhost".
#####################################################################
- 500 Internal Error
#####################################################################
This could be the result of one of our Apache directives not being
This could be the result of one of our Apache directives not being
supported by your version of Apache. Examine your apache server logs.
Also check your file permissions. Your website and all contents must generally
Also check your file permissions. Your website and all contents must generally
be world-readable.
It is likely that your web server reported the source of the problem in
its error log files. Please review these system error logs to determine what
its error log files. Please review these system error logs to determine what
caused the problem. Often this will need to be resolved with your hosting
provider or (if self-hosted) your web server configuration.
provider or (if self-hosted) your web server configuration.
#####################################################################
- 400 and 4xx "File not found" errors
#####################################################################
First check your file permissions. Your website and all contents must
First check your file permissions. Your website and all contents must
generally be world-readable.
Ensure that mod-rewite is installed and working, and that your
.htaccess file is being used. To verify the latter, create a file test.out
containing the word "test" in the top directory of the Hubzilla, make it world
containing the word "test" in the top directory of the Hubzilla, make it world
readable and point your web browser to
http://yoursitenamehere.com/test.out
This file should be blocked. You should get a permission denied message.
If you see the word "test" your Apache configuration is not allowing your
If you see the word "test" your Apache configuration is not allowing your
.htaccess file to be used (there are rules in this file to block access
to any file with .out at the end, as these are typically used for system logs).
Make certain the .htaccess file exists and is readable by everybody, then
look for the existence of "AllowOverride None" in the Apache server
configuration for your site. This will need to be changed to
"AllowOverride All".
Make certain the .htaccess file exists and is readable by everybody, then
look for the existence of "AllowOverride None" in the Apache server
configuration for your site. This will need to be changed to
"AllowOverride All".
If you do not see the word "test", your .htaccess is working, but it is
If you do not see the word "test", your .htaccess is working, but it is
likely that mod-rewrite is not installed in your web server or is not working.
On most flavours of Linux,
@@ -306,30 +306,30 @@ likely that mod-rewrite is not installed in your web server or is not working.
% a2enmod rewrite
% /etc/init.d/apache2 restart
Consult your hosting provider, experts on your particular Linux
distribution or (if Windows) the provider of your Apache server software if
you need to change either of these and can not figure out how. There is
a lot of help available on the web. Google "mod-rewrite" along with the
Consult your hosting provider, experts on your particular Linux
distribution or (if Windows) the provider of your Apache server software if
you need to change either of these and can not figure out how. There is
a lot of help available on the web. Google "mod-rewrite" along with the
name of your operating system distribution or Apache package.
#####################################################################
- If you see an error during database setup that DNS lookup failed
#####################################################################
This is a known issue on some versions of FreeBSD, because
dns_get_record() fails for some lookups. Create a file in your top webserver
This is a known issue on some versions of FreeBSD, because
dns_get_record() fails for some lookups. Create a file in your top webserver
folder called '.htpreconfig.php' and inside it put the following:
<?php
App::$config['system']['do_not_check_dns'] = 1;
This should allow installation to proceed. Once the database has been
installed, add the same config statement (but not the '<?php' line) to the
.htconfig.php file which was created during installation.
installed, add the same config statement (but not the '<?php' line) to the
.htconfig.php file which was created during installation.
#####################################################################
- If you are unable to write the file .htconfig.php during installation
- If you are unable to write the file .htconfig.php during installation
due to permissions issues:
#####################################################################
@@ -339,7 +339,7 @@ For Linux:
% touch .htconfig.php
% chmod 777 .htconfig.php
Retry the installation. As soon as the database has been created,
Retry the installation. As soon as the database has been created,
******* this is important *********
@@ -437,5 +437,5 @@ MaxRequestWorkers to 70.
Here you can read more about Apache performance tuning:
https://httpd.apache.org/docs/2.4/misc/perf-tuning.html
There are tons of scripts to help you with fine-tuning your Apache installation.
There are tons of scripts to help you with fine-tuning your Apache installation.
Just search with your favorite search engine 'apache fine-tuning script'.

File diff suppressed because it is too large Load Diff

5
vendor/autoload.php vendored
View File

@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit7b34d7e50a62201ec5d5e526a5b8b35d::getLoader();

View File

@@ -0,0 +1,55 @@
name: Test Suite
on:
push:
branches:
- master
pull_request:
jobs:
test:
runs-on: ubuntu-latest
services:
redis:
image: redis
ports:
- 6379:6379
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
mongodb:
image: mongo
ports:
- 27017:27017
myriadb:
image: mariadb
env:
MYSQL_ROOT_PASSWORD: root
ports:
- 3808:3808
- 3306:3306
postgres:
image: postgres
env:
POSTGRES_DB: oauth2_server_php
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: --health-cmd="pg_isready -h localhost" --health-interval=10s --health-timeout=5s --health-retries=5
strategy:
matrix:
php: [ 7.1, 7.2, 7.3, 7.4, "8.0", 8.1 ]
name: "PHP ${{ matrix.php }} Unit Test"
steps:
- uses: actions/checkout@v2
- uses: codecov/codecov-action@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mongodb, mbstring, intl, redis, pdo_mysql
- name: Install composer dependencies
uses: nick-invision/retry@v1
with:
timeout_minutes: 10
max_attempts: 3
command: composer install
- name: Run PHPUnit
run: vendor/bin/phpunit -v

View File

@@ -16,15 +16,16 @@
"psr-0": { "OAuth2": "src/" }
},
"require":{
"php":">=5.3.9"
"php":">=7.1"
},
"require-dev": {
"phpunit/phpunit": "^4.0",
"aws/aws-sdk-php": "~2.8",
"firebase/php-jwt": "~2.2",
"predis/predis": "dev-master",
"phpunit/phpunit": "^7.5||^8.0",
"aws/aws-sdk-php": "^2.8",
"firebase/php-jwt": "^2.2",
"predis/predis": "^1.1",
"thobbs/phpcassa": "dev-master",
"mongodb/mongodb": "^1.1"
"mongodb/mongodb": "^1.1",
"yoast/phpunit-polyfills": "^1.0"
},
"suggest": {
"predis/predis": "Required to use Redis storage",

View File

View File

@@ -133,7 +133,7 @@ class AuthorizeControllerTest extends TestCase
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertNotContains('error', $response->getHttpHeader('Location'));
$this->assertStringNotContainsString('error', $response->getHttpHeader('Location'));
}
public function testEnforceScope()
@@ -161,7 +161,7 @@ class AuthorizeControllerTest extends TestCase
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertNotContains('error', $response->getHttpHeader('Location'));
$this->assertStringNotContainsString('error', $response->getHttpHeader('Location'));
}
public function testInvalidRedirectUri()
@@ -227,7 +227,7 @@ class AuthorizeControllerTest extends TestCase
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertContains('code', $response->getHttpHeader('Location'));
$this->assertStringContainsString('code', $response->getHttpHeader('Location'));
}
public function testRedirectUriWithDifferentQueryAndExactMatchRequired()
@@ -263,7 +263,7 @@ class AuthorizeControllerTest extends TestCase
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertContains('code', $response->getHttpHeader('Location'));
$this->assertStringContainsString('code', $response->getHttpHeader('Location'));
}
public function testMultipleRedirectUris()
@@ -278,14 +278,14 @@ class AuthorizeControllerTest extends TestCase
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertContains('code', $response->getHttpHeader('Location'));
$this->assertStringContainsString('code', $response->getHttpHeader('Location'));
// call again with different (but still valid) redirect URI
$request->query['redirect_uri'] = 'http://morehazards.com';
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertContains('code', $response->getHttpHeader('Location'));
$this->assertStringContainsString('code', $response->getHttpHeader('Location'));
}
/**
@@ -303,7 +303,7 @@ class AuthorizeControllerTest extends TestCase
$server->handleAuthorizeRequest($request, $response = new Response(), true);
$this->assertEquals($response->getStatusCode(), 302);
$this->assertContains('state', $response->getHttpHeader('Location'));
$this->assertStringContainsString('state', $response->getHttpHeader('Location'));
$this->assertStringStartsWith('http://brentertainment.com?code=', $response->getHttpHeader('Location'));
$parts = parse_url($response->getHttpHeader('Location'));
@@ -421,7 +421,7 @@ class AuthorizeControllerTest extends TestCase
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertFalse(isset($parts['fake']));

View File

@@ -9,7 +9,7 @@ class FirebaseJwtTest extends TestCase
{
private $privateKey;
public function setUp()
public function setUp(): void
{
$this->privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----

View File

@@ -9,7 +9,7 @@ class JwtTest extends TestCase
{
private $privateKey;
public function setUp()
public function setUp(): void
{
$this->privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----

View File

@@ -13,7 +13,7 @@ class JwtBearerTest extends TestCase
{
private $privateKey;
public function setUp()
public function setUp(): void
{
$this->privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----

View File

@@ -29,7 +29,7 @@ class CodeIdTokenTest extends TestCase
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertArrayHasKey('query', $parts);
@@ -87,7 +87,7 @@ class CodeIdTokenTest extends TestCase
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertArrayHasKey('query', $parts);
@@ -133,7 +133,7 @@ class CodeIdTokenTest extends TestCase
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertArrayHasKey('query', $parts);

View File

@@ -52,7 +52,7 @@ class IdTokenTest extends TestCase
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertArrayHasKey('fragment', $parts);
@@ -110,7 +110,7 @@ class IdTokenTest extends TestCase
{
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertArrayHasKey('fragment', $parts);

View File

@@ -31,7 +31,7 @@ class IdTokenTokenTest extends TestCase
$this->assertEquals($response->getStatusCode(), 302);
$location = $response->getHttpHeader('Location');
$this->assertNotContains('error', $location);
$this->assertStringNotContainsString('error', $location);
$parts = parse_url($location);
$this->assertArrayHasKey('fragment', $parts);

View File

@@ -14,7 +14,7 @@ class ResponseTest extends TestCase
));
$string = $response->getResponseBody('xml');
$this->assertContains('<response><foo>bar</foo><halland>oates</halland></response>', $string);
$this->assertStringContainsString('<response><foo>bar</foo><halland>oates</halland></response>', $string);
}
public function testSetRedirect()

View File

@@ -6,27 +6,26 @@ use OAuth2\Request\TestRequest;
use OAuth2\ResponseType\AuthorizationCode;
use OAuth2\Storage\Bootstrap;
use PHPUnit\Framework\TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectPHPException;
class ServerTest extends TestCase
{
/**
* @expectedException LogicException OAuth2\Storage\ClientInterface
**/
use ExpectPHPException;
public function testGetAuthorizeControllerWithNoClientStorageThrowsException()
{
$this->expectExceptionMessage('OAuth2\Storage\ClientInterface');
// must set Client Storage
$server = new Server();
$server->getAuthorizeController();
}
/**
* @expectedException LogicException OAuth2\Storage\AccessTokenInterface
**/
public function testGetAuthorizeControllerWithNoAccessTokenStorageThrowsException()
{
$this->expectExceptionMessage('OAuth2\Storage\AccessTokenInterface');
// must set AccessToken or AuthorizationCode
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientInterface'));
$server->getAuthorizeController();
}
@@ -34,8 +33,8 @@ class ServerTest extends TestCase
{
// must set AccessToken or AuthorizationCode
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\ClientInterface'));
$server->addResponseType($this->getMock('OAuth2\ResponseType\AccessTokenInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientInterface'));
$server->addResponseType($this->createMock('OAuth2\ResponseType\AccessTokenInterface'));
$this->assertNotNull($server->getAuthorizeController());
}
@@ -44,21 +43,19 @@ class ServerTest extends TestCase
{
// must set AccessToken or AuthorizationCode
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\ClientInterface'));
$server->addResponseType($this->getMock('OAuth2\ResponseType\AuthorizationCodeInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientInterface'));
$server->addResponseType($this->createMock('OAuth2\ResponseType\AuthorizationCodeInterface'));
$this->assertNotNull($server->getAuthorizeController());
}
/**
* @expectedException LogicException allow_implicit
**/
public function testGetAuthorizeControllerWithClientStorageAndAccessTokenStorageThrowsException()
{
// must set AuthorizationCode or AccessToken / implicit
$this->expectExceptionMessage('allow_implicit');
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'));
$this->assertNotNull($server->getAuthorizeController());
}
@@ -67,8 +64,8 @@ class ServerTest extends TestCase
{
// must set AuthorizationCode or AccessToken / implicit
$server = new Server(array(), array('allow_implicit' => true));
$server->addStorage($this->getMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'));
$this->assertNotNull($server->getAuthorizeController());
}
@@ -77,63 +74,55 @@ class ServerTest extends TestCase
{
// must set AccessToken or AuthorizationCode
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\AuthorizationCodeInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\AuthorizationCodeInterface'));
$this->assertNotNull($server->getAuthorizeController());
}
/**
* @expectedException LogicException grant_types
**/
public function testGetTokenControllerWithGrantTypeStorageThrowsException()
{
$this->expectExceptionMessage('grant_types');
$server = new Server();
$server->getTokenController();
}
/**
* @expectedException LogicException OAuth2\Storage\ClientCredentialsInterface
**/
public function testGetTokenControllerWithNoClientCredentialsStorageThrowsException()
{
$this->expectExceptionMessage('OAuth2\Storage\ClientCredentialsInterface');
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\UserCredentialsInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\UserCredentialsInterface'));
$server->getTokenController();
}
/**
* @expectedException LogicException OAuth2\Storage\AccessTokenInterface
**/
public function testGetTokenControllerWithNoAccessTokenStorageThrowsException()
{
$this->expectExceptionMessage('OAuth2\Storage\AccessTokenInterface');
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->getTokenController();
}
public function testGetTokenControllerWithAccessTokenAndClientCredentialsStorage()
{
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->getTokenController();
}
public function testGetTokenControllerAccessTokenStorageAndClientCredentialsStorageAndGrantTypes()
{
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addGrantType($this->getMockBuilder('OAuth2\GrantType\AuthorizationCode')->disableOriginalConstructor()->getMock());
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addGrantType($this->createMock('OAuth2\GrantType\AuthorizationCode'));
$server->getTokenController();
}
/**
* @expectedException LogicException OAuth2\Storage\AccessTokenInterface
**/
public function testGetResourceControllerWithNoAccessTokenStorageThrowsException()
{
$this->expectExceptionMessage('OAuth2\Storage\AccessTokenInterface');
$server = new Server();
$server->getResourceController();
}
@@ -141,41 +130,35 @@ class ServerTest extends TestCase
public function testGetResourceControllerWithAccessTokenStorage()
{
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'));
$server->getResourceController();
}
/**
* @expectedException InvalidArgumentException OAuth2\Storage\AccessTokenInterface
**/
public function testAddingStorageWithInvalidClass()
{
$this->expectExceptionMessage('OAuth2\Storage\AccessTokenInterface');
$server = new Server();
$server->addStorage(new \StdClass());
}
/**
* @expectedException InvalidArgumentException access_token
**/
public function testAddingStorageWithInvalidKey()
{
$this->expectExceptionMessage('access_token');
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'), 'nonexistant_storage');
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'), 'nonexistant_storage');
}
/**
* @expectedException InvalidArgumentException OAuth2\Storage\AuthorizationCodeInterface
**/
public function testAddingStorageWithInvalidKeyStorageCombination()
{
$this->expectExceptionMessage('OAuth2\Storage\AuthorizationCodeInterface');
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\AccessTokenInterface'), 'authorization_code');
$server->addStorage($this->createMock('OAuth2\Storage\AccessTokenInterface'), 'authorization_code');
}
public function testAddingStorageWithValidKeyOnlySetsThatKey()
{
$server = new Server();
$server->addStorage($this->getMock('OAuth2\Storage\Memory'), 'access_token');
$server->addStorage($this->createMock('OAuth2\Storage\Memory'), 'access_token');
$reflection = new \ReflectionClass($server);
$prop = $reflection->getProperty('storages');
@@ -191,7 +174,7 @@ class ServerTest extends TestCase
public function testAddingClientStorageSetsClientCredentialsStorageByDefault()
{
$server = new Server();
$memory = $this->getMock('OAuth2\Storage\Memory');
$memory = $this->createMock('OAuth2\Storage\Memory');
$server->addStorage($memory, 'client');
$client_credentials = $server->getStorage('client_credentials');
@@ -202,7 +185,7 @@ class ServerTest extends TestCase
public function testAddStorageWithNullValue()
{
$memory = $this->getMock('OAuth2\Storage\Memory');
$memory = $this->createMock('OAuth2\Storage\Memory');
$server = new Server($memory);
$server->addStorage(null, 'refresh_token');
@@ -218,7 +201,7 @@ class ServerTest extends TestCase
public function testNewServerWithNullStorageValue()
{
$memory = $this->getMock('OAuth2\Storage\Memory');
$memory = $this->createMock('OAuth2\Storage\Memory');
$server = new Server(array(
'client_credentials' => $memory,
'refresh_token' => null,
@@ -237,7 +220,7 @@ class ServerTest extends TestCase
public function testAddingClientCredentialsStorageSetsClientStorageByDefault()
{
$server = new Server();
$memory = $this->getMock('OAuth2\Storage\Memory');
$memory = $this->createMock('OAuth2\Storage\Memory');
$server->addStorage($memory, 'client_credentials');
$client = $server->getStorage('client');
@@ -249,10 +232,9 @@ class ServerTest extends TestCase
public function testSettingClientStorageByDefaultDoesNotOverrideSetStorage()
{
$server = new Server();
$pdo = $this->getMockBuilder('OAuth2\Storage\Pdo')
->disableOriginalConstructor()->getMock();
$pdo = $this->createMock('OAuth2\Storage\Pdo');
$memory = $this->getMock('OAuth2\Storage\Memory');
$memory = $this->createMock('OAuth2\Storage\Memory');
$server->addStorage($pdo, 'client');
$server->addStorage($memory, 'client_credentials');
@@ -266,7 +248,7 @@ class ServerTest extends TestCase
public function testAddingResponseType()
{
$storage = $this->getMock('OAuth2\Storage\Memory');
$storage = $this->createMock('OAuth2\Storage\Memory');
$storage
->expects($this->any())
->method('getClientDetails')
@@ -323,7 +305,7 @@ class ServerTest extends TestCase
'code' => 'testcode',
));
// verify the mock clientAssertionType was called as expected
$clientAssertionType = $this->getMock('OAuth2\ClientAssertionType\ClientAssertionTypeInterface', array('validateRequest', 'getClientId'));
$clientAssertionType = $this->createMock('OAuth2\ClientAssertionType\ClientAssertionTypeInterface');
$clientAssertionType
->expects($this->once())
->method('validateRequest')
@@ -420,98 +402,84 @@ class ServerTest extends TestCase
$this->assertFalse($used_token, 'the refresh token used is no longer valid');
}
/**
* @expectedException InvalidArgumentException OAuth2\ResponseType\AuthorizationCodeInterface
**/
public function testAddingUnknownResponseTypeThrowsException()
{
$this->expectExceptionMessage('OAuth2\ResponseType\AuthorizationCodeInterface');
$server = new Server();
$server->addResponseType($this->getMock('OAuth2\ResponseType\ResponseTypeInterface'));
$server->addResponseType($this->createMock('OAuth2\ResponseType\ResponseTypeInterface'));
}
/**
* @expectedException LogicException OAuth2\Storage\PublicKeyInterface
**/
public function testUsingJwtAccessTokensWithoutPublicKeyStorageThrowsException()
{
$this->expectExceptionMessage('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array(), array('use_jwt_access_tokens' => true));
$server->addGrantType($this->getMock('OAuth2\GrantType\GrantTypeInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addStorage($this->getMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addGrantType($this->createMock('OAuth2\GrantType\GrantTypeInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->addStorage($this->createMock('OAuth2\Storage\ClientCredentialsInterface'));
$server->getTokenController();
}
public function testUsingJustJwtAccessTokenStorageWithResourceControllerIsOkay()
{
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($pubkey), array('use_jwt_access_tokens' => true));
$this->assertNotNull($server->getResourceController());
$this->assertInstanceOf('OAuth2\Storage\PublicKeyInterface', $server->getStorage('public_key'));
}
/**
* @expectedException LogicException OAuth2\Storage\ClientInterface
**/
public function testUsingJustJwtAccessTokenStorageWithAuthorizeControllerThrowsException()
{
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$this->expectExceptionMessage('OAuth2\Storage\ClientInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($pubkey), array('use_jwt_access_tokens' => true));
$this->assertNotNull($server->getAuthorizeController());
}
/**
* @expectedException LogicException grant_types
**/
public function testUsingJustJwtAccessTokenStorageWithTokenControllerThrowsException()
{
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$this->expectExceptionMessage('grant_types');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($pubkey), array('use_jwt_access_tokens' => true));
$server->getTokenController();
}
public function testUsingJwtAccessTokenAndClientStorageWithAuthorizeControllerIsOkay()
{
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$server = new Server(array($pubkey, $client), array('use_jwt_access_tokens' => true, 'allow_implicit' => true));
$this->assertNotNull($server->getAuthorizeController());
$this->assertInstanceOf('OAuth2\ResponseType\JwtAccessToken', $server->getResponseType('token'));
}
/**
* @expectedException LogicException UserClaims
**/
public function testUsingOpenIDConnectWithoutUserClaimsThrowsException()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$this->expectExceptionMessage('UserClaims');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$server = new Server($client, array('use_openid_connect' => true));
$server->getAuthorizeController();
}
/**
* @expectedException LogicException PublicKeyInterface
**/
public function testUsingOpenIDConnectWithoutPublicKeyThrowsException()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OPenID\Storage\UserClaimsInterface');
$this->expectExceptionMessage('PublicKeyInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OPenID\Storage\UserClaimsInterface');
$server = new Server(array($client, $userclaims), array('use_openid_connect' => true));
$server->getAuthorizeController();
}
/**
* @expectedException LogicException issuer
**/
public function testUsingOpenIDConnectWithoutIssuerThrowsException()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$this->expectExceptionMessage('issuer');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($client, $userclaims, $pubkey), array('use_openid_connect' => true));
$server->getAuthorizeController();
@@ -519,9 +487,9 @@ class ServerTest extends TestCase
public function testUsingOpenIDConnectWithIssuerPublicKeyAndUserClaimsIsOkay()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($client, $userclaims, $pubkey), array(
'use_openid_connect' => true,
'issuer' => 'someguy',
@@ -533,14 +501,12 @@ class ServerTest extends TestCase
$this->assertNull($server->getResponseType('id_token token'));
}
/**
* @expectedException LogicException OAuth2\ResponseType\AccessTokenInterface
**/
public function testUsingOpenIDConnectWithAllowImplicitWithoutTokenStorageThrowsException()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$this->expectErrorMessage('OAuth2\ResponseType\AccessTokenInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($client, $userclaims, $pubkey), array(
'use_openid_connect' => true,
'issuer' => 'someguy',
@@ -552,9 +518,9 @@ class ServerTest extends TestCase
public function testUsingOpenIDConnectWithAllowImplicitAndUseJwtAccessTokensIsOkay()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$server = new Server(array($client, $userclaims, $pubkey), array(
'use_openid_connect' => true,
'issuer' => 'someguy',
@@ -570,10 +536,10 @@ class ServerTest extends TestCase
public function testUsingOpenIDConnectWithAllowImplicitAndAccessTokenStorageIsOkay()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$token = $this->getMock('OAuth2\Storage\AccessTokenInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$token = $this->createMock('OAuth2\Storage\AccessTokenInterface');
$server = new Server(array($client, $userclaims, $pubkey, $token), array(
'use_openid_connect' => true,
'issuer' => 'someguy',
@@ -588,17 +554,17 @@ class ServerTest extends TestCase
public function testUsingOpenIDConnectWithAllowImplicitAndAccessTokenResponseTypeIsOkay()
{
$client = $this->getMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
// $token = $this->getMock('OAuth2\Storage\AccessTokenInterface');
$client = $this->createMock('OAuth2\Storage\ClientInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
// $token = $this->createMock('OAuth2\Storage\AccessTokenInterface');
$server = new Server(array($client, $userclaims, $pubkey), array(
'use_openid_connect' => true,
'issuer' => 'someguy',
'allow_implicit' => true,
));
$token = $this->getMock('OAuth2\ResponseType\AccessTokenInterface');
$token = $this->createMock('OAuth2\ResponseType\AccessTokenInterface');
$server->addResponseType($token, 'token');
$server->getAuthorizeController();
@@ -607,17 +573,15 @@ class ServerTest extends TestCase
$this->assertInstanceOf('OAuth2\OpenID\ResponseType\IdTokenTokenInterface', $server->getResponseType('id_token token'));
}
/**
* @expectedException LogicException OAuth2\OpenID\Storage\AuthorizationCodeInterface
**/
public function testUsingOpenIDConnectWithAuthorizationCodeStorageThrowsException()
{
$client = $this->getMock('OAuth2\Storage\ClientCredentialsInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$token = $this->getMock('OAuth2\Storage\AccessTokenInterface');
$authcode = $this->getMock('OAuth2\Storage\AuthorizationCodeInterface');
$client = $this->createMock('OAuth2\Storage\ClientCredentialsInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$token = $this->createMock('OAuth2\Storage\AccessTokenInterface');
$authcode = $this->createMock('OAuth2\Storage\AuthorizationCodeInterface');
$this->expectErrorMessage('OAuth2\OpenID\Storage\AuthorizationCodeInterface');
$server = new Server(array($client, $userclaims, $pubkey, $token, $authcode), array(
'use_openid_connect' => true,
'issuer' => 'someguy'
@@ -630,11 +594,11 @@ class ServerTest extends TestCase
public function testUsingOpenIDConnectWithOpenIDAuthorizationCodeStorageCreatesOpenIDAuthorizationCodeGrantType()
{
$client = $this->getMock('OAuth2\Storage\ClientCredentialsInterface');
$userclaims = $this->getMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->getMock('OAuth2\Storage\PublicKeyInterface');
$token = $this->getMock('OAuth2\Storage\AccessTokenInterface');
$authcode = $this->getMock('OAuth2\OpenID\Storage\AuthorizationCodeInterface');
$client = $this->createMock('OAuth2\Storage\ClientCredentialsInterface');
$userclaims = $this->createMock('OAuth2\OpenID\Storage\UserClaimsInterface');
$pubkey = $this->createMock('OAuth2\Storage\PublicKeyInterface');
$token = $this->createMock('OAuth2\Storage\AccessTokenInterface');
$authcode = $this->createMock('OAuth2\OpenID\Storage\AuthorizationCodeInterface');
$server = new Server(array($client, $userclaims, $pubkey, $token, $authcode), array(
'use_openid_connect' => true,
@@ -648,7 +612,7 @@ class ServerTest extends TestCase
public function testMultipleValuedResponseTypeOrderDoesntMatter()
{
$responseType = $this->getMock('OAuth2\OpenID\ResponseType\IdTokenTokenInterface');
$responseType = $this->createMock('OAuth2\OpenID\ResponseType\IdTokenTokenInterface');
$server = new Server(array(), array(), array(), array(
'token id_token' => $responseType,
));
@@ -659,7 +623,7 @@ class ServerTest extends TestCase
public function testAddGrantTypeWithoutKey()
{
$server = new Server();
$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->getMock('OAuth2\Storage\AuthorizationCodeInterface')));
$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->createMock('OAuth2\Storage\AuthorizationCodeInterface')));
$grantTypes = $server->getGrantTypes();
$this->assertEquals('authorization_code', key($grantTypes));
@@ -668,7 +632,7 @@ class ServerTest extends TestCase
public function testAddGrantTypeWithKey()
{
$server = new Server();
$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->getMock('OAuth2\Storage\AuthorizationCodeInterface')), 'ac');
$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->createMock('OAuth2\Storage\AuthorizationCodeInterface')), 'ac');
$grantTypes = $server->getGrantTypes();
$this->assertEquals('ac', key($grantTypes));
@@ -677,7 +641,7 @@ class ServerTest extends TestCase
public function testAddGrantTypeWithKeyNotString()
{
$server = new Server();
$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->getMock('OAuth2\Storage\AuthorizationCodeInterface')), 42);
$server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->createMock('OAuth2\Storage\AuthorizationCodeInterface')), 42);
$grantTypes = $server->getGrantTypes();
$this->assertEquals('authorization_code', key($grantTypes));

View File

@@ -2,8 +2,12 @@
namespace OAuth2\Storage;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectPHPException;
class PdoTest extends BaseTest
{
use ExpectPHPException;
public function testCreatePdoStorageUsingPdoClass()
{
$dsn = sprintf('sqlite:%s', Bootstrap::getInstance()->getSqliteDir());
@@ -30,11 +34,9 @@ class PdoTest extends BaseTest
$this->assertNotNull($storage->getClientDetails('oauth_test_client'));
}
/**
* @expectedException InvalidArgumentException dsn
*/
public function testCreatePdoStorageWithoutDSNThrowsException()
{
$this->expectErrorMessage('dsn');
$config = array('username' => 'brent', 'password' => 'brentisaballer');
$storage = new Pdo($config);
}

View File

@@ -1,15 +0,0 @@
<?php
require_once(dirname(__FILE__).'/../src/OAuth2/Autoloader.php');
OAuth2\Autoloader::register();
// register test classes
OAuth2\Autoloader::register(dirname(__FILE__).'/lib');
// register vendors if possible
if (file_exists(__DIR__.'/../vendor/autoload.php')) {
require_once(__DIR__.'/../vendor/autoload.php');
}
// remove the dynamoDB database that was created for this build
OAuth2\Storage\Bootstrap::getInstance()->cleanupTravisDynamoDb();

View File

View File

@@ -68,7 +68,7 @@ class Bootstrap
public function getPostgresDriver()
{
try {
$pdo = new \PDO('pgsql:host=localhost;dbname=oauth2_server_php', 'postgres');
$pdo = new \PDO('pgsql:host=localhost;dbname=oauth2_server_php', 'postgres', 'postgres');
return $pdo;
} catch (\PDOException $e) {
@@ -118,7 +118,7 @@ class Bootstrap
if (!$this->mysql) {
$pdo = null;
try {
$pdo = new \PDO('mysql:host=localhost;', 'root');
$pdo = new \PDO('mysql:host=localhost;', 'root', 'root');
} catch (\PDOException $e) {
$this->mysql = new NullStorage('MySQL', 'Unable to connect to MySQL on root@localhost');
}
@@ -352,11 +352,11 @@ class Bootstrap
private function createPostgresDb()
{
if (!`psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='postgres'"`) {
`createuser -s -r postgres`;
if (!`PGPASSWORD=postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='postgres'" -h localhost -U postgres`) {
`PGPASSWORD=postgres createuser -s -r postgres -h localhost -U postgres`;
}
`createdb -O postgres oauth2_server_php`;
`PGPASSWORD=postgres createdb -O postgres oauth2_server_php -h localhost -U postgres`;
}
private function populatePostgresDb(\PDO $pdo)
@@ -366,8 +366,8 @@ class Bootstrap
private function removePostgresDb()
{
if (trim(`psql -l | grep oauth2_server_php | wc -l`)) {
`dropdb oauth2_server_php`;
if (trim(`PGPASSWORD=postgres psql -l -h localhost -U postgres | grep oauth2_server_php | wc -l`)) {
`PGPASSWORD=postgres dropdb oauth2_server_php -h localhost -U postgres`;
}
}
@@ -945,21 +945,6 @@ class Bootstrap
));
}
public function cleanupTravisDynamoDb($prefix = null)
{
if (is_null($prefix)) {
// skip this when not applicable
if (!$this->getEnvVar('TRAVIS') || self::DYNAMODB_PHP_VERSION != $this->getEnvVar('TRAVIS_PHP_VERSION')) {
return;
}
$prefix = sprintf('build_%s_', $this->getEnvVar('TRAVIS_JOB_NUMBER'));
}
$client = $this->getDynamoDbClient();
$this->deleteDynamoDb($client, $prefix);
}
private function getEnvVar($var, $default = null)
{
return isset($_SERVER[$var]) ? $_SERVER[$var] : (getenv($var) ?: $default);

View File

@@ -21,6 +21,8 @@ use Composer\Semver\VersionParser;
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{

View File

@@ -2,11 +2,10 @@
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Brick\\Math\\BigDecimal' => $vendorDir . '/brick/math/src/BigDecimal.php',
'Brick\\Math\\BigInteger' => $vendorDir . '/brick/math/src/BigInteger.php',
'Brick\\Math\\BigNumber' => $vendorDir . '/brick/math/src/BigNumber.php',
@@ -873,6 +872,39 @@ return array(
'Sabre\\Xml\\XmlDeserializable' => $vendorDir . '/sabre/xml/lib/XmlDeserializable.php',
'Sabre\\Xml\\XmlSerializable' => $vendorDir . '/sabre/xml/lib/XmlSerializable.php',
'SimplePie' => $vendorDir . '/simplepie/simplepie/library/SimplePie.php',
'SimplePie\\Author' => $vendorDir . '/simplepie/simplepie/src/Author.php',
'SimplePie\\Cache' => $vendorDir . '/simplepie/simplepie/src/Cache.php',
'SimplePie\\Cache\\Base' => $vendorDir . '/simplepie/simplepie/src/Cache/Base.php',
'SimplePie\\Cache\\DB' => $vendorDir . '/simplepie/simplepie/src/Cache/DB.php',
'SimplePie\\Cache\\File' => $vendorDir . '/simplepie/simplepie/src/Cache/File.php',
'SimplePie\\Cache\\Memcache' => $vendorDir . '/simplepie/simplepie/src/Cache/Memcache.php',
'SimplePie\\Cache\\Memcached' => $vendorDir . '/simplepie/simplepie/src/Cache/Memcached.php',
'SimplePie\\Cache\\MySQL' => $vendorDir . '/simplepie/simplepie/src/Cache/MySQL.php',
'SimplePie\\Cache\\Redis' => $vendorDir . '/simplepie/simplepie/src/Cache/Redis.php',
'SimplePie\\Caption' => $vendorDir . '/simplepie/simplepie/src/Caption.php',
'SimplePie\\Category' => $vendorDir . '/simplepie/simplepie/src/Category.php',
'SimplePie\\Content\\Type\\Sniffer' => $vendorDir . '/simplepie/simplepie/src/Content/Type/Sniffer.php',
'SimplePie\\Copyright' => $vendorDir . '/simplepie/simplepie/src/Copyright.php',
'SimplePie\\Credit' => $vendorDir . '/simplepie/simplepie/src/Credit.php',
'SimplePie\\Enclosure' => $vendorDir . '/simplepie/simplepie/src/Enclosure.php',
'SimplePie\\Exception' => $vendorDir . '/simplepie/simplepie/src/Exception.php',
'SimplePie\\File' => $vendorDir . '/simplepie/simplepie/src/File.php',
'SimplePie\\Gzdecode' => $vendorDir . '/simplepie/simplepie/src/Gzdecode.php',
'SimplePie\\HTTP\\Parser' => $vendorDir . '/simplepie/simplepie/src/HTTP/Parser.php',
'SimplePie\\IRI' => $vendorDir . '/simplepie/simplepie/src/IRI.php',
'SimplePie\\Item' => $vendorDir . '/simplepie/simplepie/src/Item.php',
'SimplePie\\Locator' => $vendorDir . '/simplepie/simplepie/src/Locator.php',
'SimplePie\\Misc' => $vendorDir . '/simplepie/simplepie/src/Misc.php',
'SimplePie\\Net\\IPv6' => $vendorDir . '/simplepie/simplepie/src/Net/IPv6.php',
'SimplePie\\Parse\\Date' => $vendorDir . '/simplepie/simplepie/src/Parse/Date.php',
'SimplePie\\Parser' => $vendorDir . '/simplepie/simplepie/src/Parser.php',
'SimplePie\\Rating' => $vendorDir . '/simplepie/simplepie/src/Rating.php',
'SimplePie\\Registry' => $vendorDir . '/simplepie/simplepie/src/Registry.php',
'SimplePie\\Restriction' => $vendorDir . '/simplepie/simplepie/src/Restriction.php',
'SimplePie\\Sanitize' => $vendorDir . '/simplepie/simplepie/src/Sanitize.php',
'SimplePie\\SimplePie' => $vendorDir . '/simplepie/simplepie/src/SimplePie.php',
'SimplePie\\Source' => $vendorDir . '/simplepie/simplepie/src/Source.php',
'SimplePie\\XML\\Declaration\\Parser' => $vendorDir . '/simplepie/simplepie/src/XML/Declaration/Parser.php',
'SimplePie_Author' => $vendorDir . '/simplepie/simplepie/library/SimplePie/Author.php',
'SimplePie_Cache' => $vendorDir . '/simplepie/simplepie/library/SimplePie/Cache.php',
'SimplePie_Cache_Base' => $vendorDir . '/simplepie/simplepie/library/SimplePie/Cache/Base.php',
@@ -1074,9 +1106,6 @@ return array(
'Smarty_Template_Source' => $vendorDir . '/smarty/smarty/libs/sysplugins/smarty_template_source.php',
'Smarty_Undefined_Variable' => $vendorDir . '/smarty/smarty/libs/sysplugins/smarty_undefined_variable.php',
'Smarty_Variable' => $vendorDir . '/smarty/smarty/libs/sysplugins/smarty_variable.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php',
'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php',
'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php',
'TPC_yyStackEntry' => $vendorDir . '/smarty/smarty/libs/sysplugins/smarty_internal_configfileparser.php',
'TP_yyStackEntry' => $vendorDir . '/smarty/smarty/libs/sysplugins/smarty_internal_templateparser.php',
@@ -1085,9 +1114,7 @@ return array(
'Text_LanguageDetect_ISO639' => $vendorDir . '/pear/text_languagedetect/Text/LanguageDetect/ISO639.php',
'Text_LanguageDetect_Parser' => $vendorDir . '/pear/text_languagedetect/Text/LanguageDetect/Parser.php',
'URLify' => $vendorDir . '/jbroadway/urlify/URLify.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'UploadHandler' => $vendorDir . '/blueimp/jquery-file-upload/server/php/UploadHandler.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'Zotlabs\\Access\\AccessList' => $baseDir . '/Zotlabs/Access/AccessList.php',
'Zotlabs\\Access\\PermissionLimits' => $baseDir . '/Zotlabs/Access/PermissionLimits.php',
'Zotlabs\\Access\\PermissionRoles' => $baseDir . '/Zotlabs/Access/PermissionRoles.php',
@@ -1157,8 +1184,6 @@ return array(
'Zotlabs\\Lib\\Libzotdir' => $baseDir . '/Zotlabs/Lib/Libzotdir.php',
'Zotlabs\\Lib\\MarkdownSoap' => $baseDir . '/Zotlabs/Lib/MarkdownSoap.php',
'Zotlabs\\Lib\\MessageFilter' => $baseDir . '/Zotlabs/Lib/MessageFilter.php',
'Zotlabs\\Lib\\NativeWiki' => $baseDir . '/Zotlabs/Lib/NativeWiki.php',
'Zotlabs\\Lib\\NativeWikiPage' => $baseDir . '/Zotlabs/Lib/NativeWikiPage.php',
'Zotlabs\\Lib\\PConfig' => $baseDir . '/Zotlabs/Lib/PConfig.php',
'Zotlabs\\Lib\\Permcat' => $baseDir . '/Zotlabs/Lib/Permcat.php',
'Zotlabs\\Lib\\PermissionDescription' => $baseDir . '/Zotlabs/Lib/PermissionDescription.php',
@@ -1200,8 +1225,6 @@ return array(
'Zotlabs\\Module\\Apporder' => $baseDir . '/Zotlabs/Module/Apporder.php',
'Zotlabs\\Module\\Apps' => $baseDir . '/Zotlabs/Module/Apps.php',
'Zotlabs\\Module\\Apschema' => $baseDir . '/Zotlabs/Module/Apschema.php',
'Zotlabs\\Module\\Article_edit' => $baseDir . '/Zotlabs/Module/Article_edit.php',
'Zotlabs\\Module\\Articles' => $baseDir . '/Zotlabs/Module/Articles.php',
'Zotlabs\\Module\\Attach' => $baseDir . '/Zotlabs/Module/Attach.php',
'Zotlabs\\Module\\Attach_edit' => $baseDir . '/Zotlabs/Module/Attach_edit.php',
'Zotlabs\\Module\\Authorize' => $baseDir . '/Zotlabs/Module/Authorize.php',
@@ -1211,8 +1234,6 @@ return array(
'Zotlabs\\Module\\Bookmarks' => $baseDir . '/Zotlabs/Module/Bookmarks.php',
'Zotlabs\\Module\\Branchtopic' => $baseDir . '/Zotlabs/Module/Branchtopic.php',
'Zotlabs\\Module\\Cal' => $baseDir . '/Zotlabs/Module/Cal.php',
'Zotlabs\\Module\\Card_edit' => $baseDir . '/Zotlabs/Module/Card_edit.php',
'Zotlabs\\Module\\Cards' => $baseDir . '/Zotlabs/Module/Cards.php',
'Zotlabs\\Module\\Cdav' => $baseDir . '/Zotlabs/Module/Cdav.php',
'Zotlabs\\Module\\Changeaddr' => $baseDir . '/Zotlabs/Module/Changeaddr.php',
'Zotlabs\\Module\\Channel' => $baseDir . '/Zotlabs/Module/Channel.php',
@@ -1391,7 +1412,6 @@ return array(
'Zotlabs\\Module\\Webpages' => $baseDir . '/Zotlabs/Module/Webpages.php',
'Zotlabs\\Module\\Well_known' => $baseDir . '/Zotlabs/Module/Well_known.php',
'Zotlabs\\Module\\Wfinger' => $baseDir . '/Zotlabs/Module/Wfinger.php',
'Zotlabs\\Module\\Wiki' => $baseDir . '/Zotlabs/Module/Wiki.php',
'Zotlabs\\Module\\Xchan' => $baseDir . '/Zotlabs/Module/Xchan.php',
'Zotlabs\\Module\\Xpoco' => $baseDir . '/Zotlabs/Module/Xpoco.php',
'Zotlabs\\Module\\Xrd' => $baseDir . '/Zotlabs/Module/Xrd.php',
@@ -1675,6 +1695,7 @@ return array(
'Zotlabs\\Update\\_1250' => $baseDir . '/Zotlabs/Update/_1250.php',
'Zotlabs\\Update\\_1251' => $baseDir . '/Zotlabs/Update/_1251.php',
'Zotlabs\\Update\\_1252' => $baseDir . '/Zotlabs/Update/_1252.php',
'Zotlabs\\Update\\_1253' => $baseDir . '/Zotlabs/Update/_1253.php',
'Zotlabs\\Web\\Controller' => $baseDir . '/Zotlabs/Web/Controller.php',
'Zotlabs\\Web\\HTTPHeaders' => $baseDir . '/Zotlabs/Web/HTTPHeaders.php',
'Zotlabs\\Web\\HTTPSig' => $baseDir . '/Zotlabs/Web/HTTPSig.php',
@@ -1743,9 +1764,6 @@ return array(
'Zotlabs\\Widget\\Tokens' => $baseDir . '/Zotlabs/Widget/Tokens.php',
'Zotlabs\\Widget\\Vcard' => $baseDir . '/Zotlabs/Widget/Vcard.php',
'Zotlabs\\Widget\\Website_portation_tools' => $baseDir . '/Zotlabs/Widget/Website_portation_tools.php',
'Zotlabs\\Widget\\Wiki_list' => $baseDir . '/Zotlabs/Widget/Wiki_list.php',
'Zotlabs\\Widget\\Wiki_page_history' => $baseDir . '/Zotlabs/Widget/Wiki_page_history.php',
'Zotlabs\\Widget\\Wiki_pages' => $baseDir . '/Zotlabs/Widget/Wiki_pages.php',
'Zotlabs\\Widget\\Zcard' => $baseDir . '/Zotlabs/Widget/Zcard.php',
'Zotlabs\\Zot6\\IHandler' => $baseDir . '/Zotlabs/Zot6/IHandler.php',
'Zotlabs\\Zot6\\Receiver' => $baseDir . '/Zotlabs/Zot6/Receiver.php',

View File

@@ -2,7 +2,7 @@
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
@@ -14,8 +14,6 @@ return array(
'93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php',
'23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',

View File

@@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@@ -2,7 +2,7 @@
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
@@ -10,8 +10,7 @@ return array(
'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
'Zotlabs\\' => array($baseDir . '/Zotlabs'),
'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'SimplePie\\' => array($vendorDir . '/simplepie/simplepie/src'),
'Sabre\\Xml\\' => array($vendorDir . '/sabre/xml/lib'),
'Sabre\\VObject\\' => array($vendorDir . '/sabre/vobject/lib'),
'Sabre\\Uri\\' => array($vendorDir . '/sabre/uri/lib'),

View File

@@ -23,42 +23,19 @@ class ComposerAutoloaderInit7b34d7e50a62201ec5d5e526a5b8b35d
}
spl_autoload_register(array('ComposerAutoloaderInit7b34d7e50a62201ec5d5e526a5b8b35d', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit7b34d7e50a62201ec5d5e526a5b8b35d', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';
$includePaths[] = get_include_path();
set_include_path(implode(PATH_SEPARATOR, $includePaths));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d::getInitializer($loader));
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
$includeFiles = \Composer\Autoload\ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire7b34d7e50a62201ec5d5e526a5b8b35d($fileIdentifier, $file);
}

View File

@@ -15,8 +15,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php',
'23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
@@ -38,8 +36,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'S' =>
array (
'Symfony\\Polyfill\\Php81\\' => 23,
'Symfony\\Polyfill\\Php80\\' => 23,
'Symfony\\Polyfill\\Ctype\\' => 23,
'SimplePie\\' => 10,
'Sabre\\Xml\\' => 10,
'Sabre\\VObject\\' => 14,
'Sabre\\Uri\\' => 10,
@@ -103,13 +100,9 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
),
'Symfony\\Polyfill\\Php80\\' =>
'SimplePie\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
),
'Symfony\\Polyfill\\Ctype\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
0 => __DIR__ . '/..' . '/simplepie/simplepie/src',
),
'Sabre\\Xml\\' =>
array (
@@ -224,7 +217,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
);
public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Brick\\Math\\BigDecimal' => __DIR__ . '/..' . '/brick/math/src/BigDecimal.php',
'Brick\\Math\\BigInteger' => __DIR__ . '/..' . '/brick/math/src/BigInteger.php',
'Brick\\Math\\BigNumber' => __DIR__ . '/..' . '/brick/math/src/BigNumber.php',
@@ -1091,6 +1083,39 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Sabre\\Xml\\XmlDeserializable' => __DIR__ . '/..' . '/sabre/xml/lib/XmlDeserializable.php',
'Sabre\\Xml\\XmlSerializable' => __DIR__ . '/..' . '/sabre/xml/lib/XmlSerializable.php',
'SimplePie' => __DIR__ . '/..' . '/simplepie/simplepie/library/SimplePie.php',
'SimplePie\\Author' => __DIR__ . '/..' . '/simplepie/simplepie/src/Author.php',
'SimplePie\\Cache' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache.php',
'SimplePie\\Cache\\Base' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/Base.php',
'SimplePie\\Cache\\DB' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/DB.php',
'SimplePie\\Cache\\File' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/File.php',
'SimplePie\\Cache\\Memcache' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/Memcache.php',
'SimplePie\\Cache\\Memcached' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/Memcached.php',
'SimplePie\\Cache\\MySQL' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/MySQL.php',
'SimplePie\\Cache\\Redis' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache/Redis.php',
'SimplePie\\Caption' => __DIR__ . '/..' . '/simplepie/simplepie/src/Caption.php',
'SimplePie\\Category' => __DIR__ . '/..' . '/simplepie/simplepie/src/Category.php',
'SimplePie\\Content\\Type\\Sniffer' => __DIR__ . '/..' . '/simplepie/simplepie/src/Content/Type/Sniffer.php',
'SimplePie\\Copyright' => __DIR__ . '/..' . '/simplepie/simplepie/src/Copyright.php',
'SimplePie\\Credit' => __DIR__ . '/..' . '/simplepie/simplepie/src/Credit.php',
'SimplePie\\Enclosure' => __DIR__ . '/..' . '/simplepie/simplepie/src/Enclosure.php',
'SimplePie\\Exception' => __DIR__ . '/..' . '/simplepie/simplepie/src/Exception.php',
'SimplePie\\File' => __DIR__ . '/..' . '/simplepie/simplepie/src/File.php',
'SimplePie\\Gzdecode' => __DIR__ . '/..' . '/simplepie/simplepie/src/Gzdecode.php',
'SimplePie\\HTTP\\Parser' => __DIR__ . '/..' . '/simplepie/simplepie/src/HTTP/Parser.php',
'SimplePie\\IRI' => __DIR__ . '/..' . '/simplepie/simplepie/src/IRI.php',
'SimplePie\\Item' => __DIR__ . '/..' . '/simplepie/simplepie/src/Item.php',
'SimplePie\\Locator' => __DIR__ . '/..' . '/simplepie/simplepie/src/Locator.php',
'SimplePie\\Misc' => __DIR__ . '/..' . '/simplepie/simplepie/src/Misc.php',
'SimplePie\\Net\\IPv6' => __DIR__ . '/..' . '/simplepie/simplepie/src/Net/IPv6.php',
'SimplePie\\Parse\\Date' => __DIR__ . '/..' . '/simplepie/simplepie/src/Parse/Date.php',
'SimplePie\\Parser' => __DIR__ . '/..' . '/simplepie/simplepie/src/Parser.php',
'SimplePie\\Rating' => __DIR__ . '/..' . '/simplepie/simplepie/src/Rating.php',
'SimplePie\\Registry' => __DIR__ . '/..' . '/simplepie/simplepie/src/Registry.php',
'SimplePie\\Restriction' => __DIR__ . '/..' . '/simplepie/simplepie/src/Restriction.php',
'SimplePie\\Sanitize' => __DIR__ . '/..' . '/simplepie/simplepie/src/Sanitize.php',
'SimplePie\\SimplePie' => __DIR__ . '/..' . '/simplepie/simplepie/src/SimplePie.php',
'SimplePie\\Source' => __DIR__ . '/..' . '/simplepie/simplepie/src/Source.php',
'SimplePie\\XML\\Declaration\\Parser' => __DIR__ . '/..' . '/simplepie/simplepie/src/XML/Declaration/Parser.php',
'SimplePie_Author' => __DIR__ . '/..' . '/simplepie/simplepie/library/SimplePie/Author.php',
'SimplePie_Cache' => __DIR__ . '/..' . '/simplepie/simplepie/library/SimplePie/Cache.php',
'SimplePie_Cache_Base' => __DIR__ . '/..' . '/simplepie/simplepie/library/SimplePie/Cache/Base.php',
@@ -1292,9 +1317,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Smarty_Template_Source' => __DIR__ . '/..' . '/smarty/smarty/libs/sysplugins/smarty_template_source.php',
'Smarty_Undefined_Variable' => __DIR__ . '/..' . '/smarty/smarty/libs/sysplugins/smarty_undefined_variable.php',
'Smarty_Variable' => __DIR__ . '/..' . '/smarty/smarty/libs/sysplugins/smarty_variable.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php',
'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php',
'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php',
'TPC_yyStackEntry' => __DIR__ . '/..' . '/smarty/smarty/libs/sysplugins/smarty_internal_configfileparser.php',
'TP_yyStackEntry' => __DIR__ . '/..' . '/smarty/smarty/libs/sysplugins/smarty_internal_templateparser.php',
@@ -1303,9 +1325,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Text_LanguageDetect_ISO639' => __DIR__ . '/..' . '/pear/text_languagedetect/Text/LanguageDetect/ISO639.php',
'Text_LanguageDetect_Parser' => __DIR__ . '/..' . '/pear/text_languagedetect/Text/LanguageDetect/Parser.php',
'URLify' => __DIR__ . '/..' . '/jbroadway/urlify/URLify.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'UploadHandler' => __DIR__ . '/..' . '/blueimp/jquery-file-upload/server/php/UploadHandler.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'Zotlabs\\Access\\AccessList' => __DIR__ . '/../..' . '/Zotlabs/Access/AccessList.php',
'Zotlabs\\Access\\PermissionLimits' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionLimits.php',
'Zotlabs\\Access\\PermissionRoles' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionRoles.php',
@@ -1375,8 +1395,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Lib\\Libzotdir' => __DIR__ . '/../..' . '/Zotlabs/Lib/Libzotdir.php',
'Zotlabs\\Lib\\MarkdownSoap' => __DIR__ . '/../..' . '/Zotlabs/Lib/MarkdownSoap.php',
'Zotlabs\\Lib\\MessageFilter' => __DIR__ . '/../..' . '/Zotlabs/Lib/MessageFilter.php',
'Zotlabs\\Lib\\NativeWiki' => __DIR__ . '/../..' . '/Zotlabs/Lib/NativeWiki.php',
'Zotlabs\\Lib\\NativeWikiPage' => __DIR__ . '/../..' . '/Zotlabs/Lib/NativeWikiPage.php',
'Zotlabs\\Lib\\PConfig' => __DIR__ . '/../..' . '/Zotlabs/Lib/PConfig.php',
'Zotlabs\\Lib\\Permcat' => __DIR__ . '/../..' . '/Zotlabs/Lib/Permcat.php',
'Zotlabs\\Lib\\PermissionDescription' => __DIR__ . '/../..' . '/Zotlabs/Lib/PermissionDescription.php',
@@ -1418,8 +1436,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Module\\Apporder' => __DIR__ . '/../..' . '/Zotlabs/Module/Apporder.php',
'Zotlabs\\Module\\Apps' => __DIR__ . '/../..' . '/Zotlabs/Module/Apps.php',
'Zotlabs\\Module\\Apschema' => __DIR__ . '/../..' . '/Zotlabs/Module/Apschema.php',
'Zotlabs\\Module\\Article_edit' => __DIR__ . '/../..' . '/Zotlabs/Module/Article_edit.php',
'Zotlabs\\Module\\Articles' => __DIR__ . '/../..' . '/Zotlabs/Module/Articles.php',
'Zotlabs\\Module\\Attach' => __DIR__ . '/../..' . '/Zotlabs/Module/Attach.php',
'Zotlabs\\Module\\Attach_edit' => __DIR__ . '/../..' . '/Zotlabs/Module/Attach_edit.php',
'Zotlabs\\Module\\Authorize' => __DIR__ . '/../..' . '/Zotlabs/Module/Authorize.php',
@@ -1429,8 +1445,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Module\\Bookmarks' => __DIR__ . '/../..' . '/Zotlabs/Module/Bookmarks.php',
'Zotlabs\\Module\\Branchtopic' => __DIR__ . '/../..' . '/Zotlabs/Module/Branchtopic.php',
'Zotlabs\\Module\\Cal' => __DIR__ . '/../..' . '/Zotlabs/Module/Cal.php',
'Zotlabs\\Module\\Card_edit' => __DIR__ . '/../..' . '/Zotlabs/Module/Card_edit.php',
'Zotlabs\\Module\\Cards' => __DIR__ . '/../..' . '/Zotlabs/Module/Cards.php',
'Zotlabs\\Module\\Cdav' => __DIR__ . '/../..' . '/Zotlabs/Module/Cdav.php',
'Zotlabs\\Module\\Changeaddr' => __DIR__ . '/../..' . '/Zotlabs/Module/Changeaddr.php',
'Zotlabs\\Module\\Channel' => __DIR__ . '/../..' . '/Zotlabs/Module/Channel.php',
@@ -1609,7 +1623,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Module\\Webpages' => __DIR__ . '/../..' . '/Zotlabs/Module/Webpages.php',
'Zotlabs\\Module\\Well_known' => __DIR__ . '/../..' . '/Zotlabs/Module/Well_known.php',
'Zotlabs\\Module\\Wfinger' => __DIR__ . '/../..' . '/Zotlabs/Module/Wfinger.php',
'Zotlabs\\Module\\Wiki' => __DIR__ . '/../..' . '/Zotlabs/Module/Wiki.php',
'Zotlabs\\Module\\Xchan' => __DIR__ . '/../..' . '/Zotlabs/Module/Xchan.php',
'Zotlabs\\Module\\Xpoco' => __DIR__ . '/../..' . '/Zotlabs/Module/Xpoco.php',
'Zotlabs\\Module\\Xrd' => __DIR__ . '/../..' . '/Zotlabs/Module/Xrd.php',
@@ -1893,6 +1906,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Update\\_1250' => __DIR__ . '/../..' . '/Zotlabs/Update/_1250.php',
'Zotlabs\\Update\\_1251' => __DIR__ . '/../..' . '/Zotlabs/Update/_1251.php',
'Zotlabs\\Update\\_1252' => __DIR__ . '/../..' . '/Zotlabs/Update/_1252.php',
'Zotlabs\\Update\\_1253' => __DIR__ . '/../..' . '/Zotlabs/Update/_1253.php',
'Zotlabs\\Web\\Controller' => __DIR__ . '/../..' . '/Zotlabs/Web/Controller.php',
'Zotlabs\\Web\\HTTPHeaders' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPHeaders.php',
'Zotlabs\\Web\\HTTPSig' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPSig.php',
@@ -1961,9 +1975,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Widget\\Tokens' => __DIR__ . '/../..' . '/Zotlabs/Widget/Tokens.php',
'Zotlabs\\Widget\\Vcard' => __DIR__ . '/../..' . '/Zotlabs/Widget/Vcard.php',
'Zotlabs\\Widget\\Website_portation_tools' => __DIR__ . '/../..' . '/Zotlabs/Widget/Website_portation_tools.php',
'Zotlabs\\Widget\\Wiki_list' => __DIR__ . '/../..' . '/Zotlabs/Widget/Wiki_list.php',
'Zotlabs\\Widget\\Wiki_page_history' => __DIR__ . '/../..' . '/Zotlabs/Widget/Wiki_page_history.php',
'Zotlabs\\Widget\\Wiki_pages' => __DIR__ . '/../..' . '/Zotlabs/Widget/Wiki_pages.php',
'Zotlabs\\Widget\\Zcard' => __DIR__ . '/../..' . '/Zotlabs/Widget/Zcard.php',
'Zotlabs\\Zot6\\IHandler' => __DIR__ . '/../..' . '/Zotlabs/Zot6/IHandler.php',
'Zotlabs\\Zot6\\Receiver' => __DIR__ . '/../..' . '/Zotlabs/Zot6/Receiver.php',

View File

@@ -2,7 +2,7 @@
// include_paths.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@@ -133,29 +133,30 @@
},
{
"name": "bshaffer/oauth2-server-php",
"version": "v1.11.1",
"version_normalized": "1.11.1.0",
"version": "v1.12.0",
"version_normalized": "1.12.0.0",
"source": {
"type": "git",
"url": "https://github.com/bshaffer/oauth2-server-php.git",
"reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa"
"reference": "60254fc7fbb08ce56164faae9e075068adf914ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/5a0c8000d4763b276919e2106f54eddda6bc50fa",
"reference": "5a0c8000d4763b276919e2106f54eddda6bc50fa",
"url": "https://api.github.com/repos/bshaffer/oauth2-server-php/zipball/60254fc7fbb08ce56164faae9e075068adf914ef",
"reference": "60254fc7fbb08ce56164faae9e075068adf914ef",
"shasum": ""
},
"require": {
"php": ">=5.3.9"
"php": ">=7.1"
},
"require-dev": {
"aws/aws-sdk-php": "~2.8",
"firebase/php-jwt": "~2.2",
"aws/aws-sdk-php": "^2.8",
"firebase/php-jwt": "^2.2",
"mongodb/mongodb": "^1.1",
"phpunit/phpunit": "^4.0",
"predis/predis": "dev-master",
"thobbs/phpcassa": "dev-master"
"phpunit/phpunit": "^7.5||^8.0",
"predis/predis": "^1.1",
"thobbs/phpcassa": "dev-master",
"yoast/phpunit-polyfills": "^1.0"
},
"suggest": {
"aws/aws-sdk-php": "~2.8 is required to use DynamoDB storage",
@@ -164,7 +165,7 @@
"predis/predis": "Required to use Redis storage",
"thobbs/phpcassa": "Required to use Cassandra storage"
},
"time": "2018-12-04T00:29:32+00:00",
"time": "2022-04-19T17:09:11+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -190,6 +191,10 @@
"oauth",
"oauth2"
],
"support": {
"issues": "https://github.com/bshaffer/oauth2-server-php/issues",
"source": "https://github.com/bshaffer/oauth2-server-php/tree/v1.12.0"
},
"install-path": "../bshaffer/oauth2-server-php"
},
{
@@ -653,17 +658,17 @@
},
{
"name": "phpseclib/phpseclib",
"version": "2.0.36",
"version_normalized": "2.0.36.0",
"version": "2.0.37",
"version_normalized": "2.0.37.0",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "a97547126396548c224703a267a30af1592be146"
"reference": "c812fbb4d6b4d7f30235ab7298a12f09ba13b37c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/a97547126396548c224703a267a30af1592be146",
"reference": "a97547126396548c224703a267a30af1592be146",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c812fbb4d6b4d7f30235ab7298a12f09ba13b37c",
"reference": "c812fbb4d6b4d7f30235ab7298a12f09ba13b37c",
"shasum": ""
},
"require": {
@@ -680,7 +685,7 @@
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
},
"time": "2022-01-30T08:48:36+00:00",
"time": "2022-04-04T04:57:45+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -745,7 +750,7 @@
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
"source": "https://github.com/phpseclib/phpseclib/tree/2.0.36"
"source": "https://github.com/phpseclib/phpseclib/tree/2.0.37"
},
"funding": [
{
@@ -900,26 +905,25 @@
},
{
"name": "ramsey/uuid",
"version": "4.2.3",
"version_normalized": "4.2.3.0",
"version": "4.3.1",
"version_normalized": "4.3.1.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
"reference": "8505afd4fea63b81a85d3b7b53ac3cb8dc347c28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/8505afd4fea63b81a85d3b7b53ac3cb8dc347c28",
"reference": "8505afd4fea63b81a85d3b7b53ac3cb8dc347c28",
"shasum": ""
},
"require": {
"brick/math": "^0.8 || ^0.9",
"ext-ctype": "*",
"ext-json": "*",
"php": "^7.2 || ^8.0",
"ramsey/collection": "^1.0",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php80": "^1.14"
"php": "^8.0",
"ramsey/collection": "^1.0"
},
"replace": {
"rhumsaa/uuid": "self.version"
@@ -954,24 +958,21 @@
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
"time": "2021-09-25T23:10:38+00:00",
"time": "2022-03-27T21:42:02+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "4.x-dev"
},
"captainhook": {
"force-install": true
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Ramsey\\Uuid\\": "src/"
},
"files": [
"src/functions.php"
]
],
"psr-4": {
"Ramsey\\Uuid\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -985,7 +986,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.2.3"
"source": "https://github.com/ramsey/uuid/tree/4.3.1"
},
"funding": [
{
@@ -1464,17 +1465,17 @@
},
{
"name": "simplepie/simplepie",
"version": "1.5.8",
"version_normalized": "1.5.8.0",
"version": "1.6.0",
"version_normalized": "1.6.0.0",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "d1d80f37264c9f1ed7fa3434eca14d179cb689b1"
"reference": "2bdbc51ed1010941c9c5f2cddca433e79665bfe1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/d1d80f37264c9f1ed7fa3434eca14d179cb689b1",
"reference": "d1d80f37264c9f1ed7fa3434eca14d179cb689b1",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/2bdbc51ed1010941c9c5f2cddca433e79665bfe1",
"reference": "2bdbc51ed1010941c9c5f2cddca433e79665bfe1",
"shasum": ""
},
"require": {
@@ -1493,14 +1494,22 @@
"ext-mbstring": "",
"mf2/mf2": "Microformat module that allows for parsing HTML for microformats"
},
"time": "2021-12-24T02:53:50+00:00",
"time": "2022-04-21T11:05:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"SimplePie\\": "src"
},
"psr-0": {
"SimplePie": "library"
}
},
"autoload-dev": {
"psr-4": {
"SimplePie\\Tests\\Unit\\": "tests/Unit"
}
},
"scripts": {
"test": [
"phpunit"
@@ -1535,24 +1544,24 @@
"rss"
],
"support": {
"source": "https://github.com/simplepie/simplepie/tree/1.5.8",
"source": "https://github.com/simplepie/simplepie/tree/1.6.0",
"issues": "https://github.com/simplepie/simplepie/issues"
},
"install-path": "../simplepie/simplepie"
},
{
"name": "smarty/smarty",
"version": "v4.1.0",
"version_normalized": "4.1.0.0",
"version": "v4.1.1",
"version_normalized": "4.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/smarty-php/smarty.git",
"reference": "9e0536de18b53ba193364291ef0303b0ab9903e1"
"reference": "71036be8be02bf93735c47b0b745f722efbc729f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/9e0536de18b53ba193364291ef0303b0ab9903e1",
"reference": "9e0536de18b53ba193364291ef0303b0ab9903e1",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/71036be8be02bf93735c47b0b745f722efbc729f",
"reference": "71036be8be02bf93735c47b0b745f722efbc729f",
"shasum": ""
},
"require": {
@@ -1562,7 +1571,7 @@
"phpunit/phpunit": "^8.5 || ^7.5",
"smarty/smarty-lexer": "^3.1"
},
"time": "2022-02-06T20:34:27+00:00",
"time": "2022-05-17T12:56:28+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -1605,185 +1614,14 @@
"support": {
"forum": "https://github.com/smarty-php/smarty/discussions",
"issues": "https://github.com/smarty-php/smarty/issues",
"source": "https://github.com/smarty-php/smarty/tree/v4.1.0"
"source": "https://github.com/smarty-php/smarty/tree/v4.1.1"
},
"install-path": "../smarty/smarty"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"time": "2021-10-20T20:35:02+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/polyfill-ctype"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9",
"reference": "57b712b08eddb97c762a8caa32c84e037892d2e9",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2021-09-13T13:58:33+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.24.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/polyfill-php80"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.24.0",
"version_normalized": "1.24.0.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
@@ -1844,7 +1682,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.24.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0"
},
"funding": [
{

View File

@@ -5,7 +5,7 @@
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '6930c4e23b8b24f7436c0e265d751460bed9b1d2',
'reference' => '8ba47450970bab036664f03a558917c13d8c1574',
'name' => 'zotlabs/hubzilla',
'dev' => false,
),
@@ -29,12 +29,12 @@
'dev_requirement' => false,
),
'bshaffer/oauth2-server-php' => array(
'pretty_version' => 'v1.11.1',
'version' => '1.11.1.0',
'pretty_version' => 'v1.12.0',
'version' => '1.12.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../bshaffer/oauth2-server-php',
'aliases' => array(),
'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
'reference' => '60254fc7fbb08ce56164faae9e075068adf914ef',
'dev_requirement' => false,
),
'commerceguys/intl' => array(
@@ -110,12 +110,12 @@
'dev_requirement' => false,
),
'phpseclib/phpseclib' => array(
'pretty_version' => '2.0.36',
'version' => '2.0.36.0',
'pretty_version' => '2.0.37',
'version' => '2.0.37.0',
'type' => 'library',
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
'aliases' => array(),
'reference' => 'a97547126396548c224703a267a30af1592be146',
'reference' => 'c812fbb4d6b4d7f30235ab7298a12f09ba13b37c',
'dev_requirement' => false,
),
'psr/log' => array(
@@ -137,18 +137,18 @@
'dev_requirement' => false,
),
'ramsey/uuid' => array(
'pretty_version' => '4.2.3',
'version' => '4.2.3.0',
'pretty_version' => '4.3.1',
'version' => '4.3.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../ramsey/uuid',
'aliases' => array(),
'reference' => 'fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
'reference' => '8505afd4fea63b81a85d3b7b53ac3cb8dc347c28',
'dev_requirement' => false,
),
'rhumsaa/uuid' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '4.2.3',
0 => '4.3.1',
),
),
'sabre/dav' => array(
@@ -206,44 +206,26 @@
'dev_requirement' => false,
),
'simplepie/simplepie' => array(
'pretty_version' => '1.5.8',
'version' => '1.5.8.0',
'pretty_version' => '1.6.0',
'version' => '1.6.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../simplepie/simplepie',
'aliases' => array(),
'reference' => 'd1d80f37264c9f1ed7fa3434eca14d179cb689b1',
'reference' => '2bdbc51ed1010941c9c5f2cddca433e79665bfe1',
'dev_requirement' => false,
),
'smarty/smarty' => array(
'pretty_version' => 'v4.1.0',
'version' => '4.1.0.0',
'pretty_version' => 'v4.1.1',
'version' => '4.1.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../smarty/smarty',
'aliases' => array(),
'reference' => '9e0536de18b53ba193364291ef0303b0ab9903e1',
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'reference' => '30885182c981ab175d4d034db0f6f469898070ab',
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9',
'reference' => '71036be8be02bf93735c47b0b745f722efbc729f',
'dev_requirement' => false,
),
'symfony/polyfill-php81' => array(
'pretty_version' => 'v1.24.0',
'version' => '1.24.0.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php81',
'aliases' => array(),
@@ -289,7 +271,7 @@
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '6930c4e23b8b24f7436c0e265d751460bed9b1d2',
'reference' => '8ba47450970bab036664f03a558917c13d8c1574',
'dev_requirement' => false,
),
),

View File

@@ -5,6 +5,7 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
## Backers
- Allan Simon
- [ChargeOver](https://chargeover.com/)
- Raghu Veer Dendukuri
- Zane Hooper
- [Setasign](https://www.setasign.com/)

View File

@@ -68,9 +68,10 @@ Need Support?
## Special Thanks
Special Thanks to our Patreon sponsors!:
Special Thanks to our $50+ sponsors!:
- Allan Simon
- [ChargeOver](https://chargeover.com/)
## Contributing

View File

@@ -156,7 +156,7 @@ abstract class Base
* @var string
* @access private
*/
var $iv;
var $iv = '';
/**
* A "sliding" Initialization Vector
@@ -779,6 +779,7 @@ abstract class Base
}
return $ciphertext;
case self::MODE_OFB8:
// OpenSSL has built in support for cfb8 but not ofb8
$ciphertext = '';
$len = strlen($plaintext);
$iv = $this->encryptIV;
@@ -795,8 +796,6 @@ abstract class Base
break;
case self::MODE_OFB:
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
case self::MODE_OFB8:
// OpenSSL has built in support for cfb8 but not ofb8
}
}
@@ -918,8 +917,8 @@ abstract class Base
$block = substr($plaintext, $i, $block_size);
if (strlen($block) > strlen($buffer['ciphertext'])) {
$buffer['ciphertext'].= $this->_encryptBlock($xor);
$this->_increment_str($xor);
}
$this->_increment_str($xor);
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
$ciphertext.= $block ^ $key;
}
@@ -2079,6 +2078,13 @@ abstract class Base
*/
function _increment_str(&$var)
{
if (function_exists('sodium_increment')) {
$var = strrev($var);
sodium_increment($var);
$var = strrev($var);
return;
}
for ($i = 4; $i <= strlen($var); $i+= 4) {
$temp = substr($var, -$i, 4);
switch ($temp) {

View File

@@ -1405,11 +1405,18 @@ class RSA
unset($xml);
return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false;
// from PuTTY's SSHPUBK.C
// see PuTTY's SSHPUBK.C and https://tartarus.org/~simon/putty-snapshots/htmldoc/AppendixC.html
case self::PRIVATE_FORMAT_PUTTY:
$components = array();
$key = preg_split('#\r\n|\r|\n#', $key);
$type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
if ($this->_string_shift($key[0], strlen('PuTTY-User-Key-File-')) != 'PuTTY-User-Key-File-') {
return false;
}
$version = (int) $this->_string_shift($key[0], 3); // should be either "2: " or "3: 0" prior to int casting
if ($version != 2 && $version != 3) {
return false;
}
$type = rtrim($key[0]);
if ($type != 'ssh-rsa') {
return false;
}
@@ -1424,23 +1431,55 @@ class RSA
extract(unpack('Nlength', $this->_string_shift($public, 4)));
$components['modulus'] = new BigInteger($this->_string_shift($public, $length), -256);
$privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4]));
$private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
$offset = $publicLength + 4;
switch ($encryption) {
case 'aes256-cbc':
$symkey = '';
$sequence = 0;
while (strlen($symkey) < 32) {
$temp = pack('Na*', $sequence++, $this->password);
$symkey.= pack('H*', sha1($temp));
}
$symkey = substr($symkey, 0, 32);
$crypto = new AES();
switch ($version) {
case 3:
if (!function_exists('sodium_crypto_pwhash')) {
return false;
}
$flavour = trim(preg_replace('#Key-Derivation: (.*)#', '$1', $key[$offset++]));
switch ($flavour) {
case 'Argon2i':
$flavour = SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13;
break;
case 'Argon2id':
$flavour = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13;
break;
default:
return false;
}
$memory = trim(preg_replace('#Argon2-Memory: (\d+)#', '$1', $key[$offset++]));
$passes = trim(preg_replace('#Argon2-Passes: (\d+)#', '$1', $key[$offset++]));
$parallelism = trim(preg_replace('#Argon2-Parallelism: (\d+)#', '$1', $key[$offset++]));
$salt = pack('H*', trim(preg_replace('#Argon2-Salt: ([0-9a-f]+)#', '$1', $key[$offset++])));
$length = 80; // keylen + ivlen + mac_keylen
$temp = sodium_crypto_pwhash($length, $this->password, $salt, $passes, $memory << 10, $flavour);
$symkey = substr($temp, 0, 32);
$symiv = substr($temp, 32, 16);
break;
case 2:
$symkey = '';
$sequence = 0;
while (strlen($symkey) < 32) {
$temp = pack('Na*', $sequence++, $this->password);
$symkey.= pack('H*', sha1($temp));
}
$symkey = substr($symkey, 0, 32);
$symiv = str_repeat("\0", 16);
}
}
$privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$offset++]));
$private = base64_decode(implode('', array_map('trim', array_slice($key, $offset, $privateLength))));
if ($encryption != 'none') {
$crypto->setKey($symkey);
$crypto->setIV($symiv);
$crypto->disablePadding();
$private = $crypto->decrypt($private);
if ($private === false) {

View File

@@ -234,11 +234,10 @@ class Agent
* Signal that agent forwarding should
* be requested when a channel is opened
*
* @param Net_SSH2 $ssh
* @return bool
* @access public
*/
function startSSHForwarding($ssh)
function startSSHForwarding()
{
if ($this->forward_status == self::FORWARD_NONE) {
$this->forward_status = self::FORWARD_REQUEST;

View File

@@ -1,4 +1,4 @@
Copyright (c) 2012-2021 Ben Ramsey <ben@benramsey.com>
Copyright (c) 2012-2022 Ben Ramsey <ben@benramsey.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,23 +1,19 @@
{
"name": "ramsey/uuid",
"type": "library",
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
"license": "MIT",
"type": "library",
"keywords": [
"uuid",
"identifier",
"guid"
],
"license": "MIT",
"require": {
"php": "^7.2 || ^8.0",
"php": "^8.0",
"ext-ctype": "*",
"ext-json": "*",
"brick/math": "^0.8 || ^0.9",
"ramsey/collection": "^1.0",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php80": "^1.14"
},
"replace": {
"rhumsaa/uuid": "self.version"
"ramsey/collection": "^1.0"
},
"require-dev": {
"captainhook/captainhook": "^5.10",
@@ -41,6 +37,9 @@
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.9"
},
"replace": {
"rhumsaa/uuid": "self.version"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
@@ -49,17 +48,8 @@
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-main": "4.x-dev"
},
"captainhook": {
"force-install": true
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Ramsey\\Uuid\\": "src/"
@@ -75,8 +65,20 @@
"Ramsey\\Uuid\\Test\\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"allow-plugins": {
"captainhook/plugin-composer": true,
"ergebnis/composer-normalize": true,
"phpstan/extension-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
},
"sort-packages": true
},
"extra": {
"captainhook": {
"force-install": true
}
},
"scripts": {
"analyze": [
"@phpstan",

View File

@@ -27,6 +27,11 @@ use Traversable;
/**
* A collection of UuidBuilderInterface objects
*
* @deprecated this class has been deprecated, and will be removed in 5.0.0. The use-case for this class comes from
* a pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced
* at runtime: that is no longer necessary, now that you can safely verify your code to be correct, and use
* more generic types like `iterable<T>` instead.
*
* @extends AbstractCollection<UuidBuilderInterface>
*/
class BuilderCollection extends AbstractCollection

View File

@@ -28,14 +28,14 @@ use Ramsey\Uuid\UuidInterface;
class FallbackBuilder implements UuidBuilderInterface
{
/**
* @var BuilderCollection
* @var iterable<UuidBuilderInterface>
*/
private $builders;
/**
* @param BuilderCollection $builders An array of UUID builders
* @param iterable<UuidBuilderInterface> $builders An array of UUID builders
*/
public function __construct(BuilderCollection $builders)
public function __construct(iterable $builders)
{
$this->builders = $builders;
}

View File

@@ -14,7 +14,6 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
use Ramsey\Uuid\Builder\BuilderCollection;
use Ramsey\Uuid\Builder\FallbackBuilder;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
@@ -43,7 +42,6 @@ use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
use Ramsey\Uuid\Provider\Dce\SystemDceSecurityProvider;
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
use Ramsey\Uuid\Provider\Node\NodeProviderCollection;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
use Ramsey\Uuid\Provider\NodeProviderInterface;
@@ -350,10 +348,10 @@ class FeatureSet
return new RandomNodeProvider();
}
return new FallbackNodeProvider(new NodeProviderCollection([
return new FallbackNodeProvider([
new SystemNodeProvider(),
new RandomNodeProvider(),
]));
]);
}
/**
@@ -432,11 +430,10 @@ class FeatureSet
return new GuidBuilder($this->numberConverter, $this->timeConverter);
}
/** @psalm-suppress ImpureArgument */
return new FallbackBuilder(new BuilderCollection([
return new FallbackBuilder([
new Rfc4122UuidBuilder($this->numberConverter, $this->timeConverter),
new NonstandardUuidBuilder($this->numberConverter, $this->timeConverter),
]));
]);
}
/**

View File

@@ -87,7 +87,7 @@ class CombGenerator implements RandomGeneratorInterface
*/
public function generate(int $length): string
{
if ($length < self::TIMESTAMP_BYTES || $length < 0) {
if ($length < self::TIMESTAMP_BYTES) {
throw new InvalidArgumentException(
'Length must be a positive integer greater than or equal to ' . self::TIMESTAMP_BYTES
);

View File

@@ -21,6 +21,10 @@ use RandomLib\Generator;
* RandomLibAdapter generates strings of random binary data using the
* paragonie/random-lib library
*
* @deprecated This class will be removed in 5.0.0. Use the default
* RandomBytesGenerator or implement your own generator that implements
* RandomGeneratorInterface.
*
* @link https://packagist.org/packages/paragonie/random-lib paragonie/random-lib
*/
class RandomLibAdapter implements RandomGeneratorInterface

View File

@@ -229,6 +229,6 @@ class SystemDceSecurityProvider implements DceSecurityProviderInterface
return '';
}
return trim((string) substr($sid, $lastHyphen + 1));
return trim(substr($sid, $lastHyphen + 1));
}
}

View File

@@ -25,14 +25,14 @@ use Ramsey\Uuid\Type\Hexadecimal;
class FallbackNodeProvider implements NodeProviderInterface
{
/**
* @var NodeProviderCollection
* @var iterable<NodeProviderInterface>
*/
private $nodeProviders;
/**
* @param NodeProviderCollection $providers Array of node providers
* @param iterable<NodeProviderInterface> $providers Array of node providers
*/
public function __construct(NodeProviderCollection $providers)
public function __construct(iterable $providers)
{
$this->nodeProviders = $providers;
}

View File

@@ -21,6 +21,11 @@ use Ramsey\Uuid\Type\Hexadecimal;
/**
* A collection of NodeProviderInterface objects
*
* @deprecated this class has been deprecated, and will be removed in 5.0.0. The use-case for this class comes from
* a pre-`phpstan/phpstan` and pre-`vimeo/psalm` ecosystem, in which type safety had to be mostly enforced
* at runtime: that is no longer necessary, now that you can safely verify your code to be correct, and use
* more generic types like `iterable<T>` instead.
*
* @extends AbstractCollection<NodeProviderInterface>
*/
class NodeProviderCollection extends AbstractCollection

View File

@@ -476,10 +476,11 @@ class Uuid implements UuidInterface
*/
public static function fromString(string $uuid): UuidInterface
{
$uuid = strtolower($uuid);
if (! self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) {
assert($uuid !== '');
return new LazyUuidFromString(strtolower($uuid));
return new LazyUuidFromString($uuid);
}
return self::getFactory()->fromString($uuid);

View File

@@ -0,0 +1,20 @@
# https://EditorConfig.org
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{css,html,js,json,php,sql}]
indent_style = tab
[*.{markdown,md}]
indent_size = 4
indent_style = space
max_line_length = off
trim_trailing_whitespace = false
[*.{yaml,yml}]
indent_size = 2
indent_style = space

View File

@@ -5,7 +5,37 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://github.com/simplepie/simplepie/compare/1.5.7...master)
## [Unreleased](https://github.com/simplepie/simplepie/compare/1.6.0...master)
## [1.6.0](https://github.com/simplepie/simplepie/compare/1.5.8...1.6.0) - 2022-04-21
### Added
- New methods `SimplePie::rename_attributes()` and `SimplePie_Sanitize::rename_attributes()` allow renaming attributes by @math-GH in [#717](https://github.com/simplepie/simplepie/pull/717)
- Add audio, video @src elements/attribute for URL resolution by @rdalverny in [#716](https://github.com/simplepie/simplepie/pull/716)
- Added new namespaced aliases and PSR-4 support for every class by @Art4 in [#711](https://github.com/simplepie/simplepie/pull/711)
- Add .editorconfig by @Alkarex in [#724](https://github.com/simplepie/simplepie/pull/724)
- Upload compiled file as release asset by @Art4 in [#725](https://github.com/simplepie/simplepie/pull/725)
### Changed
- GH Actions: version update for ramsey/composer-install by @jrfnl in [#713](https://github.com/simplepie/simplepie/pull/713)
### Fixed
- Bugfix in MySQL cache by @Art4 in [#720](https://github.com/simplepie/simplepie/pull/720)
- Re-enable xml:base for all supported RSS formats by @Alkarex in [#723](https://github.com/simplepie/simplepie/pull/723)
## [1.5.8](https://github.com/simplepie/simplepie/compare/1.5.7...1.5.8) - 2021-12-24
### Changed
- Update CHANGELOG.md, follow keepachangelog format by @Art4 in [#709](https://github.com/simplepie/simplepie/pull/709)
### Fixed
- Fix a small typo in the error() function Docblock by @audrasjb in [#712](https://github.com/simplepie/simplepie/pull/712)
- Fix/708 version bump for constant `SIMPLEPIE_VERSION` for 1.5.8 release by @faisal-alvi in [#710](https://github.com/simplepie/simplepie/pull/710)
## [1.5.7](https://github.com/simplepie/simplepie/compare/1.5.6...1.5.7) - 2021-12-19
@@ -41,7 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* PHP 7.4/8.0: curly brace array access deprecated & removed [#655](https://github.com/simplepie/simplepie/pull/655)
* PHP 8.0: required parameters are no longer allowed after optional parameters [#656](https://github.com/simplepie/simplepie/pull/656)
* Fix permanent_url for HTTP 301 [#660](https://github.com/simplepie/simplepie/pull/660)
* Fix typo in MIME type in Content_Type_Sniffer [#661](https://github.com/simplepie/simplepie/pull/661)
* Fix typo in MIME type in Content_Type_Sniffer [#661](https://github.com/simplepie/simplepie/pull/661)
## [1.5.5](https://github.com/simplepie/simplepie/compare/1.5.4...1.5.5) - 2020-05-01
@@ -118,13 +148,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Use the latest HHVM version in testing (3.15.2). [#480](https://github.com/simplepie/simplepie/pull/480)
* Added PHPUnit as a `dev-dependency` in Composer. [#463](https://github.com/simplepie/simplepie/pull/463)
* Added `mf2/mf2` as a suggestion in Composer for use with microformats. [#491](https://github.com/simplepie/simplepie/pull/491)
* Fixed misspelled occurrences of "separated". [#459](https://github.com/simplepie/simplepie/pull/459)
* Fixed misspelled occurrences of "separated". [#459](https://github.com/simplepie/simplepie/pull/459)
* Improvements to the compatibility test and error messages. [#488](https://github.com/simplepie/simplepie/pull/488)
## [1.4.2](https://github.com/simplepie/simplepie/compare/1.4.1...1.4.2) - 2016-06-14
* Fixed a bug with IRI parsing.
* More cleanly separates discovery of microformats and parsing when php-mf2 is not present.
* More cleanly separates discovery of microformats and parsing when php-mf2 is not present.
## [1.4.1](https://github.com/simplepie/simplepie/compare/1.4.0...1.4.1) - 2016-06-02
@@ -147,7 +177,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added support for `application/x-rss+xml` in `SimplePie_Locator`. [#348](https://github.com/simplepie/simplepie/pull/348)
* Added photo de-duping in microformats. [#348](https://github.com/simplepie/simplepie/pull/348)
* Added decoding for special characters in MAYBE_HTML. [#400](https://github.com/simplepie/simplepie/pull/400)
* Added `SimplePie_Exception` for internally reporting errors. Also, use this to show an error when trying to load the class instead of causing a failure. [#241](https://github.com/simplepie/simplepie/pull/241)
* Added `SimplePie_Exception` for internally reporting errors. Also, use this to show an error when trying to load the class instead of causing a failure. [#241](https://github.com/simplepie/simplepie/pull/241)
* Added sanitization of the `</html>` and `</body>` tags. [#348](https://github.com/simplepie/simplepie/pull/348)
* Added support for media thumbnails through `SimplePie_Item->get_thumbnail()`. [#348](https://github.com/simplepie/simplepie/pull/348)
* Added the `feed_url` to a returned error message. [#348](https://github.com/simplepie/simplepie/pull/348)
@@ -170,7 +200,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Fixed an error caused when trying to instantiate a `SimplePie_File` object with a bad URI. [#272](https://github.com/simplepie/simplepie/pull/272)
* Fixed a PHP notice that occurs when a date starts with `(`. [#348](https://github.com/simplepie/simplepie/pull/348)
* Fixed uninitialized string offeset PHP notices. [#353](https://github.com/simplepie/simplepie/pull/353)
* Fixed call to non-existent property in Memcache. [#311](https://github.com/simplepie/simplepie/pull/311)
* Fixed call to non-existent property in Memcache. [#311](https://github.com/simplepie/simplepie/pull/311)
* Fixed a bug where MySQL statements were not being passed thorugh `prepare()`. [#348](https://github.com/simplepie/simplepie/pull/348)
* Fixed an instance where an error message in `SimplePie` was not being triggered correctly. [#348](https://github.com/simplepie/simplepie/pull/348)
* Fixed a bug with Russian feeds. [#348](https://github.com/simplepie/simplepie/pull/348)

View File

@@ -38,8 +38,9 @@ What comes in the package?
Since SimplePie 1.3, we've split the classes into separate files to make it easier
to maintain and use.
If you'd like a single monolithic file, you can run `php build/compile.php` to
generate `SimplePie.compiled.php`.
If you'd like a single monolithic file, see the assets in the
[releases](https://github.com/simplepie/simplepie/releases), or you can
run `php build/compile.php` to generate `SimplePie.compiled.php` yourself.
To start the demo
-----------------

View File

@@ -40,10 +40,18 @@
"mf2/mf2": "Microformat module that allows for parsing HTML for microformats"
},
"autoload": {
"psr-4": {
"SimplePie\\": "src"
},
"psr-0": {
"SimplePie": "library"
}
},
"autoload-dev": {
"psr-4": {
"SimplePie\\Tests\\Unit\\": "tests/Unit"
}
},
"config": {
"bin-dir": "bin"
},

View File

@@ -33,7 +33,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
* @package SimplePie
* @version 1.5.8
* @version 1.6.0
* @copyright 2004-2017 Ryan Parman, Sam Sneddon, Ryan McCue
* @author Ryan Parman
* @author Sam Sneddon
@@ -50,7 +50,7 @@ define('SIMPLEPIE_NAME', 'SimplePie');
/**
* SimplePie Version
*/
define('SIMPLEPIE_VERSION', '1.5.8');
define('SIMPLEPIE_VERSION', '1.6.0');
/**
* SimplePie Build
@@ -650,6 +650,13 @@ class SimplePie
*/
public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
/**
* @var array Stores the default attributes to be renamed by rename_attributes().
* @see SimplePie::rename_attributes()
* @access private
*/
public $rename_attributes = array();
/**
* @var bool Should we throw exceptions, or use the old-style error property?
* @access private
@@ -1223,6 +1230,15 @@ class SimplePie
$this->sanitize->encode_instead_of_strip($enable);
}
public function rename_attributes($attribs = '')
{
if ($attribs === '')
{
$attribs = $this->rename_attributes;
}
$this->sanitize->rename_attributes($attribs);
}
public function strip_attributes($attribs = '')
{
if ($attribs === '')
@@ -2199,7 +2215,7 @@ class SimplePie
*/
public function get_base($element = array())
{
if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
if (!empty($element['xml_base_explicit']) && isset($element['xml_base']))
{
return $element['xml_base'];
}
@@ -3316,3 +3332,5 @@ class SimplePie
}
}
}
class_alias('SimplePie', 'SimplePie\SimplePie', false);

View File

@@ -147,3 +147,5 @@ class SimplePie_Author
return null;
}
}
class_alias('SimplePie_Author', 'SimplePie\Author', false);

View File

@@ -132,3 +132,5 @@ class SimplePie_Cache
return $params;
}
}
class_alias('SimplePie_Cache', 'SimplePie\Cache', false);

View File

@@ -111,3 +111,5 @@ interface SimplePie_Cache_Base
*/
public function unlink();
}
class_alias('SimplePie_Cache_Base', 'SimplePie\Cache\Base', false);

View File

@@ -134,3 +134,5 @@ abstract class SimplePie_Cache_DB implements SimplePie_Cache_Base
return array(serialize($data->data), $items_by_id);
}
}
class_alias('SimplePie_Cache_DB', 'SimplePie\Cache\DB', false);

View File

@@ -162,3 +162,5 @@ class SimplePie_Cache_File implements SimplePie_Cache_Base
return false;
}
}
class_alias('SimplePie_Cache_File', 'SimplePie\Cache\File', false);

View File

@@ -178,3 +178,5 @@ class SimplePie_Cache_Memcache implements SimplePie_Cache_Base
return $this->cache->delete($this->name, 0);
}
}
class_alias('SimplePie_Cache_Memcache', 'SimplePie\Cache\Memcache', false);

View File

@@ -164,3 +164,5 @@ class SimplePie_Cache_Memcached implements SimplePie_Cache_Base
return false;
}
}
class_alias('SimplePie_Cache_Memcached', 'SimplePie\Cache\Memcached', false);

View File

@@ -278,7 +278,7 @@ class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
$query->bindValue(':data', serialize($data));
$query->bindValue(':time', time());
$query->bindValue(':feed', $this->id);
if ($this->execute())
if ($query->execute())
{
return true;
}
@@ -438,3 +438,5 @@ class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
return $query->execute() && $query2->execute();
}
}
class_alias('SimplePie_Cache_MySQL', 'SimplePie\Cache\MySQL', false);

Some files were not shown because too many files have changed in this diff Show More