mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 09:01:15 -04:00
Compare commits
260 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eefdc6485 | ||
|
|
4d2bcbc583 | ||
|
|
299c4bda1b | ||
|
|
f4b9291d42 | ||
|
|
b7afc905ec | ||
|
|
01bd846433 | ||
|
|
08f717d4fc | ||
|
|
b9fd87b004 | ||
|
|
1615f2c79a | ||
|
|
f430db0de7 | ||
|
|
32eb603643 | ||
|
|
c3f387f22a | ||
|
|
8703caff5f | ||
|
|
c5d50c9e47 | ||
|
|
fed4e3e03a | ||
|
|
9d1f73e179 | ||
|
|
ba164d9488 | ||
|
|
3fe67eb646 | ||
|
|
12ba2c30b9 | ||
|
|
7c1b41019e | ||
|
|
707110e5a7 | ||
|
|
ba9a9cb016 | ||
|
|
c1c75c4b67 | ||
|
|
0446349b89 | ||
|
|
915cb44601 | ||
|
|
17a153fb6d | ||
|
|
e339e897ff | ||
|
|
6b57f163bd | ||
|
|
4ace4819ff | ||
|
|
ce893122af | ||
|
|
fb5188a8c6 | ||
|
|
c17f452fc7 | ||
|
|
71b0f54b7a | ||
|
|
d387d021fe | ||
|
|
d6fefc3603 | ||
|
|
efb8a29b5f | ||
|
|
ff100a499a | ||
|
|
d89dc65330 | ||
|
|
fa41527f85 | ||
|
|
f48d844e42 | ||
|
|
898df6287a | ||
|
|
2522d42c71 | ||
|
|
39c5e85564 | ||
|
|
1294c05a91 | ||
|
|
64f802d4f6 | ||
|
|
61e782389c | ||
|
|
7cfb230a5e | ||
|
|
0e2af40329 | ||
|
|
7f51ff0a8d | ||
|
|
d1a61c6dce | ||
|
|
c90d1fc8ef | ||
|
|
42cd046e90 | ||
|
|
52fa350138 | ||
|
|
4ea8357c6a | ||
|
|
dd0da70b06 | ||
|
|
d80f2a621d | ||
|
|
16082456df | ||
|
|
49cc69ecc5 | ||
|
|
a0c8e1959a | ||
|
|
c7010dac3c | ||
|
|
99bfc3aaa0 | ||
|
|
43b3922803 | ||
|
|
ca70ad1a9f | ||
|
|
a250419b59 | ||
|
|
291644f29d | ||
|
|
d4e97ab64c | ||
|
|
e92f98d3c6 | ||
|
|
999aac19de | ||
|
|
b2f6e5673d | ||
|
|
f0d1c962a7 | ||
|
|
6999b8d9b4 | ||
|
|
46e704d507 | ||
|
|
308e94ea79 | ||
|
|
0c839b2738 | ||
|
|
cff5859c59 | ||
|
|
6d95f5fc98 | ||
|
|
7684861249 | ||
|
|
9759cb7075 | ||
|
|
b3a5f9bef4 | ||
|
|
3e3b6cc1e1 | ||
|
|
474103dc82 | ||
|
|
092a8f2d05 | ||
|
|
2bcf0c354a | ||
|
|
73cc756cac | ||
|
|
6091c2dba0 | ||
|
|
2862a73253 | ||
|
|
850c3f2b6a | ||
|
|
98f3e4cbd3 | ||
|
|
efc8ed4845 | ||
|
|
0bc4c7d1a0 | ||
|
|
be2e754d78 | ||
|
|
817e72846e | ||
|
|
220768bffc | ||
|
|
3cd64bcb22 | ||
|
|
86bfb07c29 | ||
|
|
ad08bd62aa | ||
|
|
d79cab0680 | ||
|
|
d1d6f7d838 | ||
|
|
e31a7e5c9d | ||
|
|
e6f0d9887c | ||
|
|
2855d84fba | ||
|
|
3c19648a56 | ||
|
|
8db367c743 | ||
|
|
2c4fabba35 | ||
|
|
dff42ffb41 | ||
|
|
11d61a744d | ||
|
|
5cefdbf985 | ||
|
|
5485f96625 | ||
|
|
af0f46d23d | ||
|
|
c063fe0720 | ||
|
|
203ba7343c | ||
|
|
d889547b26 | ||
|
|
b66e19dc43 | ||
|
|
c84e3334bf | ||
|
|
d5eeb948d5 | ||
|
|
9670833a5d | ||
|
|
ca051e943f | ||
|
|
36d89d02e1 | ||
|
|
f4bfa77942 | ||
|
|
f2258d4202 | ||
|
|
d56bf34326 | ||
|
|
9fa3dee522 | ||
|
|
7ee2192c29 | ||
|
|
3a38292bab | ||
|
|
60cbb65d84 | ||
|
|
d118ab71e6 | ||
|
|
81a1aedeb9 | ||
|
|
1fd576436b | ||
|
|
fac05e7dcd | ||
|
|
eef3126f0b | ||
|
|
2df5a2a66d | ||
|
|
01e7e3c24a | ||
|
|
8112dee91e | ||
|
|
638f7a1c89 | ||
|
|
5de4c3cc3f | ||
|
|
6579007ca0 | ||
|
|
c596fb14bb | ||
|
|
116fc4e00d | ||
|
|
57f6f54f29 | ||
|
|
8640e6d1df | ||
|
|
801583fd07 | ||
|
|
4987534eba | ||
|
|
ed4bf1c13d | ||
|
|
5b24225251 | ||
|
|
886be8c452 | ||
|
|
269efb9c1e | ||
|
|
612448e4ae | ||
|
|
82db19d54c | ||
|
|
06aa3e6b8c | ||
|
|
abf985c69e | ||
|
|
c176b54f6b | ||
|
|
b24e691e7e | ||
|
|
c2e43dc1b0 | ||
|
|
7b7739c32c | ||
|
|
269172406f | ||
|
|
4c054d6de9 | ||
|
|
34a58369f2 | ||
|
|
59b4764a15 | ||
|
|
7ebba75fa2 | ||
|
|
b2e80efe3f | ||
|
|
b4b566318a | ||
|
|
27df896a9c | ||
|
|
8188a551f3 | ||
|
|
f13bff2a76 | ||
|
|
59f1c038fe | ||
|
|
006a409eb8 | ||
|
|
dec4ceabb5 | ||
|
|
4a902dbbbe | ||
|
|
8e488e2913 | ||
|
|
e58e27ce22 | ||
|
|
78c0926a64 | ||
|
|
4693069a06 | ||
|
|
70e529ef5d | ||
|
|
2a154f8c9a | ||
|
|
634ace552d | ||
|
|
751a1ba969 | ||
|
|
d95573741d | ||
|
|
faf4bcdd62 | ||
|
|
badae90051 | ||
|
|
a27c593a2a | ||
|
|
f699442bec | ||
|
|
8720931a53 | ||
|
|
600dcdfc58 | ||
|
|
a4b83327c2 | ||
|
|
8c1c49a45e | ||
|
|
b1f0014429 | ||
|
|
d984918c75 | ||
|
|
21ac4b5139 | ||
|
|
92eb7a0be4 | ||
|
|
b26b1c0820 | ||
|
|
a9dd6d6bdb | ||
|
|
d60c53cd12 | ||
|
|
6b0fe6e0a0 | ||
|
|
9c7ec55b40 | ||
|
|
28f1f4cbdc | ||
|
|
508b3ce730 | ||
|
|
87ecc61fb4 | ||
|
|
ce4d664abc | ||
|
|
45b41f0787 | ||
|
|
c47434634d | ||
|
|
b89355b9d8 | ||
|
|
3f40d6f7b7 | ||
|
|
155daac8ad | ||
|
|
f9d24d07dd | ||
|
|
d91e35e197 | ||
|
|
a967dd9d13 | ||
|
|
f4bb7bcbff | ||
|
|
0f6166da00 | ||
|
|
07e5b8295e | ||
|
|
9afdf86961 | ||
|
|
f4f1974be0 | ||
|
|
6f6399ca0f | ||
|
|
5018c0fbb8 | ||
|
|
188975ccbd | ||
|
|
5e1addc75e | ||
|
|
138beeac41 | ||
|
|
187364d94a | ||
|
|
6e74e76fcd | ||
|
|
615424d272 | ||
|
|
d40a7a609e | ||
|
|
0ec40f00a9 | ||
|
|
de054026f2 | ||
|
|
175b45d1ed | ||
|
|
e236b77817 | ||
|
|
21cd4a1b48 | ||
|
|
e9a50371f5 | ||
|
|
71f8a08e5f | ||
|
|
4419c93d80 | ||
|
|
fcc13ce02c | ||
|
|
941db04260 | ||
|
|
87d7a3053a | ||
|
|
ae11b2c281 | ||
|
|
f43577ec27 | ||
|
|
c648c38fb0 | ||
|
|
34d54fd309 | ||
|
|
891b1428cc | ||
|
|
453dd38e51 | ||
|
|
f59aefd3d9 | ||
|
|
451468d129 | ||
|
|
c0adf31da9 | ||
|
|
bb43c57b07 | ||
|
|
6c94bbc93f | ||
|
|
50422c608f | ||
|
|
7639157a49 | ||
|
|
f74cfaec5f | ||
|
|
d559b4a201 | ||
|
|
2d4064aca4 | ||
|
|
337d8ea78c | ||
|
|
4c0a26dbf9 | ||
|
|
885edd6261 | ||
|
|
011de75706 | ||
|
|
852e456d44 | ||
|
|
18136788e4 | ||
|
|
f1101808b7 | ||
|
|
791d5098a0 | ||
|
|
f2fd12fbe5 | ||
|
|
b5ab77908e | ||
|
|
5750e6cada | ||
|
|
394aa76a8f | ||
|
|
35c4deb884 |
@@ -40,7 +40,8 @@ before_script:
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
|
||||
213
CHANGELOG
213
CHANGELOG
@@ -1,3 +1,108 @@
|
||||
Hubzilla 5.2 (2021-01-13)
|
||||
- Use libzotdir for directory
|
||||
- Streamline usage of channel url for keyId
|
||||
- Basic work on PHP8 compatibility
|
||||
- Improve performance for forum post edit action
|
||||
- Improve File App tiles view
|
||||
- Update es strings
|
||||
- Update ru strings
|
||||
- Implement directory download via zip files in Files App
|
||||
- Implement bulk file download via zip files in Files App
|
||||
- Deprecate ! and !! forum tags - use direct messages to post to forums
|
||||
- Do not show forums where we do not have permission to post in ACL selector
|
||||
- Implement lockview for Files App
|
||||
- Implement file and directory rename functionality Files App
|
||||
- Implement file and directory copy functionality in Files App
|
||||
- Implement file and directory move functionality in Files App
|
||||
- Implement categories for files and directories in Files App
|
||||
- Implement drag and drop move action for files and directories in Files App
|
||||
- Implement bulk file actions for move, copy, categories and permissions
|
||||
- Implement a files categories widget
|
||||
- Implement a breadcrumb view for file paths
|
||||
- Rewrite xchan_vcard template
|
||||
- Update composer libs
|
||||
|
||||
Bugfixes
|
||||
- Fix direct messages by forum channel turned into group item
|
||||
- Fix ID3Parser composer autoload
|
||||
- Fix issue where directory_fallback_servers were not accessible from static function
|
||||
- Fix missing constant defenition for HUBLOC_OFFLINE
|
||||
- Fix sync_directories() including known dead sites
|
||||
- Fix undefined variable in poller preventing Onedirsync from running
|
||||
- Fix w2w posts not editable/deletable from local server
|
||||
- Fix issue where categories were not saved on forum wall posts
|
||||
- Fix no channel_id provided for contact_remove() in reply_purge()
|
||||
- Fix typo in notifier command
|
||||
- Fix profile title/description allowed more than 191 characters
|
||||
|
||||
Addons
|
||||
- Queueworker: cleanup whitespace
|
||||
- Queueworker: add some tweaks to prevent deadlocks for postgresql
|
||||
- Flashcards: compatibility for the changes in the Files App
|
||||
- Openstreemap: fix hostname parsing from URL
|
||||
- Openstreemap: fix content security policy
|
||||
- Pubcrawl: fix peertube video display
|
||||
- Pubcrawl: deliver updates to anyone owning the item
|
||||
|
||||
|
||||
Hubzilla 5.0.8 (2020-12-30)
|
||||
- Fix single quotes not escaped in the notifications title (issue 1503)
|
||||
- Return zot6 xchans for random_profile()
|
||||
- Return zot6 entries in dirsearch
|
||||
- Fix comment sync issue
|
||||
- Fix duplicate entries in contact autocomplete
|
||||
- Fix issue where direct message notifications where not displayed for wall items
|
||||
- Do not revalidate cached photos
|
||||
- Implement imagemagic resource consumption limiting
|
||||
- Specify key in mod owa
|
||||
- Fix issue where array was passed to get_key()
|
||||
|
||||
|
||||
Hubzilla 5.0.7 (2020-12-21)
|
||||
- Fix CardDAV addressbook ID
|
||||
- Use Zot6 for CardDAV and CalDAV sync between clones
|
||||
- Handle owa with hubloc_id_url only
|
||||
- Fix attachment in comment not visible after commenting - issue #1499
|
||||
|
||||
|
||||
Hubzilla 5.0.6 (2020-12-17)
|
||||
- Fix zot hublocs with empty hubloc_id_url in DB caused by clone import bug
|
||||
- Only look for zot6 and zot hublocs in mod owa
|
||||
- Fix abconfig issue when cloning a channel
|
||||
- Call notifier with refresh_all instead of location when importing a clone
|
||||
- Use Libzot::encode_locations() instead of zot_encode_locations() in notifier
|
||||
- Fix missing zot hubloc hubloc_id_url when importing a clone
|
||||
- Implement Libzot::zot_record_preferred() in various places to prevent hubloc confusion
|
||||
|
||||
Addons
|
||||
- Fix wrong redirect path for check_form_security_token_redirectOnErr() in various addons
|
||||
|
||||
|
||||
Hubzilla 5.0.5 (2020-12-12)
|
||||
- Fix hubloc issue in mod getfile
|
||||
- Remove duplicate SQL query
|
||||
|
||||
|
||||
Hubzilla 5.0.4 (2020-12-01)
|
||||
- Fix regression updating the primary
|
||||
- Dismiss title in response activities
|
||||
|
||||
|
||||
Hubzilla 5.0.3 (2020-11-26)
|
||||
- Upgrade phpunit to version 9
|
||||
- Remove dbunit because its not maintained anymore
|
||||
- Add uuid version 5 based uuid's to imported feeds
|
||||
- Fix potential delivery loop
|
||||
- Fix actor of fetched activities not stored
|
||||
- Improve update mechanism for comments and likes to prevent page jumps
|
||||
- Fix issue where channel suggestions was suggesting oneself
|
||||
- Do not auto-update except for own actions
|
||||
- Introduce ctrl-enter shortcut to send comments and posts
|
||||
|
||||
Addons
|
||||
Pubcrawl: improve addressing of mentioned actors
|
||||
|
||||
|
||||
Hubzilla 5.0.2 (2020-11-16)
|
||||
- Fix edge case in acl selector
|
||||
- Fix ping_site()
|
||||
@@ -14,7 +119,7 @@ Hubzilla 5.0.2 (2020-11-16)
|
||||
|
||||
|
||||
Hubzilla 5.0.1 (2020-11-12)
|
||||
- Fix share title size
|
||||
- Fix share title size
|
||||
- Fix issue where hublocs could get mixed up between different protocols
|
||||
|
||||
Addons
|
||||
@@ -330,7 +435,7 @@ Hubzilla 4.2 (2019-06-04)
|
||||
|
||||
Hubzilla 4.0.3 (2019-04-26)
|
||||
- Add attachments to zot6 event objects
|
||||
- Add zot6 to federated transports
|
||||
- Add zot6 to federated transports
|
||||
- Update import/export to handle zot6 hublocs and xchans
|
||||
- Update fix_system_urls() to handle zot6 hublocs
|
||||
- Fix infinite loop using postgres as backend
|
||||
@@ -383,7 +488,7 @@ Hubzilla 4.0.1 (2019-03-21)
|
||||
- Perform zot6 discovery in import_author_xchan
|
||||
- Fix authenticated fetches
|
||||
- Port zot_record_preferred() from zap
|
||||
|
||||
|
||||
Addons:
|
||||
- Pubcrawl: deliver comments to abook contacts and thread participants
|
||||
- Pubcrawl: fix can_comment_on_post()
|
||||
@@ -597,7 +702,7 @@ Hubzilla 3.8.3 (2018-11-05)
|
||||
- Fix forum notifications count not correct
|
||||
- Fix gallery addon which broke mod apps in some situations
|
||||
- Fix wiki_list widget not working on every page respectively level
|
||||
|
||||
|
||||
|
||||
Hubzilla 3.8.2 (2018-10-29)
|
||||
- Merge unmerged changes from dev into master
|
||||
@@ -613,7 +718,7 @@ Hubzilla 3.8.2 (2018-10-29)
|
||||
- Look for for matches in the entire string when suggesting emojis
|
||||
- Add [summary] bbcode to autocomplete list
|
||||
- Update blueimp_upload to version 9.23
|
||||
- Update spanish strings
|
||||
- Update spanish strings
|
||||
|
||||
Addons
|
||||
- Cart: don't allow items to be added unless user is logged into the Grid.
|
||||
@@ -671,7 +776,7 @@ Hubzilla 3.8 (2018-10-19)
|
||||
- Sanitise vcard fields
|
||||
- Don't sync system apps
|
||||
|
||||
|
||||
|
||||
Bugfixes
|
||||
- Fix issue with timeago plurals
|
||||
- Fix issue with HTTP signatures
|
||||
@@ -730,7 +835,7 @@ Hubzilla 3.8 (2018-10-19)
|
||||
Hubzilla 3.6 (2018-07-25)
|
||||
- Update jquery.timeago library
|
||||
- Implement Hookable CSP
|
||||
- ActivityStreams: accept header changes to support plume
|
||||
- ActivityStreams: accept header changes to support plume
|
||||
- Streamline inconsistencies in addon naming
|
||||
- SECURITY: hash the session_id in logs
|
||||
- Update justified gallery library
|
||||
@@ -743,9 +848,9 @@ Hubzilla 3.6 (2018-07-25)
|
||||
- Make droping posts of removed connections more memory efficient
|
||||
- Refactor getOutainfo() for DAV storage
|
||||
- Optionally report total available space when uploading
|
||||
- SECURITY: provide option to disable the cloud 'root' directory and make the cloud module require a target channel nickname
|
||||
- SECURITY: provide option to disable the cloud 'root' directory and make the cloud module require a target channel nickname
|
||||
- Add plink and llink to viewsource
|
||||
- Add new 'filter by name' feature
|
||||
- Add new 'filter by name' feature
|
||||
- Remove network tabs
|
||||
- New activity filter widget
|
||||
- New activity order widget
|
||||
@@ -787,8 +892,8 @@ Hubzilla 3.6 (2018-07-25)
|
||||
- Fix sys channels visible in dirsearch
|
||||
- Fix remote_self not working correctly
|
||||
- Fix photos not syncing properly if destination is a postgres site
|
||||
- Fix wrong hubloc_url for activitypub hublocs
|
||||
- Fix z_check_dns() for BSD
|
||||
- Fix wrong hubloc_url for activitypub hublocs
|
||||
- Fix z_check_dns() for BSD
|
||||
- Fix not null violation in oauth1
|
||||
- Fix DB issues with oauth2 on postgresql
|
||||
- Fix 'anybody authenticated' not correctly handled in can_comment_on_post()
|
||||
@@ -1350,10 +1455,10 @@ Hubzilla 2.6.2 (2017-08-31)
|
||||
Hubzilla 2.6.1 (2017-08-18)
|
||||
- Fix a regression with dav clients
|
||||
- Raise install requirements
|
||||
|
||||
|
||||
Plugins/Addon
|
||||
- Diaspora: fix PHP warning
|
||||
- GNU-Social: fix PHP warning
|
||||
- GNU-Social: fix PHP warning
|
||||
|
||||
|
||||
Hubzilla 2.6 (2017-08-16)
|
||||
@@ -1361,18 +1466,18 @@ Hubzilla 2.6 (2017-08-16)
|
||||
- Consolidate disable_discover_tab config
|
||||
- Fix some bbcode to markdown conversion issues
|
||||
- Improved finding of recursive attachment permissions
|
||||
- Smaller line-height for notification badges
|
||||
- Smaller line-height for notification badges
|
||||
- Bluegrid schema removed - will be added again if someone is willing to maintain it
|
||||
- Improved file_activity()
|
||||
- DB - add index for item.obj_type
|
||||
- Add options flag to bb_to_markdown() so we can distinguish between diaspora use and other use and therefore filter and adjust content selectively
|
||||
- Close the apps-menu if the notifications-menu is open and vice versa
|
||||
- Close the apps-menu if the notifications-menu is open and vice versa
|
||||
- Remove redundant call to jquery ready function in photo albums view
|
||||
- Remove borders from navbar toggler in mobile view
|
||||
- Improve the formatting of shares when converting from bbcode to markdown
|
||||
- Suppress fopen errors from dav
|
||||
- Make local channel (not our own) nav menus appear similar to what we are used from remote channels
|
||||
- Indicate the selected channel in the dropdown menu if the feature is enabled
|
||||
- Indicate the selected channel in the dropdown menu if the feature is enabled
|
||||
- Provide a mechanism to mark apps active in the app tray
|
||||
- Allow wildcard tag and category searches
|
||||
- Improved installer
|
||||
@@ -1384,7 +1489,7 @@ Hubzilla 2.6 (2017-08-16)
|
||||
- Update htmlpurifier to version 4.9.3
|
||||
- Update sabre/http to version 4.2.3
|
||||
- Add optimize-autoloader to composer config
|
||||
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
|
||||
- Missing abook_{my,their}_perms in pg schema and missing keys in mysql schema
|
||||
- Provide a gender icon on the profile sidebar within reason
|
||||
- Provide more comprehensible information on the admin summary page
|
||||
- Upgrade blueimp from 9.8 to 9.18
|
||||
@@ -1450,7 +1555,7 @@ Hubzilla 2.6 (2017-08-16)
|
||||
Cdav addon moved to core
|
||||
head_add_css() needs a preceding '/' to find files in the addons dir
|
||||
New addon code syntax highlighting (moved from core to addon)
|
||||
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
|
||||
Pubsubhubbub: specify a minimum number of records - otherwise it defaults to zero
|
||||
|
||||
|
||||
Hubzilla 2.4 (2017-05-31)
|
||||
@@ -1804,10 +1909,10 @@ Hubzilla 1.14 (2016-10-13)
|
||||
- Start grouping addons by server_role
|
||||
|
||||
Hubzilla 1.12
|
||||
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
|
||||
- guest access tokens can do anything you let them, including create posts and administer your channel
|
||||
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
|
||||
- guest access tokens can do anything you let them, including create posts and administer your channel
|
||||
- ACLs can be set on files and directories prior to creation.
|
||||
- ACL tool can now be used in multiple forms within a page
|
||||
- ACL tool can now be used in multiple forms within a page
|
||||
- a myriad of new drag/drop features (drop files or photos into /cloud or a post, or drop link into a post or comment, etc.)
|
||||
- multiple file uploads
|
||||
- improvements to website import
|
||||
@@ -1832,7 +1937,7 @@ Hubzilla 1.10
|
||||
Wiki:
|
||||
Lots of enhanced functionality, usability improvements, and bugfixes from v1.8
|
||||
Turned into an optional feature (default on) but disabled in UNO
|
||||
Sync:
|
||||
Sync:
|
||||
Items are now relocated (links patched) when syncing to clones
|
||||
Access Tokens:
|
||||
New feature - allows members to create access controlled guest logins and create/share 'dropbox' style links to protected resources.
|
||||
@@ -1840,7 +1945,7 @@ Hubzilla 1.10
|
||||
Use icons instead of iconic text constructs
|
||||
Only request geolocation permission when creating a post, not on page load
|
||||
provide 'redeliver' option on Delivery Report page for when things really stuff up
|
||||
CalDAV/CardDAV management pages with heaps of functionality
|
||||
CalDAV/CardDAV management pages with heaps of functionality
|
||||
Lib:
|
||||
z_fetch_url() updated to accept different request methods and request bodies
|
||||
item_store(), item_store_update() now return the stored items
|
||||
@@ -1864,7 +1969,7 @@ Hubzilla 1.10
|
||||
issues with 'use existing photo' for profile photo
|
||||
layout editor "list all layouts" returned empty
|
||||
oembed - better detect video file URLs so they aren't loaded into memory.
|
||||
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
|
||||
handcrafted bbcode tables could end up with way too much whitespace due to CRLF translation
|
||||
refresh permissions whitescreen in 1.8
|
||||
force immediate profile photo update on local site
|
||||
regression: 'save bookmarks' post action missing
|
||||
@@ -1889,7 +1994,7 @@ Hubzilla 1.8
|
||||
Documentation:
|
||||
Clarify privacy rights of commenters w/r/t conversation owners, as this policy is network dependent.
|
||||
Wiki (Git backed):
|
||||
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
|
||||
Brand new feature. We'll call it experimental until it has undergone a bit more testing.
|
||||
Account Cloning:
|
||||
Regression on clone channel creation created a new channel name each time.
|
||||
New issue (fixed) with directory creation on cloned file content
|
||||
@@ -1912,7 +2017,7 @@ Hubzilla 1.8
|
||||
Experimental PDO database driver
|
||||
Creation of Daemon Master class and port all daemon (background task) interfaces to use it
|
||||
Create separate class for each of 'Cron', 'Cron daily', and 'Cron weekly'.
|
||||
Always run a Cron maintenance task if not run in the last four hours
|
||||
Always run a Cron maintenance task if not run in the last four hours
|
||||
Refactor the template classes
|
||||
Refactor the ConversationItem mess into ThreadItem and ThreadStream
|
||||
Refactor Apps, Enotify, and Chat library code
|
||||
@@ -1920,7 +2025,7 @@ Hubzilla 1.8
|
||||
Created WebServer class for top level
|
||||
Remove mcrypt dependencies (deprecated in PHP 7.1)
|
||||
Remove all reserved (including merely 'not recommended') words as DB table column names
|
||||
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
|
||||
Provide mutex lock on DB logging to prevent recursion under rare failure modes.
|
||||
Bugfixes:
|
||||
Remove db_close function on page end - not needed and will not work with persistent DB connections.
|
||||
Undefined ref_session_write
|
||||
@@ -1940,7 +2045,7 @@ Hubzilla 1.8
|
||||
CalDAV/CardDAV plugin provided
|
||||
Issue sending Diaspora 'like' activities from sources that did not propagate the DCV
|
||||
Allow 'superblock' to work across API calls from third party clients
|
||||
statistics.json: use 'zot' as protocol
|
||||
statistics.json: use 'zot' as protocol
|
||||
Issues fixed during testing of ability to follow Diaspora tags
|
||||
Parse issue with Diaspora reshare content
|
||||
Chess: moved to main repo, ported to 1.8
|
||||
@@ -1952,7 +2057,7 @@ Hubzilla 1.6
|
||||
Plugin hook interface adapted to call static class methods
|
||||
Context help improved dramatically with content for the most accessed pages.
|
||||
Reverted a compatibility change to support GNU-social events. We copied their feed format and their feed format is wrong (XML namespace collisions).
|
||||
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
|
||||
Provide a querystring attribute to CSS/JS resources to avoid caching issues when our code changes (which is often).
|
||||
Fix javascript detection and allow either positive or negative detection.
|
||||
Refactor the plugin hook registration procedure, provide 'unregister all' ability.
|
||||
Fix RSD (Real Simple Discovery) which has been broken for some time.
|
||||
@@ -1961,7 +2066,7 @@ Hubzilla 1.6
|
||||
Update font-awesome to 4.6.1
|
||||
Update SabreDAV to 3.0 (PHP version requirements prevent us from pushing it further at this time)
|
||||
Help text added to cmdline utilities config and pconfig
|
||||
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
|
||||
Reworking of the database logging facility to avoid the rare but troublesome recursion when the log facility needed to query the DB internally to obtain config parameters.
|
||||
Implement singleton delivery (emulate nomadic identity to singleton networks and services)
|
||||
Fix empty album name in photo activities when photo is stored in top level folder.
|
||||
Allow engineering units to be used in service class data size restrictions (400M, 1G, etc.)
|
||||
@@ -1969,7 +2074,7 @@ Hubzilla 1.6
|
||||
Admin interface provided to manage external resource repositories
|
||||
Oembed security reworked. Now all sources are filtered by default unless blocked.
|
||||
Remove the date-string version and use only STD_VERSION
|
||||
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
|
||||
Add categories and categorisation filtering and the ability to edit all apps (including system apps) for a given channel
|
||||
Ensure the ability to translate names of all system apps (except those provided in addons)
|
||||
Provide ability to add categories to content from channel sources
|
||||
Lots of work on the presentation of the ACL widget to enhance usability and intuitiveness
|
||||
@@ -1983,24 +2088,24 @@ Hubzilla 1.6
|
||||
Provide some extra security checks to import data and files to prevent mischief
|
||||
Block CalDAV/CardDAV namespace reserved words from being used as a channel nickname/redress since Sabre is somewhat inflexible in this regard
|
||||
Plugins:
|
||||
Diaspora
|
||||
markdown translator work needed to eradicate the Diaspora Comment Virus.
|
||||
Diaspora
|
||||
markdown translator work needed to eradicate the Diaspora Comment Virus.
|
||||
upgrade all inbound paths with the most recent protocol changes (several of these)
|
||||
convert 'diaspora_meta' (Diaspora Comment Virus) to iconfig and eradicate from sites with Diaspora disabled
|
||||
implement social relay and allow following tags
|
||||
upgrade statistics.json to NodeInfo. Currently hubzilla sites are tagged as 'redmatrix' because the NodeInfo schema lacks extensibility and project names are used to designate protocol compatibility rather than protocol names.
|
||||
Std-embeds
|
||||
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
|
||||
New addon to allow a handful of corporate providers to run unfiltered embed code (youtube, vimeo, soundcloud)
|
||||
Various:
|
||||
upgrade font-awesome icons and adapt a few addons to Objects and the new hook interface and new controller interface
|
||||
|
||||
|
||||
Hubzilla 1.4
|
||||
[This list may appear brief, but encompasses a huge amount of re-writing and re-factoring
|
||||
of the internal code structure to gain long-term performance and stability and provide a standard
|
||||
interface to alternate protocol federation plugins which were made possible by the UNO configuration.
|
||||
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
|
||||
improved protocol federation potential to other networks by virtue of removing nomadic identity
|
||||
(which is not possible to model or work around using other network protocols).]
|
||||
UNO is a configuration of hubzilla introduced in 1.3 with reduced complexity and which provides
|
||||
improved protocol federation potential to other networks by virtue of removing nomadic identity
|
||||
(which is not possible to model or work around using other network protocols).]
|
||||
|
||||
Implement channel move operation for UNO configuration
|
||||
Remove bookmark references in UNO (which has no bookmarks by default)
|
||||
@@ -2023,10 +2128,10 @@ Hubzilla 1.4
|
||||
Rework detection of JavaScript to avoid reload penalty under normal operation
|
||||
Changed primary directory server to a hubzilla server
|
||||
Plugins:
|
||||
Diaspora - switch to alternate XML parser to avoid storing compound objects
|
||||
Diaspora - switch to alternate XML parser to avoid storing compound objects
|
||||
GNU-Social - Huge amounts of work, federation somewhat working now, several issues remain
|
||||
Friendica - Initial federation work (not yet published)
|
||||
|
||||
|
||||
Hubzilla 1.3
|
||||
Admin Security configuration page created which consolidates several previously hidden settings:
|
||||
Communication white/black lists
|
||||
@@ -2042,26 +2147,26 @@ Hubzilla 1.3
|
||||
"pubsites" module UI reworked
|
||||
item-meta ("iconfig") created which implements arbitrary storage for item metadata for plugins
|
||||
abook-meta ("abconfig") created which implements arbitrary storage for connection metadata for plugins
|
||||
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
|
||||
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
|
||||
"Strict transport security header" made optional as it conflicts with some existing Apache/nginx configurations
|
||||
"Hubzilla UNO" (Hubzilla with radically simplified and locked site settings) implemented as an install configuration.
|
||||
.well-known directory conflict worked out to support LetsEncrypt cert ownership checks without disrupting webfinger and other internal uses of .well-known
|
||||
Lots of work on 'zcards' which are self-contained HTML representations of a channel including cover photos, profile photos, and some text information
|
||||
Long standing bug uncovered which failed to properly restrict the lower time limit for public feed requests
|
||||
A number of fixes to "readmore" to fix page jumping
|
||||
Bugfix: persons other than the channel owner who have permission to upload photos to a channel could not do so if the js_upload plugin/addon was enabled
|
||||
Siteinfo incorrectly identifying secondary directory servers
|
||||
Allow admin to set and lock features when UNO is configured
|
||||
Allow admin to set and lock features when UNO is configured
|
||||
Atom feeds: alter how events are formatted to be compatible with GNU-social
|
||||
Allow guest/visitor access to view personal calendar
|
||||
Moved several more classes to "composer format" and provided an autoloader.
|
||||
Bugfix: require existing password to change password
|
||||
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
|
||||
Bugfix: allow relative_date() to be translated to Polish which has more than two plural forms.
|
||||
Plugin API: add "requires" keyword to module header to indicate dependent addons
|
||||
ActivityStreams improvements and cleanup: photo and file activities
|
||||
UI cleanup for editing profile when multiple profiles enabled
|
||||
Removed the "markdown" feature as there are numerous issues and no maintainer.
|
||||
Provide "footer" bbcode to ease theming of post footer content
|
||||
Bugfix: install issues caused by composer code refactor and typo in postgres load file
|
||||
Bugfix: install issues caused by composer code refactor and typo in postgres load file
|
||||
Plugins:
|
||||
keepout - "block public on steroids"
|
||||
pubsubhubbub - provides PuSH support to Atom feeds, required for GNU-social federation
|
||||
@@ -2069,7 +2174,7 @@ Hubzilla 1.3
|
||||
Diaspora protocol - some work to ease migration to the new signing format
|
||||
Diaspost - disabled; numerous issues and no maintainer
|
||||
smileybutton - theme work and fixed compatibility with other jot-tools plugins
|
||||
|
||||
|
||||
|
||||
Hubzilla 1.2
|
||||
Provide extra HTTP security headers (several of them).
|
||||
@@ -2079,7 +2184,7 @@ Hubzilla 1.2
|
||||
Add locked features to siteinfo report to aid remote debugging
|
||||
Provide version compatibility checking to plugins (minversion, maxversion, and minphpversion)
|
||||
Account config storage
|
||||
Provide optional integrated registration and channel create form
|
||||
Provide optional integrated registration and channel create form
|
||||
cli utility for managing addons
|
||||
issue with sharing photo "items"
|
||||
cover photo manager: upload, crop, and store
|
||||
@@ -2101,7 +2206,7 @@ Hubzilla 1.2
|
||||
proc_run modified to use exec() instead of proc_open() - causing issues on some PHP installations
|
||||
remote delegation failure under a specific set of circumstances which we were finally able to duplicate
|
||||
Delegation section of Channel Manager was missing names and contained useless notification icons.
|
||||
Change "expire" channel setting to show system limit if there is one.
|
||||
Change "expire" channel setting to show system limit if there is one.
|
||||
Regression: provide a one-click ignore of pending connection
|
||||
Config to control directory keyword generation on client and server.
|
||||
"Collections" renamed to "Privacy Groups", documentation improved
|
||||
@@ -2154,11 +2259,11 @@ Hubzilla 1.1
|
||||
Addons/Plugins:
|
||||
Pageheader addon ported from Friendica
|
||||
Hubwall (allow admin to send email to all accounts on this hub) created
|
||||
GNU-social - queueing added
|
||||
Diaspora - fixes for various failures to update profile photos, updates to queue API
|
||||
GNU-social - queueing added
|
||||
Diaspora - fixes for various failures to update profile photos, updates to queue API
|
||||
Cross Domain Authenticated Chess (Andrew Manning's repository)
|
||||
|
||||
And... the normal "lots of bugs fixed, translations updated, and documentation improved"
|
||||
|
||||
|
||||
|
||||
And... the normal "lots of bugs fixed, translations updated, and documentation improved"
|
||||
|
||||
|
||||
|
||||
|
||||
27
SBOM.md
27
SBOM.md
@@ -3,27 +3,28 @@
|
||||
|Name|Version|License|Source|
|
||||
|----|-------|-------|------|
|
||||
|blueimp/jquery-file-upload|10.31.0.0|MIT|https://github.com/vkhramtsov/jQuery-File-Upload.git|
|
||||
|brick/math|0.9.1.0|MIT|https://github.com/brick/math.git|
|
||||
|bshaffer/oauth2-server-php|1.11.1.0|MIT|https://github.com/bshaffer/oauth2-server-php.git|
|
||||
|commerceguys/intl|1.0.5.0|MIT|https://github.com/commerceguys/intl.git|
|
||||
|commerceguys/intl|1.0.7.0|MIT|https://github.com/commerceguys/intl.git|
|
||||
|desandro/imagesloaded|4.1.4.0|MIT|https://github.com/desandro/imagesloaded.git|
|
||||
|ezyang/htmlpurifier|4.13.0.0|LGPL-2.1-or-later|https://github.com/ezyang/htmlpurifier.git|
|
||||
|league/html-to-markdown|4.10.0.0|MIT|https://github.com/thephpleague/html-to-markdown.git|
|
||||
|lukasreschke/id3parser|0.0.3.0|GPL|https://github.com/LukasReschke/ID3Parser.git|
|
||||
|michelf/php-markdown|1.9.0.0|BSD-3-Clause|https://github.com/michelf/php-markdown.git|
|
||||
|paragonie/random_compat|9.99.99.0|MIT|https://github.com/paragonie/random_compat.git|
|
||||
|pear/text_languagedetect|1.0.0.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|
||||
|pear/text_languagedetect|1.0.1.0|BSD-2-Clause|https://github.com/pear/Text_LanguageDetect.git|
|
||||
|psr/log|1.1.3.0|MIT|https://github.com/php-fig/log.git|
|
||||
|ramsey/uuid|3.9.3.0|MIT|https://github.com/ramsey/uuid.git|
|
||||
|sabre/dav|4.1.1.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|
||||
|sabre/event|5.1.0.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|
||||
|sabre/http|5.1.0.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
|
||||
|sabre/uri|2.2.0.0|BSD-3-Clause|https://github.com/sabre-io/uri.git|
|
||||
|sabre/vobject|4.3.1.0|BSD-3-Clause|https://github.com/sabre-io/vobject.git|
|
||||
|sabre/xml|2.2.1.0|BSD-3-Clause|https://github.com/sabre-io/xml.git|
|
||||
|simplepie/simplepie|1.5.5.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|
||||
|ramsey/collection|1.1.1.0|MIT|https://github.com/ramsey/collection.git|
|
||||
|ramsey/uuid|4.1.1.0|MIT|https://github.com/ramsey/uuid.git|
|
||||
|sabre/dav|4.1.3.0|BSD-3-Clause|https://github.com/sabre-io/dav.git|
|
||||
|sabre/event|5.1.2.0|BSD-3-Clause|https://github.com/sabre-io/event.git|
|
||||
|sabre/http|5.1.1.0|BSD-3-Clause|https://github.com/sabre-io/http.git|
|
||||
|sabre/uri|2.2.1.0|BSD-3-Clause|https://github.com/sabre-io/uri.git|
|
||||
|sabre/vobject|4.3.3.0|BSD-3-Clause|https://github.com/sabre-io/vobject.git|
|
||||
|sabre/xml|2.2.3.0|BSD-3-Clause|https://github.com/sabre-io/xml.git|
|
||||
|simplepie/simplepie|1.5.6.0|BSD-3-Clause|https://github.com/simplepie/simplepie.git|
|
||||
|smarty/smarty|3.1.36.0|LGPL-3.0|https://github.com/smarty-php/smarty.git|
|
||||
|symfony/polyfill-ctype|1.13.1.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|
||||
|twbs/bootstrap|4.5.2.0|MIT|https://github.com/twbs/bootstrap.git|
|
||||
|symfony/polyfill-ctype|1.20.0.0|MIT|https://github.com/symfony/polyfill-ctype.git|
|
||||
|twbs/bootstrap|4.5.3.0|MIT|https://github.com/twbs/bootstrap.git|
|
||||
|fullcalendar/fullcalendar|4.4.2.0|MIT|https://github.com/fullcalendar/fullcalendar.git|
|
||||
|miromannino/Justified-Gallery|3.8.1.0|MIT|https://github.com/miromannino/Justified-Gallery.git|
|
||||
|fengyuanchen/cropperjs|1.5.7.0|MIT|https://github.com/fengyuanchen/cropperjs.git|
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Cron_daily {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
@@ -14,12 +16,11 @@ class Cron_daily {
|
||||
*/
|
||||
|
||||
|
||||
require_once('include/dir_fns.php');
|
||||
check_upstream_directory();
|
||||
Libzotdir::check_upstream_directory();
|
||||
|
||||
|
||||
// Fire off the Cron_weekly process if it's the correct day.
|
||||
|
||||
|
||||
$d3 = intval(datetime_convert('UTC','UTC','now','N'));
|
||||
if($d3 == 7) {
|
||||
Master::Summon(array('Cron_weekly'));
|
||||
@@ -80,15 +81,14 @@ class Cron_daily {
|
||||
downgrade_accounts();
|
||||
|
||||
// If this is a directory server, request a sync with an upstream
|
||||
// directory at least once a day, up to once every poll interval.
|
||||
// directory at least once a day, up to once every poll interval.
|
||||
// Pull remote changes and push local changes.
|
||||
// potential issue: how do we keep from creating an endless update loop?
|
||||
// potential issue: how do we keep from creating an endless update loop?
|
||||
|
||||
$dirmode = get_config('system','directory_mode');
|
||||
|
||||
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
require_once('include/dir_fns.php');
|
||||
sync_directories($dirmode);
|
||||
Libzotdir::sync_directories($dirmode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class Gprobe {
|
||||
if(! strpos($url,'@'))
|
||||
return;
|
||||
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
|
||||
@@ -17,26 +17,26 @@ require_once('include/bbcode.php');
|
||||
|
||||
/*
|
||||
* This file was at one time responsible for doing all deliveries, but this caused
|
||||
* big problems on shared hosting systems, where the process might get killed by the
|
||||
* hosting provider and nothing would get delivered.
|
||||
* big problems on shared hosting systems, where the process might get killed by the
|
||||
* hosting provider and nothing would get delivered.
|
||||
* It now only delivers one message under certain cases, and invokes a queued
|
||||
* delivery mechanism (include/deliver.php) to deliver individual contacts at
|
||||
* delivery mechanism (include/deliver.php) to deliver individual contacts at
|
||||
* controlled intervals.
|
||||
* This has a much better chance of surviving random processes getting killed
|
||||
* by the hosting provider.
|
||||
* by the hosting provider.
|
||||
*
|
||||
* The basic flow is:
|
||||
* Identify the type of message
|
||||
* Collect any information that needs to be sent
|
||||
* Convert it into a suitable generic format for sending
|
||||
* Figure out who the recipients are and if we need to relay
|
||||
* Figure out who the recipients are and if we need to relay
|
||||
* through a conversation owner
|
||||
* Once we know what recipients are involved, collect a list of
|
||||
* Once we know what recipients are involved, collect a list of
|
||||
* destination sites
|
||||
* Build and store a queue item for each unique site and invoke
|
||||
* a delivery process for each site or a small number of sites (1-3)
|
||||
* and add a slight delay between each delivery invocation if desired (usually)
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -61,7 +61,7 @@ require_once('include/bbcode.php');
|
||||
*
|
||||
* and ITEM_ID is the id of the item in the database that needs to be sent to others.
|
||||
*
|
||||
* ZOT
|
||||
* ZOT
|
||||
* permission_create abook_id
|
||||
* permission_accept abook_id
|
||||
* permission_reject abook_id
|
||||
@@ -167,7 +167,7 @@ class Notifier {
|
||||
$normal_mode = false;
|
||||
}
|
||||
elseif(in_array($cmd, [ 'permission_update', 'permission_reject', 'permission_accept', 'permission_create' ])) {
|
||||
// Get the (single) recipient
|
||||
// Get the (single) recipient
|
||||
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_self = 0",
|
||||
intval($item_id)
|
||||
);
|
||||
@@ -176,7 +176,7 @@ class Notifier {
|
||||
// Get the sender
|
||||
$channel = channelx_by_n($uid);
|
||||
if($channel) {
|
||||
$perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
|
||||
$perm_update = array('sender' => $channel, 'recipient' => $r[0], 'success' => false, 'deliveries' => '');
|
||||
|
||||
if($cmd === 'permission_create')
|
||||
call_hooks('permissions_create',$perm_update);
|
||||
@@ -192,7 +192,7 @@ class Notifier {
|
||||
$deliveries[] = $perm_update['deliveries'];
|
||||
do_delivery($deliveries);
|
||||
}
|
||||
return;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
$recipients[] = $r[0]['abook_xchan'];
|
||||
@@ -236,7 +236,7 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
$encoded_item = array('locations' => zot_encode_locations($channel),'type' => 'location', 'encoding' => 'zot');
|
||||
$encoded_item = array('locations' => Libzot::encode_locations($channel),'type' => 'location', 'encoding' => 'zot');
|
||||
$target_item = array('aid' => $channel['channel_account_id'],'uid' => $channel['channel_id']);
|
||||
$private = false;
|
||||
$packet_type = 'location';
|
||||
@@ -293,7 +293,7 @@ class Notifier {
|
||||
xchan_query($r);
|
||||
|
||||
$r = fetch_post_tags($r);
|
||||
|
||||
|
||||
$target_item = $r[0];
|
||||
|
||||
if(in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
|
||||
@@ -329,7 +329,7 @@ class Notifier {
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
|
||||
if(intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
|
||||
intval($target_item['item_blocked']) ||
|
||||
intval($target_item['item_blocked']) ||
|
||||
( intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
|
||||
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
|
||||
return;
|
||||
@@ -372,7 +372,7 @@ class Notifier {
|
||||
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r);
|
||||
|
||||
|
||||
$parent_item = $r[0];
|
||||
$top_level_post = false;
|
||||
}
|
||||
@@ -397,7 +397,7 @@ class Notifier {
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_activity($target_item)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item,true), LOGGER_DEBUG);
|
||||
logger('encoded: ' . print_r($activity,true), LOGGER_DEBUG);
|
||||
@@ -405,11 +405,11 @@ class Notifier {
|
||||
// Send comments to the owner to re-deliver to everybody in the conversation
|
||||
// We only do this if the item in question originated on this site. This prevents looping.
|
||||
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
|
||||
// Relaying should never be initiated on a post that arrived from elsewhere.
|
||||
// Relaying should never be initiated on a post that arrived from elsewhere.
|
||||
|
||||
// We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this
|
||||
// flag on comments for an extended period. So we'll also call comment_local_origin() which looks at
|
||||
// the hostname in the message_id and provides a second (fallback) opinion.
|
||||
// the hostname in the message_id and provides a second (fallback) opinion.
|
||||
|
||||
$relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
|
||||
|
||||
@@ -426,9 +426,9 @@ class Notifier {
|
||||
// tag_deliver'd post which needs to be sent back to the original author
|
||||
|
||||
if(($cmd === 'uplink') && intval($parent_item['item_uplink']) && (! $top_level_post)) {
|
||||
logger('notifier: uplink');
|
||||
logger('notifier: uplink');
|
||||
$uplink = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
|
||||
logger('notifier: followup relay', LOGGER_DEBUG);
|
||||
@@ -445,8 +445,8 @@ class Notifier {
|
||||
logger('notifier: owner relay');
|
||||
$upstream = false;
|
||||
// if our parent is a tag_delivery recipient, uplink to the original author causing
|
||||
// a delivery fork.
|
||||
|
||||
// a delivery fork.
|
||||
|
||||
if(($parent_item) && intval($parent_item['item_uplink']) && (! $top_level_post) && ($cmd !== 'uplink')) {
|
||||
// don't uplink a relayed post to the relay owner
|
||||
if($parent_item['source_xchan'] !== $parent_item['owner_xchan']) {
|
||||
@@ -462,21 +462,14 @@ class Notifier {
|
||||
if ($top_level_post) {
|
||||
// remove clones who will receive the post via sync
|
||||
$recipients = array_diff($recipients, [ $target_item['owner_xchan'] ]);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME add any additional recipients such as mentions, etc.
|
||||
|
||||
// don't send deletions onward for other people's stuff
|
||||
// TODO verify this is needed - copied logic from same place in old code
|
||||
|
||||
if(intval($target_item['item_deleted']) && (! intval($target_item['item_wall']))) {
|
||||
logger('notifier: ignoring delete notification for non-wall item', LOGGER_NORMAL, LOG_NOTICE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
|
||||
$walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false);
|
||||
|
||||
// Generic delivery section, we have an encoded item and recipients
|
||||
// Now start the delivery process
|
||||
@@ -505,7 +498,7 @@ class Notifier {
|
||||
if($details) {
|
||||
foreach($details as $d) {
|
||||
|
||||
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
|
||||
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
|
||||
if($private) {
|
||||
$env_recips[] = [
|
||||
'guid' => $d['xchan_guid'],
|
||||
@@ -557,19 +550,19 @@ class Notifier {
|
||||
// shouldn't happen
|
||||
logger('notifier: private message with no envelope recipients.' . print_r($argv,true), LOGGER_NORMAL, LOG_NOTICE);
|
||||
}
|
||||
|
||||
|
||||
logger('notifier: recipients (may be delivered to more if public): ' . print_r($recip_list,true), LOGGER_DEBUG);
|
||||
|
||||
|
||||
|
||||
// Now we have collected recipients (except for external mentions, FIXME)
|
||||
// Let's reduce this to a set of hubs; checking that the site is not dead.
|
||||
|
||||
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
|
||||
where hubloc_hash in (" . protect_sprintf(implode(',',$recipients)) . ")
|
||||
$hubs = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc left join site on site_url = hubloc_url
|
||||
where hubloc_hash in (" . protect_sprintf(implode(',',$recipients)) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0"
|
||||
);
|
||||
|
||||
// public posts won't make it to the local public stream unless there's a recipient on this site.
|
||||
// public posts won't make it to the local public stream unless there's a recipient on this site.
|
||||
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
|
||||
|
||||
if (! $private) {
|
||||
@@ -583,7 +576,7 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
if (! $found_localhost) {
|
||||
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
|
||||
$localhub = q("select hubloc.*, site.site_crypto, site.site_flags, site.site_version, site.site_project, site.site_dead from hubloc
|
||||
left join site on site_url = hubloc_url where hubloc_id_url = '%s' and hubloc_error = 0 and hubloc_deleted = 0",
|
||||
dbesc(z_root() . '/channel/sys')
|
||||
);
|
||||
@@ -592,14 +585,14 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(! $hubs) {
|
||||
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
|
||||
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey,
|
||||
* since it may have been a re-install which has not yet been detected and pruned.
|
||||
* For other networks which don't have or require sitekeys, we'll have to use the URL
|
||||
*/
|
||||
@@ -629,7 +622,7 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($hub['hubloc_network'] == 'zot') {
|
||||
if(! in_array($hub['hubloc_sitekey'],$keys)) {
|
||||
@@ -640,9 +633,16 @@ class Notifier {
|
||||
}
|
||||
else {
|
||||
if(! in_array($hub['hubloc_url'],$urls)) {
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
if($hub['hubloc_url'] === z_root()) {
|
||||
//deliver to local hub first
|
||||
array_unshift($hublist, $hub['hubloc_host'] . ' ' . $hub['hubloc_network']);
|
||||
array_unshift($dhubs, $hub);
|
||||
}
|
||||
else {
|
||||
$hublist[] = $hub['hubloc_host'] . ' ' . $hub['hubloc_network'];
|
||||
$dhubs[] = $hub;
|
||||
}
|
||||
$urls[] = $hub['hubloc_url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -707,8 +707,8 @@ class Notifier {
|
||||
}
|
||||
|
||||
// Do not change this to a uuid as long as we have traditional zot servers
|
||||
// in the loop. The signature verification step can't handle dashes in the
|
||||
// hashes.
|
||||
// in the loop. The signature verification step can't handle dashes in the
|
||||
// hashes.
|
||||
|
||||
$hash = random_string(48);
|
||||
|
||||
@@ -759,13 +759,13 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
|
||||
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
|
||||
|
||||
// block zot private reshares from zot6, as this could cause a number of privacy issues
|
||||
// due to parenting differences between the reshare implementations. In zot a reshare is
|
||||
// a standalone parent activity and in zot6 it is a followup/child of the original activity.
|
||||
// For public reshares, some comments to the reshare on the zot fork will not make it to zot6
|
||||
// due to these different message models. This cannot be prevented at this time.
|
||||
// due to these different message models. This cannot be prevented at this time.
|
||||
|
||||
if($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
|
||||
continue;
|
||||
@@ -775,7 +775,7 @@ class Notifier {
|
||||
}
|
||||
else {
|
||||
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
|
||||
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
|
||||
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
|
||||
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
|
||||
// to trigger dequeue'ing
|
||||
|
||||
@@ -832,9 +832,9 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
$deliveries[] = $hash;
|
||||
$deliveries[] = $hash;
|
||||
}
|
||||
|
||||
|
||||
if($normal_mode) {
|
||||
$x = q("select * from hook where hook = 'notifier_normal'");
|
||||
if($x) {
|
||||
@@ -850,7 +850,7 @@ class Notifier {
|
||||
if ($dead) {
|
||||
foreach ($dead as $deceased) {
|
||||
if (is_array($target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan, dreport_queue )
|
||||
values ( '%s', '%s','%s','%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($target_item['mid']),
|
||||
dbesc($deceased['hubloc_host']),
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/dir_fns.php');
|
||||
|
||||
@@ -11,7 +14,7 @@ class Onedirsync {
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
logger('onedirsync: start ' . intval($argv[1]));
|
||||
|
||||
|
||||
if(($argc > 1) && (intval($argv[1])))
|
||||
$update_id = intval($argv[1]);
|
||||
|
||||
@@ -19,7 +22,7 @@ class Onedirsync {
|
||||
logger('onedirsync: no update');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from updates where ud_id = %d limit 1",
|
||||
intval($update_id)
|
||||
);
|
||||
@@ -50,10 +53,13 @@ class Onedirsync {
|
||||
|
||||
// ignore doing an update if this ud_addr refers to a known dead hubloc
|
||||
|
||||
$h = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
$h = q("select * from hubloc where hubloc_addr = '%s'",
|
||||
dbesc($r[0]['ud_addr'])
|
||||
);
|
||||
if(($h) && ($h[0]['hubloc_status'] & HUBLOC_OFFLINE)) {
|
||||
|
||||
$h = Libzot::zot_record_preferred($h);
|
||||
|
||||
if(($h) && ($h['hubloc_status'] & HUBLOC_OFFLINE)) {
|
||||
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
@@ -63,13 +69,13 @@ class Onedirsync {
|
||||
return;
|
||||
}
|
||||
|
||||
// we might have to pull this out some day, but for now update_directory_entry()
|
||||
// we might have to pull this out some day, but for now update_directory_entry()
|
||||
// runs zot_finger() and is kind of zot specific
|
||||
|
||||
if($h && $h[0]['hubloc_network'] !== 'zot')
|
||||
if($h && ! in_array($h['hubloc_network'], ['zot6', 'zot']))
|
||||
return;
|
||||
|
||||
update_directory_entry($r[0]);
|
||||
Libzotdir::update_directory_entry($r[0]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ class Poller {
|
||||
$force = true;
|
||||
}
|
||||
|
||||
|
||||
$sql_extra = (($manual_id) ? " AND abook_id = " . intval($manual_id) . " " : "");
|
||||
|
||||
reload_plugins();
|
||||
@@ -86,7 +85,6 @@ class Poller {
|
||||
);
|
||||
|
||||
if($contacts) {
|
||||
|
||||
foreach($contacts as $contact) {
|
||||
|
||||
$update = false;
|
||||
@@ -174,6 +172,8 @@ class Poller {
|
||||
}
|
||||
}
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
|
||||
if($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
$r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last <= '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Identity\BasicId;
|
||||
namespace Zotlabs\Identity;
|
||||
|
||||
class BasicId {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Zotlabs\Identity\ProfilePhoto;
|
||||
namespace Zotlabs\Identity;
|
||||
|
||||
class ProfilePhoto {
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ class Activity {
|
||||
);
|
||||
if($r) {
|
||||
xchan_query($r,true);
|
||||
$r = fetch_post_tags($r,true);
|
||||
$r = fetch_post_tags($r);
|
||||
if (in_array($r[0]['verb'], ['Create', 'Invite']) && $r[0]['obj_type'] === ACTIVITY_OBJ_EVENT) {
|
||||
$r[0]['verb'] = 'Invite';
|
||||
return self::encode_activity($r[0]);
|
||||
@@ -713,7 +713,7 @@ class Activity {
|
||||
);
|
||||
if($p) {
|
||||
xchan_query($p,true);
|
||||
$p = fetch_post_tags($p,true);
|
||||
$p = fetch_post_tags($p);
|
||||
$i['obj'] = self::encode_item($p[0]);
|
||||
|
||||
// convert to zot6 emoji reaction encoding which uses the target object to indicate the
|
||||
@@ -800,7 +800,7 @@ class Activity {
|
||||
$is_directmessage = false;
|
||||
$recips = get_iconfig($i['parent'], 'activitypub', 'recips');
|
||||
|
||||
if(in_array($i['author']['xchan_url'], $recips['to'])) {
|
||||
if(array_path_exists('to', $recips) && in_array($i['author']['xchan_url'], $recips['to'])) {
|
||||
$reply_url = $d[0]['xchan_url'];
|
||||
$is_directmessage = true;
|
||||
}
|
||||
@@ -2143,7 +2143,7 @@ class Activity {
|
||||
if(! $s['edited'])
|
||||
$s['edited'] = $s['created'];
|
||||
|
||||
$s['title'] = self::bb_content($content,'name');
|
||||
$s['title'] = (($response_activity) ? EMPTY_STR : self::bb_content($content,'name'));
|
||||
$s['summary'] = self::bb_content($content,'summary');
|
||||
$s['body'] = ((self::bb_content($content,'bbcode') && (! $response_activity)) ? self::bb_content($content,'bbcode') : self::bb_content($content,'content'));
|
||||
|
||||
@@ -2648,7 +2648,7 @@ class Activity {
|
||||
$current_item = $item;
|
||||
|
||||
while($current_item['parent_mid'] !== $current_item['mid']) {
|
||||
$n = ActivityStreams::fetch($current_item['parent_mid'], $channel);
|
||||
$n = self::fetch($current_item['parent_mid'], $channel);
|
||||
if(! $n) {
|
||||
break;
|
||||
}
|
||||
@@ -2660,6 +2660,10 @@ class Activity {
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_array($a->actor) && array_key_exists('id',$a->actor)) {
|
||||
self::actor_store($a->actor['id'],$a->actor);
|
||||
}
|
||||
|
||||
$replies = null;
|
||||
if(isset($a->obj['replies']['first']['items'])) {
|
||||
$replies = $a->obj['replies']['first']['items'];
|
||||
@@ -2725,7 +2729,7 @@ class Activity {
|
||||
|
||||
foreach($arr as $url) {
|
||||
|
||||
$n = ActivityStreams::fetch($url, $channel);
|
||||
$n = self::fetch($url, $channel);
|
||||
if(! $n) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class ActivityStreams {
|
||||
if($this->data) {
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
|
||||
if(is_array($this->data) && array_key_exists('signed',$this->data)) {
|
||||
$ret = JSalmon::verify($this->data);
|
||||
$tmp = JSalmon::unpack($this->data['data']);
|
||||
@@ -103,7 +103,7 @@ class ActivityStreams {
|
||||
}
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object',$this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
|
||||
}
|
||||
@@ -115,10 +115,10 @@ class ActivityStreams {
|
||||
|
||||
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||
|
||||
if((! $this->parent_id) && is_array($this->obj)) {
|
||||
if((! $this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['inReplyTo'];
|
||||
}
|
||||
if((! $this->parent_id) && is_array($this->obj)) {
|
||||
if((! $this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
}
|
||||
@@ -286,7 +286,7 @@ class ActivityStreams {
|
||||
if (! $s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact' ]));
|
||||
return (in_array($s, [ 'Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact' ]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,7 +302,7 @@ class ActivityStreams {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if($this->is_url($x)) {
|
||||
|
||||
// SECURITY: If we have already stored the actor profile, re-generate it
|
||||
// SECURITY: If we have already stored the actor profile, re-generate it
|
||||
// from cached data - don't refetch it from the network
|
||||
|
||||
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
|
||||
@@ -344,7 +344,7 @@ class ActivityStreams {
|
||||
}
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
|
||||
if(is_array($x) && array_key_exists('signed',$x)) {
|
||||
$ret = JSalmon::verify($x);
|
||||
$tmp = JSalmon::unpack($x['data']);
|
||||
|
||||
@@ -64,7 +64,7 @@ class Enotify {
|
||||
$sitename = get_config('system','sitename');
|
||||
$site_admin = sprintf( t('%s Administrator'), $sitename);
|
||||
$opt_out1 = sprintf( t('This email was sent by %1$s at %2$s.'), t('$Projectname'), \App::get_hostname());
|
||||
$opt_out2 = sprintf( t('To stop receiving these messages, please adjust your Notification Settings at %s'), z_root() . '/settings');
|
||||
$opt_out2 = sprintf( t('To stop receiving these messages, please adjust your Notification Settings at %s'), z_root() . '/settings');
|
||||
$hopt_out2 = sprintf( t('To stop receiving these messages, please adjust your %s.'), '<a href="' . z_root() . '/settings' . '">' . t('Notification Settings') . '</a>');
|
||||
$sender_name = $product;
|
||||
$hostname = \App::get_hostname();
|
||||
@@ -80,7 +80,7 @@ class Enotify {
|
||||
$sender_email = get_config('system','from_email');
|
||||
if(! $sender_email)
|
||||
$sender_email = 'Administrator' . '@' . $hostname;
|
||||
|
||||
|
||||
$sender_name = get_config('system','from_email_name');
|
||||
if(! $sender_name)
|
||||
$sender_name = \Zotlabs\Lib\System::get_site_name();
|
||||
@@ -108,7 +108,7 @@ class Enotify {
|
||||
logger('notification invoked for an old item which may have been refetched.',LOGGER_DEBUG,LOG_INFO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$title = $body = '';
|
||||
}
|
||||
@@ -181,7 +181,7 @@ class Enotify {
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if it's a post figure out who's post it is.
|
||||
|
||||
@@ -219,7 +219,7 @@ class Enotify {
|
||||
$itemlink,
|
||||
$p[0]['author']['xchan_name'],
|
||||
$item_post_type);
|
||||
|
||||
|
||||
// "your post"
|
||||
if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
|
||||
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
|
||||
@@ -230,15 +230,15 @@ class Enotify {
|
||||
|
||||
// Some mail softwares relies on subject field for threading.
|
||||
// So, we cannot have different subjects for notifications of the same thread.
|
||||
// Before this we have the name of the replier on the subject rendering
|
||||
// Before this we have the name of the replier on the subject rendering
|
||||
// differents subjects for messages on the same thread.
|
||||
|
||||
if($moderated)
|
||||
$subject = sprintf( t('[$Projectname:Notify] Moderated Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
else
|
||||
$subject = sprintf( t('[$Projectname:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
$preamble = sprintf( t('%1$s commented on an item/conversation you have been following.'), $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
@@ -247,7 +247,7 @@ class Enotify {
|
||||
$tsitelink .= "\n\n" . sprintf( t('Please visit %s to approve or reject this comment.'), z_root() . '/moderate' );
|
||||
$hsitelink .= "<br><br>" . sprintf( t('Please visit %s to approve or reject this comment.'), '<a href="' . z_root() . '/moderate">' . z_root() . '/moderate</a>' );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ($params['type'] == NOTIFY_LIKE) {
|
||||
@@ -278,7 +278,7 @@ class Enotify {
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if it's a post figure out who's post it is.
|
||||
|
||||
@@ -314,12 +314,12 @@ class Enotify {
|
||||
|
||||
// Some mail softwares relies on subject field for threading.
|
||||
// So, we cannot have different subjects for notifications of the same thread.
|
||||
// Before this we have the name of the replier on the subject rendering
|
||||
// Before this we have the name of the replier on the subject rendering
|
||||
// differents subjects for messages on the same thread.
|
||||
|
||||
$subject = sprintf( t('[$Projectname:Notify] Like received to conversation #%1$d by %2$s'), $parent_id, $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
$preamble = sprintf( t('%1$s liked an item/conversation you created.'), $sender['xchan_name']);
|
||||
$epreamble = $dest_str;
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
@@ -335,7 +335,7 @@ class Enotify {
|
||||
|
||||
$epreamble = sprintf( t('%1$s posted to [zrl=%2$s]your wall[/zrl]') ,
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$params['link']);
|
||||
$params['link']);
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
@@ -355,12 +355,12 @@ class Enotify {
|
||||
pop_lang();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$subject = sprintf( t('[$Projectname:Notify] %s tagged you') , $sender['xchan_name']);
|
||||
$preamble = sprintf( t('%1$s tagged you at %2$s') , $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('%1$s [zrl=%2$s]tagged you[/zrl].') ,
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$params['link']);
|
||||
$params['link']);
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
@@ -373,7 +373,7 @@ class Enotify {
|
||||
$preamble = sprintf( t('%1$s poked you at %2$s') , $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('%1$s [zrl=%2$s]poked you[/zrl].') ,
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$params['link']);
|
||||
$params['link']);
|
||||
|
||||
$subject = str_replace('poked', t($params['activity']), $subject);
|
||||
$preamble = str_replace('poked', t($params['activity']), $preamble);
|
||||
@@ -390,7 +390,7 @@ class Enotify {
|
||||
$preamble = sprintf( t('%1$s tagged your post at %2$s'),$sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('%1$s tagged [zrl=%2$s]your post[/zrl]') ,
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
|
||||
$itemlink);
|
||||
$itemlink);
|
||||
|
||||
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
|
||||
$tsitelink = sprintf( $sitelink, $siteurl );
|
||||
@@ -400,10 +400,10 @@ class Enotify {
|
||||
|
||||
if ($params['type'] == NOTIFY_INTRO) {
|
||||
$subject = sprintf( t('[$Projectname:Notify] Introduction received'));
|
||||
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a new connection request[/zrl] from %2$s.'),
|
||||
$siteurl . '/connections/ifpending',
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
|
||||
$body = sprintf( t('You may visit their profile at %s'),$sender['xchan_url']);
|
||||
|
||||
$sitelink = t('Please visit %s to approve or reject the connection request.');
|
||||
@@ -414,11 +414,11 @@ class Enotify {
|
||||
|
||||
if ($params['type'] == NOTIFY_SUGGEST) {
|
||||
$subject = sprintf( t('[$Projectname:Notify] Friend suggestion received'));
|
||||
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
|
||||
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a friend suggestion[/zrl] for %2$s from %3$s.'),
|
||||
$itemlink,
|
||||
'[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]',
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
|
||||
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
|
||||
|
||||
$body = t('Name:') . ' ' . $params['item']['name'] . "\n";
|
||||
$body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
|
||||
@@ -462,7 +462,7 @@ class Enotify {
|
||||
$sitelink = $h['sitelink'];
|
||||
$tsitelink = $h['tsitelink'];
|
||||
$hsitelink = $h['hsitelink'];
|
||||
$itemlink = $h['itemlink'];
|
||||
$itemlink = $h['itemlink'];
|
||||
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
@@ -510,7 +510,7 @@ class Enotify {
|
||||
// Mark some notifications as seen right away
|
||||
// Note! The notification have to be created, because they are used to send emails
|
||||
// So easiest solution to hide them from Notices is to mark them as seen right away.
|
||||
// Another option would be to not add them to the DB, and change how emails are handled
|
||||
// Another option would be to not add them to the DB, and change how emails are handled
|
||||
// (probably would be better that way)
|
||||
|
||||
if (!$always_show_in_notices) {
|
||||
@@ -555,7 +555,7 @@ class Enotify {
|
||||
// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
|
||||
|
||||
if ((\App::$language === 'en' || (! \App::$language)) && strpos($msg,', '))
|
||||
$msg = substr($msg,strpos($msg,', ')+1);
|
||||
$msg = substr($msg,strpos($msg,', ')+1);
|
||||
|
||||
$datarray['id'] = $notify_id;
|
||||
$datarray['msg'] = $msg;
|
||||
@@ -587,12 +587,12 @@ class Enotify {
|
||||
$htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)));
|
||||
|
||||
|
||||
// use $_SESSION['zid_override'] to force zid() to use
|
||||
// use $_SESSION['zid_override'] to force zid() to use
|
||||
// the recipient address instead of the current observer
|
||||
|
||||
$_SESSION['zid_override'] = channel_reddress($recip);
|
||||
$_SESSION['zrl_override'] = z_root() . '/channel/' . $recip['channel_address'];
|
||||
|
||||
|
||||
$textversion = zidify_links($textversion);
|
||||
$htmlversion = zidify_links($htmlversion);
|
||||
|
||||
@@ -754,7 +754,7 @@ class Enotify {
|
||||
return $params['result'];
|
||||
}
|
||||
|
||||
$fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
|
||||
$fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
|
||||
$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
|
||||
|
||||
// generate a mime boundary
|
||||
@@ -767,8 +767,8 @@ class Enotify {
|
||||
$messageHeader =
|
||||
$params['additionalMailHeader'] .
|
||||
"From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
|
||||
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
|
||||
"MIME-Version: 1.0" . PHP_EOL .
|
||||
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
|
||||
"MIME-Version: 1.0" . PHP_EOL .
|
||||
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
|
||||
|
||||
// assemble the final multipart message body with the text and html types included
|
||||
@@ -782,7 +782,7 @@ class Enotify {
|
||||
$textBody . PHP_EOL .
|
||||
"--" . $mimeBoundary . PHP_EOL . // text/html section
|
||||
"Content-Type: text/html; charset=UTF-8" . PHP_EOL .
|
||||
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
|
||||
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
|
||||
$htmlBody . PHP_EOL .
|
||||
"--" . $mimeBoundary . "--" . PHP_EOL; // message ending
|
||||
|
||||
@@ -803,7 +803,7 @@ class Enotify {
|
||||
|
||||
require_once('include/conversation.php');
|
||||
|
||||
// Call localize_item to get a one line status for activities.
|
||||
// Call localize_item to get a one line status for activities.
|
||||
// This should set $item['localized'] to indicate we have a brief summary.
|
||||
// and perhaps $item['shortlocalized'] for an even briefer summary
|
||||
|
||||
@@ -860,7 +860,7 @@ class Enotify {
|
||||
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => bbcode(escape_tags($itemem_text)),
|
||||
'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_COMPAT, 'UTF-8', false),
|
||||
'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_QUOTES, 'UTF-8', false),
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'uid' => $item['uid'],
|
||||
|
||||
@@ -40,15 +40,15 @@ class JSalmon {
|
||||
$ret = [ 'results' => [] ];
|
||||
|
||||
if(! is_array($x)) {
|
||||
return $false;
|
||||
return false;
|
||||
}
|
||||
if(! ( array_key_exists('signed',$x) && $x['signed'])) {
|
||||
return $false;
|
||||
return false;
|
||||
}
|
||||
|
||||
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
|
||||
. base64url_encode($x['data_type'],true) . '.'
|
||||
. base64url_encode($x['encoding'],true) . '.'
|
||||
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
|
||||
. base64url_encode($x['data_type'],true) . '.'
|
||||
. base64url_encode($x['encoding'],true) . '.'
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
|
||||
|
||||
@@ -42,7 +42,7 @@ class Libsync {
|
||||
|
||||
$channel = $r[0];
|
||||
|
||||
// don't provide these in the export
|
||||
// don't provide these in the export
|
||||
|
||||
unset($channel['channel_active']);
|
||||
unset($channel['channel_password']);
|
||||
@@ -245,7 +245,7 @@ class Libsync {
|
||||
|
||||
if(array_key_exists('app',$arr) && $arr['app'])
|
||||
sync_apps($channel,$arr['app']);
|
||||
|
||||
|
||||
if(array_key_exists('addressbook',$arr) && $arr['addressbook'])
|
||||
sync_addressbook($channel,$arr['addressbook']);
|
||||
|
||||
@@ -260,7 +260,7 @@ class Libsync {
|
||||
|
||||
if(array_key_exists('mail',$arr) && $arr['mail'])
|
||||
sync_mail($channel,$arr['mail']);
|
||||
|
||||
|
||||
if(array_key_exists('event',$arr) && $arr['event'])
|
||||
sync_events($channel,$arr['event']);
|
||||
|
||||
@@ -269,7 +269,7 @@ class Libsync {
|
||||
|
||||
if(array_key_exists('item',$arr) && $arr['item'])
|
||||
sync_items($channel,$arr['item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
|
||||
|
||||
|
||||
// deprecated, maintaining for a few months for upward compatibility
|
||||
// this should sync webpages, but the logic is a bit subtle
|
||||
|
||||
@@ -278,7 +278,7 @@ class Libsync {
|
||||
|
||||
if(array_key_exists('menu',$arr) && $arr['menu'])
|
||||
sync_menus($channel,$arr['menu']);
|
||||
|
||||
|
||||
if(array_key_exists('file',$arr) && $arr['file'])
|
||||
sync_files($channel,$arr['file']);
|
||||
|
||||
@@ -293,7 +293,7 @@ class Libsync {
|
||||
if(array_key_exists('channel_pageflags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
|
||||
|
||||
// Several pageflags are site-specific and cannot be sync'd.
|
||||
// Only allow those bits which are shareable from the remote and then
|
||||
// Only allow those bits which are shareable from the remote and then
|
||||
// logically OR with the local flags
|
||||
|
||||
$arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] & (PAGE_HIDDEN|PAGE_AUTOCONNECT|PAGE_APPLICATION|PAGE_PREMIUM|PAGE_ADULT);
|
||||
@@ -562,7 +562,7 @@ class Libsync {
|
||||
// our group list is already synchronised
|
||||
if($x) {
|
||||
foreach($x as $y) {
|
||||
|
||||
|
||||
// for each group, loop on members list we just received
|
||||
if(isset($y['hash']) && isset($members[$y['hash']])) {
|
||||
foreach($members[$y['hash']] as $member) {
|
||||
@@ -574,9 +574,9 @@ class Libsync {
|
||||
);
|
||||
if($z)
|
||||
$found = true;
|
||||
|
||||
|
||||
// if somebody is in the group that wasn't before - add them
|
||||
|
||||
|
||||
if(! $found) {
|
||||
q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
@@ -587,7 +587,7 @@ class Libsync {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now retrieve a list of members we have on this site
|
||||
$m = q("select xchan from pgrp_member where gid = %d and uid = %d",
|
||||
intval($y['id']),
|
||||
@@ -615,7 +615,7 @@ class Libsync {
|
||||
$disallowed = array('id','aid','uid','guid');
|
||||
|
||||
foreach($arr['profile'] as $profile) {
|
||||
|
||||
|
||||
$x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1",
|
||||
dbesc($profile['profile_guid']),
|
||||
intval($channel['channel_id'])
|
||||
@@ -628,7 +628,7 @@ class Libsync {
|
||||
'profile_guid' => $profile['profile_guid'],
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1",
|
||||
dbesc($profile['profile_guid']),
|
||||
intval($channel['channel_id'])
|
||||
@@ -713,7 +713,7 @@ class Libsync {
|
||||
if($arr['locations']) {
|
||||
|
||||
if($absolute)
|
||||
self::check_location_move($sender['hash'],$arr['locations']);
|
||||
Libzot::check_location_move($sender['hash'],$arr['locations']);
|
||||
|
||||
$xisting = q("select * from hubloc where hubloc_hash = '%s'",
|
||||
dbesc($sender['hash'])
|
||||
@@ -775,14 +775,14 @@ class Libsync {
|
||||
);
|
||||
if($r) {
|
||||
logger('Hub exists: ' . $location['url'], LOGGER_DEBUG);
|
||||
|
||||
|
||||
// update connection timestamp if this is the site we're talking to
|
||||
// This only happens when called from import_xchan
|
||||
|
||||
$current_site = false;
|
||||
|
||||
$t = datetime_convert('UTC','UTC','now - 15 minutes');
|
||||
|
||||
|
||||
if(array_key_exists('site',$arr) && $location['url'] == $arr['site']['url']) {
|
||||
q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d and hubloc_connected < '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
@@ -903,12 +903,14 @@ class Libsync {
|
||||
$changed = true;
|
||||
|
||||
if($location['primary']) {
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_sitekey = '%s' limit 1",
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_sitekey = '%s'",
|
||||
dbesc($location['address']),
|
||||
dbesc($location['sitekey'])
|
||||
);
|
||||
if($r)
|
||||
hubloc_change_primary($r[0]);
|
||||
if($r) {
|
||||
$r = Libzot::zot_record_preferred($r);
|
||||
hubloc_change_primary($r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ class Libzot {
|
||||
|
||||
if($new_connection) {
|
||||
if(! Permissions::PermsCompare($new_perms,$previous_perms))
|
||||
Master::Summon([ 'Notifier', 'permissions_create', $new_connection[0]['abook_id'] ]);
|
||||
Master::Summon([ 'Notifier', 'permission_create', $new_connection[0]['abook_id'] ]);
|
||||
Enotify::submit(
|
||||
[
|
||||
'type' => NOTIFY_INTRO,
|
||||
@@ -1489,9 +1489,9 @@ class Libzot {
|
||||
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
|
||||
if(($act) && ($act->obj) && (! is_array($act->obj))) {
|
||||
// The initial object fetch failed using the sys channel credentials.
|
||||
// The initial object fetch failed using the sys channel credentials.
|
||||
// Try again using the delivery channel credentials.
|
||||
// We will also need to re-parse the $item array,
|
||||
// We will also need to re-parse the $item array,
|
||||
// but preserve any values that were set during anonymous parsing.
|
||||
|
||||
$o = Activity::fetch($act->obj,$channel);
|
||||
@@ -1505,7 +1505,7 @@ class Libzot {
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to block normal top-level message delivery from our clones, as the delivered
|
||||
@@ -1634,7 +1634,7 @@ class Libzot {
|
||||
// have the copy and we don't want the request to loop.
|
||||
// Also don't do this if this comment came from a conversation request packet.
|
||||
// It's possible that comments are allowed but posting isn't and that could
|
||||
// cause a conversation fetch loop.
|
||||
// cause a conversation fetch loop.
|
||||
// We'll also check the send_stream permission - because if it isn't allowed,
|
||||
// the top level post is unlikely to be imported and
|
||||
// this is just an exercise in futility.
|
||||
@@ -2295,7 +2295,7 @@ class Libzot {
|
||||
*
|
||||
* @see import_directory_profile()
|
||||
*
|
||||
* @param string $sender
|
||||
* @param string $sender
|
||||
* @param array $arr
|
||||
* @param array $deliveries (unused)
|
||||
* @return void
|
||||
@@ -2316,7 +2316,7 @@ class Libzot {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $sender
|
||||
* @param string $sender
|
||||
* @param array $arr
|
||||
* @param array $deliveries (unused) deliveries is irrelevant
|
||||
* @return void
|
||||
|
||||
@@ -19,7 +19,6 @@ class Libzotdir {
|
||||
*/
|
||||
|
||||
static function find_upstream_directory($dirmode) {
|
||||
global $DIRECTORY_FALLBACK_SERVERS;
|
||||
|
||||
$preferred = get_config('system','directory_server');
|
||||
|
||||
@@ -31,7 +30,7 @@ class Libzotdir {
|
||||
);
|
||||
if(($r) && ($r[0]['site_flags'] & DIRECTORY_MODE_STANDALONE)) {
|
||||
$preferred = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,19 +41,21 @@ class Libzotdir {
|
||||
* from our list of directory servers. However, if we're a directory
|
||||
* server ourself, point at the local instance
|
||||
* We will then set this value so this should only ever happen once.
|
||||
* Ideally there will be an admin setting to change to a different
|
||||
* Ideally there will be an admin setting to change to a different
|
||||
* directory server if you don't like our choice or if circumstances change.
|
||||
*/
|
||||
|
||||
$directory_fallback_servers = get_directory_fallback_servers();
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
if ($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
$toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS));
|
||||
$preferred = $DIRECTORY_FALLBACK_SERVERS[$toss];
|
||||
$toss = mt_rand(0,count($directory_fallback_servers));
|
||||
$preferred = $directory_fallback_servers[$toss];
|
||||
if(! $preferred) {
|
||||
$preferred = DIRECTORY_FALLBACK_MASTER;
|
||||
}
|
||||
set_config('system','directory_server',$preferred);
|
||||
}
|
||||
}
|
||||
else {
|
||||
set_config('system','directory_server',z_root());
|
||||
}
|
||||
@@ -108,7 +109,7 @@ class Libzotdir {
|
||||
$ret = get_config('directory', $setting);
|
||||
|
||||
|
||||
// 'safemode' is the default if there is no observer or no established preference.
|
||||
// 'safemode' is the default if there is no observer or no established preference.
|
||||
|
||||
if($setting === 'safemode' && $ret === false)
|
||||
$ret = 1;
|
||||
@@ -175,8 +176,8 @@ class Libzotdir {
|
||||
*
|
||||
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
|
||||
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
|
||||
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||
* directly if the rater's signature matches.
|
||||
*
|
||||
* @param int $dirmode;
|
||||
@@ -188,16 +189,17 @@ class Libzotdir {
|
||||
return;
|
||||
|
||||
$realm = get_directory_realm();
|
||||
|
||||
if ($realm == DIRECTORY_REALM) {
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') ",
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') and site_dead = 0",
|
||||
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
|
||||
dbesc(z_root()),
|
||||
intval(SITE_TYPE_ZOT),
|
||||
dbesc($realm)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d ",
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d and site_dead = 0",
|
||||
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
|
||||
dbesc(z_root()),
|
||||
dbesc(protect_sprintf('%' . $realm . '%')),
|
||||
@@ -205,6 +207,8 @@ class Libzotdir {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If there are no directory servers, setup the fallback master
|
||||
/** @FIXME What to do if we're in a different realm? */
|
||||
|
||||
@@ -214,14 +218,14 @@ class Libzotdir {
|
||||
[
|
||||
'site_url' => DIRECTORY_FALLBACK_MASTER,
|
||||
'site_flags' => DIRECTORY_MODE_PRIMARY,
|
||||
'site_update' => NULL_DATE,
|
||||
'site_update' => NULL_DATE,
|
||||
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
|
||||
'site_realm' => DIRECTORY_REALM,
|
||||
'site_valid' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ",
|
||||
$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d and site_dead = 0",
|
||||
intval(DIRECTORY_MODE_PRIMARY),
|
||||
intval(DIRECTORY_MODE_SECONDARY),
|
||||
dbesc(z_root()),
|
||||
@@ -245,7 +249,6 @@ class Libzotdir {
|
||||
|
||||
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
|
||||
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
|
||||
|
||||
if (! $x['success'])
|
||||
continue;
|
||||
|
||||
@@ -273,7 +276,7 @@ class Libzotdir {
|
||||
$ud_flags |= UPDATE_FLAGS_DELETED;
|
||||
if (is_array($t['flags']) && in_array('forced',$t['flags']))
|
||||
$ud_flags |= UPDATE_FLAGS_FORCED;
|
||||
|
||||
|
||||
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
|
||||
values ( '%s', '%s', '%s', %d, '%s' ) ",
|
||||
dbesc($t['hash']),
|
||||
@@ -338,7 +341,7 @@ class Libzotdir {
|
||||
|
||||
static function local_dir_update($uid, $force) {
|
||||
|
||||
|
||||
|
||||
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$p = q("select channel.channel_hash, channel_address, channel_timezone, channel_portable_id, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||
@@ -354,7 +357,7 @@ class Libzotdir {
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
@@ -415,7 +418,7 @@ class Libzotdir {
|
||||
dbesc($legacy_hash)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$ud_hash = random_string() . '@' . \App::get_hostname();
|
||||
@@ -446,7 +449,7 @@ class Libzotdir {
|
||||
$arr['xprof_hash'] = $hash;
|
||||
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
|
||||
$arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
|
||||
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
@@ -641,7 +644,7 @@ class Libzotdir {
|
||||
dbesc(datetime_convert()),
|
||||
intval($flags),
|
||||
dbesc($addr)
|
||||
);
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
|
||||
|
||||
@@ -9,7 +9,7 @@ define ( 'NWIKI_ITEM_RESOURCE_TYPE', 'nwiki' );
|
||||
class NativeWiki {
|
||||
|
||||
|
||||
static public function listwikis($channel, $observer_hash) {
|
||||
public static function listwikis($channel, $observer_hash) {
|
||||
|
||||
$sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
|
||||
$wikis = q("SELECT * FROM item
|
||||
@@ -40,7 +40,7 @@ class NativeWiki {
|
||||
}
|
||||
|
||||
|
||||
function create_wiki($channel, $observer_hash, $wiki, $acl) {
|
||||
public static function create_wiki($channel, $observer_hash, $wiki, $acl) {
|
||||
|
||||
$resource_id = new_uuid();
|
||||
$uuid = new_uuid();
|
||||
@@ -101,7 +101,7 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
function update_wiki($channel_id, $observer_hash, $arr, $acl) {
|
||||
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'];
|
||||
@@ -156,7 +156,7 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
static public function sync_a_wiki_item($uid,$id,$resource_id) {
|
||||
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' )) ",
|
||||
@@ -185,7 +185,7 @@ class NativeWiki {
|
||||
}
|
||||
}
|
||||
|
||||
function delete_wiki($channel_id,$observer_hash,$resource_id) {
|
||||
public static function delete_wiki($channel_id,$observer_hash,$resource_id) {
|
||||
|
||||
$w = self::get_wiki($channel_id,$observer_hash,$resource_id);
|
||||
$item = $w['wiki'];
|
||||
@@ -202,7 +202,7 @@ class NativeWiki {
|
||||
}
|
||||
|
||||
|
||||
static public function get_wiki($channel_id, $observer_hash, $resource_id) {
|
||||
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
|
||||
|
||||
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
|
||||
|
||||
@@ -236,7 +236,7 @@ class NativeWiki {
|
||||
}
|
||||
|
||||
|
||||
static public function exists_by_name($uid, $urlName) {
|
||||
public static function exists_by_name($uid, $urlName) {
|
||||
|
||||
$sql_extra = item_permissions_sql($uid);
|
||||
|
||||
@@ -258,7 +258,7 @@ class NativeWiki {
|
||||
}
|
||||
|
||||
|
||||
static public function get_permissions($resource_id, $owner_id, $observer_hash) {
|
||||
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);
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/group.php';
|
||||
|
||||
@@ -46,20 +48,20 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
|
||||
// 'x' => nav search bar autocomplete (match any xchan)
|
||||
// $_REQUEST['query'] contains autocomplete search text.
|
||||
|
||||
// List of channels whose connections to also suggest,
|
||||
|
||||
// List of channels whose connections to also suggest,
|
||||
// e.g. currently viewed channel or channels mentioned in a post
|
||||
|
||||
$extra_channels = (x($_REQUEST,'extra_channels') ? $_REQUEST['extra_channels'] : array());
|
||||
|
||||
|
||||
// The different autocomplete libraries use different names for the search text
|
||||
// parameter. Internally we'll use $search to represent the search text no matter
|
||||
// what request variable it was attached to.
|
||||
|
||||
// what request variable it was attached to.
|
||||
|
||||
if(array_key_exists('query',$_REQUEST)) {
|
||||
$search = $_REQUEST['query'];
|
||||
}
|
||||
|
||||
|
||||
if( (! local_channel()) && (! in_array($type, [ 'x', 'c', 'f' ])))
|
||||
killme();
|
||||
|
||||
@@ -68,7 +70,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
if(in_array($type, [ 'm', 'a', 'c', 'f' ])) {
|
||||
|
||||
// These queries require permission checking. We'll create a simple array of xchan_hash for those with
|
||||
// the requisite permissions which we can check against.
|
||||
// the requisite permissions which we can check against.
|
||||
|
||||
$x = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = '%s' and v = '1'",
|
||||
intval(local_channel()),
|
||||
@@ -85,34 +87,34 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
|
||||
$sql_extra2_xchan = "AND ( xchan_name LIKE " . protect_sprintf( "'" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
|
||||
|
||||
// This horrible mess is needed because position also returns 0 if nothing is found.
|
||||
// This horrible mess is needed because position also returns 0 if nothing is found.
|
||||
// Would be MUCH easier if it instead returned a very large value
|
||||
// Otherwise we could just
|
||||
// Otherwise we could just
|
||||
// order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
|
||||
|
||||
$order_extra2 = "CASE WHEN xchan_name LIKE "
|
||||
. protect_sprintf( "'%" . dbesc($search) . "%'" )
|
||||
. " then POSITION('" . protect_sprintf(dbesc($search))
|
||||
$order_extra2 = "CASE WHEN xchan_name LIKE "
|
||||
. protect_sprintf( "'%" . dbesc($search) . "%'" )
|
||||
. " then POSITION('" . protect_sprintf(dbesc($search))
|
||||
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
|
||||
|
||||
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) ";
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
$sql_extra = $sql_extra2 = $sql_extra3 = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$groups = array();
|
||||
$contacts = array();
|
||||
|
||||
|
||||
if($type == '' || $type == 'g') {
|
||||
|
||||
// virtual groups based on private profile viewing ability
|
||||
|
||||
$r = q("select id, profile_guid, profile_name from profile where is_default = 0 and uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$groups[] = array(
|
||||
@@ -130,19 +132,19 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
// Normal privacy groups
|
||||
|
||||
$r = q("SELECT pgrp.id, pgrp.hash, pgrp.gname
|
||||
FROM pgrp, pgrp_member
|
||||
WHERE pgrp.deleted = 0 AND pgrp.uid = %d
|
||||
FROM pgrp, pgrp_member
|
||||
WHERE pgrp.deleted = 0 AND pgrp.uid = %d
|
||||
AND pgrp_member.gid = pgrp.id
|
||||
$sql_extra
|
||||
GROUP BY pgrp.id
|
||||
ORDER BY pgrp.gname
|
||||
ORDER BY pgrp.gname
|
||||
LIMIT %d OFFSET %d",
|
||||
intval(local_channel()),
|
||||
intval($count),
|
||||
intval($start)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
if($r) {
|
||||
foreach($r as $g){
|
||||
// logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
|
||||
$groups[] = array(
|
||||
@@ -157,10 +159,10 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($type == '' || $type == 'c' || $type === 'f') {
|
||||
|
||||
$extra_channels_sql = '';
|
||||
$extra_channels_sql = '';
|
||||
|
||||
// Only include channels who allow the observer to view their connections
|
||||
if($extra_channels) {
|
||||
@@ -172,7 +174,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Getting info from the abook is better for local users because it contains info about permissions
|
||||
if(local_channel()) {
|
||||
if($extra_channels_sql != '')
|
||||
@@ -199,7 +201,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
$r2 = array();
|
||||
foreach($r1 as $rr) {
|
||||
$x = atoken_xchan($rr);
|
||||
$r2[] = [
|
||||
$r2[] = [
|
||||
'id' => 'a' . $rr['atoken_id'] ,
|
||||
'hash' => $x['xchan_hash'],
|
||||
'name' => $x['xchan_name'],
|
||||
@@ -211,12 +213,12 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
'abook_self' => 0
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add connections
|
||||
|
||||
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, xchan_pubforum, abook_flags, abook_self
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
|
||||
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, xchan_pubforum, abook_flags, abook_self
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE (abook_channel = %d $extra_channels_sql) AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
|
||||
intval(local_channel())
|
||||
);
|
||||
@@ -225,28 +227,28 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
else { // Visitors
|
||||
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
||||
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
||||
FROM xchan left join xlink on xlink_link = xchan_hash
|
||||
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2_xchan order by $order_extra2 xchan_name asc" ,
|
||||
dbesc(get_observer_hash())
|
||||
);
|
||||
|
||||
|
||||
// Find contacts of extra channels
|
||||
// This is probably more complicated than it needs to be
|
||||
if($extra_channels_sql) {
|
||||
// Build a list of hashes that we got previously so we don't get them again
|
||||
$known_hashes = array("'".get_observer_hash()."'");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$known_hashes[] = "'".$rr['hash']."'";
|
||||
$known_hashes_sql = 'AND xchan_hash not in ('.join(',',$known_hashes).')';
|
||||
|
||||
$r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
|
||||
$r2 = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, abook_their_perms, abook_flags, abook_self
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel IN ($extra_channels_sql) $known_hashes_sql AND abook_blocked = 0 and abook_pending = 0 and abook_hidden = 0 and xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc");
|
||||
if($r2)
|
||||
$r = array_merge($r,$r2);
|
||||
|
||||
|
||||
// Sort accoring to match position, then alphabetically. This could be avoided if the above two SQL queries could be combined into one, and the sorting could be done on the SQl server (like in the case of a local user)
|
||||
$matchpos = function($x) use($search) {
|
||||
$namepos = strpos($x['name'],$search);
|
||||
@@ -269,22 +271,22 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
if((count($r) < 100) && $type == 'c') {
|
||||
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
||||
FROM xchan
|
||||
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
||||
FROM xchan
|
||||
WHERE xchan_deleted = 0 and not xchan_network in ('rss','anon','unknown') $sql_extra2_xchan order by $order_extra2 xchan_name asc"
|
||||
);
|
||||
if($r2) {
|
||||
$r = array_merge($r,$r2);
|
||||
$r = unique_multidim_array($r,'hash');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($type == 'm') {
|
||||
|
||||
$r = array();
|
||||
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
|
||||
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d
|
||||
WHERE abook_channel = %d
|
||||
and xchan_deleted = 0
|
||||
and xchan_network IN ('zot', 'diaspora', 'friendica-over-diaspora')
|
||||
$sql_extra3
|
||||
@@ -298,18 +300,18 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
elseif($type == 'a') {
|
||||
|
||||
$r = q("SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
|
||||
$r = q("SELECT abook_id as id, xchan_name as name, xchan_network as net, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d
|
||||
and xchan_deleted = 0
|
||||
$sql_extra3
|
||||
ORDER BY xchan_name ASC ",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
elseif($type == 'x') {
|
||||
$r = $this->navbar_complete($a);
|
||||
@@ -323,7 +325,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$o = array(
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
@@ -334,27 +336,34 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else
|
||||
$r = array();
|
||||
|
||||
|
||||
if($r) {
|
||||
$i = count($contacts);
|
||||
$x = [];
|
||||
foreach($r as $g) {
|
||||
|
||||
if(in_array($g['network'],['rss','anon','unknown']) && ($type != 'a'))
|
||||
|
||||
if(in_array($g['net'],['rss','anon','unknown']) && ($type != 'a'))
|
||||
continue;
|
||||
|
||||
$g['hash'] = urlencode($g['hash']);
|
||||
|
||||
|
||||
if(! $g['nick']) {
|
||||
$g['nick'] = $g['url'];
|
||||
}
|
||||
|
||||
$clink = ($g['nick']) ? $g['nick'] : $g['url'];
|
||||
$lkey = md5($clink);
|
||||
if (! array_key_exists($lkey, $x))
|
||||
$x[$lkey] = $i;
|
||||
|
||||
if(in_array($g['hash'],$permitted) && $type === 'f' && (! $noforums)) {
|
||||
$contacts[] = array(
|
||||
$contacts[$i] = array(
|
||||
"type" => "c",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
|
||||
"link" => $clink,
|
||||
"nick" => substr($g['nick'],0,strpos($g['nick'],'@')),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => 'taggable',
|
||||
@@ -362,24 +371,28 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
}
|
||||
if($type !== 'f') {
|
||||
$contacts[] = array(
|
||||
"type" => "c",
|
||||
"photo" => $g['micro'],
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
|
||||
"nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => '',
|
||||
"label" => '',
|
||||
);
|
||||
if (! array_key_exists($x[$lkey], $contacts) || ($contacts[$x[$lkey]]['net'] !== 'zot6' && ($g['net'] == 'zot6' || $g['net'] == 'zot'))) {
|
||||
$contacts[$x[$lkey]] = array(
|
||||
"type" => "c",
|
||||
"photo" => $g['micro'],
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => $clink,
|
||||
"nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => '',
|
||||
"label" => '',
|
||||
"net" => $g['net']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$items = array_merge($groups, $contacts);
|
||||
|
||||
|
||||
$o = array(
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
@@ -393,50 +406,50 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
function navbar_complete(&$a) {
|
||||
|
||||
|
||||
// logger('navbar_complete');
|
||||
|
||||
|
||||
if(observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
$search = ((x($_REQUEST,'search')) ? htmlentities($_REQUEST['search'],ENT_COMPAT,'UTF-8',false) : '');
|
||||
if(! $search || mb_strlen($search) < 2)
|
||||
return array();
|
||||
|
||||
|
||||
$star = false;
|
||||
$address = false;
|
||||
|
||||
|
||||
if(substr($search,0,1) === '@')
|
||||
$search = substr($search,1);
|
||||
|
||||
|
||||
if(substr($search,0,1) === '*') {
|
||||
$star = true;
|
||||
$search = substr($search,1);
|
||||
}
|
||||
|
||||
|
||||
if(strpos($search,'@') !== false) {
|
||||
$address = true;
|
||||
}
|
||||
|
||||
|
||||
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
$url = z_root() . '/dirsearch';
|
||||
}
|
||||
|
||||
|
||||
if(! $url) {
|
||||
require_once("include/dir_fns.php");
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
$directory = Libzotdir::find_upstream_directory($dirmode);
|
||||
$url = $directory['url'] . '/dirsearch';
|
||||
}
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
|
||||
|
||||
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
|
||||
if($url) {
|
||||
$query = $url . '?f=' . (($token) ? '&t=' . urlencode($token) : '');
|
||||
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');
|
||||
|
||||
|
||||
$x = z_fetch_url($query);
|
||||
if($x['success']) {
|
||||
$t = 0;
|
||||
|
||||
@@ -1,61 +1,187 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use ZipArchive;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Verify;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/attach.php');
|
||||
|
||||
class Attach extends Controller {
|
||||
|
||||
class Attach extends \Zotlabs\Web\Controller {
|
||||
function post() {
|
||||
|
||||
$attach_ids = ((x($_REQUEST, 'attach_ids')) ? $_REQUEST['attach_ids'] : []);
|
||||
$attach_path = ((x($_REQUEST, 'attach_path')) ? $_REQUEST['attach_path'] : '');
|
||||
$channel_id = ((x($_REQUEST, 'channel_id')) ? intval($_REQUEST['channel_id']) : 0);
|
||||
$channel = channelx_by_n($channel_id);
|
||||
|
||||
if (! $channel) {
|
||||
notice(t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$strip_str = '/cloud/' . $channel['channel_address'] . '/';
|
||||
$count = strlen($strip_str);
|
||||
$attach_path = substr($attach_path, $count);
|
||||
|
||||
if ($attach_ids) {
|
||||
|
||||
$zip_dir = 'store/[data]/' . $channel['channel_address'] . '/tmp';
|
||||
if (! is_dir($zip_dir))
|
||||
mkdir($zip_dir, STORAGE_DEFAULT_PERMISSIONS, true);
|
||||
|
||||
$token = random_string(32);
|
||||
|
||||
$zip_file = 'download_' . $token . '.zip';
|
||||
$zip_path = $zip_dir . '/' . $zip_file;
|
||||
|
||||
$zip = new ZipArchive();
|
||||
|
||||
if ($zip->open($zip_path, ZipArchive::CREATE) === true) {
|
||||
|
||||
$zip_filename = self::zip_archive_handler($zip, $attach_ids, $attach_path);
|
||||
|
||||
$zip->close();
|
||||
|
||||
$meta = [
|
||||
'zip_filename' => $zip_filename,
|
||||
'zip_path' => $zip_path
|
||||
];
|
||||
|
||||
Verify::create('zip_token', 0, $token, json_encode($meta));
|
||||
|
||||
json_return_and_die([
|
||||
'success' => true,
|
||||
'token' => $token
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
function init() {
|
||||
|
||||
if(argc() < 2) {
|
||||
notice( t('Item not available.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$token = ((x($_REQUEST, 'token')) ? $_REQUEST['token'] : '');
|
||||
|
||||
if(argv(1) === 'download') {
|
||||
$meta = Verify::get_meta('zip_token', 0, $token);
|
||||
|
||||
if(! $meta)
|
||||
killme();
|
||||
|
||||
$meta = json_decode($meta, true);
|
||||
|
||||
header('Content-Type: application/zip');
|
||||
header('Content-Disposition: attachment; filename="'. $meta['zip_filename'] . '"');
|
||||
header('Content-Length: ' . filesize($meta['zip_path']));
|
||||
|
||||
$istream = fopen($meta['zip_path'], 'rb');
|
||||
$ostream = fopen('php://output', 'wb');
|
||||
if($istream && $ostream) {
|
||||
pipe_streams($istream, $ostream);
|
||||
fclose($istream);
|
||||
fclose($ostream);
|
||||
}
|
||||
|
||||
unlink($meta['zip_path']);
|
||||
killme();
|
||||
}
|
||||
|
||||
$r = attach_by_hash(argv(1),get_observer_hash(),((argc() > 2) ? intval(argv(2)) : 0));
|
||||
|
||||
|
||||
if(! $r['success']) {
|
||||
notice( $r['message'] . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$c = q("select channel_address from channel where channel_id = %d limit 1",
|
||||
intval($r['data']['uid'])
|
||||
);
|
||||
|
||||
|
||||
if(! $c)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
$unsafe_types = array('text/html','text/css','application/javascript');
|
||||
|
||||
|
||||
if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($r['data']['uid']))) {
|
||||
header('Content-type: text/plain');
|
||||
header('Content-Type: text/plain');
|
||||
}
|
||||
else {
|
||||
header('Content-type: ' . $r['data']['filetype']);
|
||||
header('Content-Type: ' . $r['data']['filetype']);
|
||||
}
|
||||
|
||||
header('Content-disposition: attachment; filename="' . $r['data']['filename'] . '"');
|
||||
|
||||
header('Content-Disposition: attachment; filename="' . $r['data']['filename'] . '"');
|
||||
if(intval($r['data']['os_storage'])) {
|
||||
$fname = dbunescbin($r['data']['content']);
|
||||
$fname = $r['data']['content'];
|
||||
if(strpos($fname,'store') !== false)
|
||||
$istream = fopen($fname,'rb');
|
||||
else
|
||||
$istream = fopen('store/' . $c[0]['channel_address'] . '/' . $fname,'rb');
|
||||
$ostream = fopen('php://output','wb');
|
||||
if($istream && $ostream) {
|
||||
pipe_streams($istream,$ostream);
|
||||
pipe_streams($istream, $ostream);
|
||||
fclose($istream);
|
||||
fclose($ostream);
|
||||
}
|
||||
}
|
||||
else
|
||||
echo dbunescbin($r['data']['content']);
|
||||
echo $r['data']['content'];
|
||||
killme();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function zip_archive_handler($zip, $attach_ids, $attach_path, $pass = 1) {
|
||||
|
||||
$observer_hash = get_observer_hash();
|
||||
$single = ((count($attach_ids) == 1) ? true : false);
|
||||
$download_name = 'download.zip';
|
||||
|
||||
foreach($attach_ids as $attach_id) {
|
||||
|
||||
$r = attach_by_id($attach_id, $observer_hash);
|
||||
|
||||
if (! $r['success']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($r['data']['is_dir'] && $single && $pass === 1)
|
||||
$download_name = $r['data']['filename'] . '.zip';
|
||||
|
||||
$zip_path = $r['data']['display_path'];
|
||||
|
||||
if ($attach_path) {
|
||||
$strip_str = $attach_path . '/';
|
||||
$count = strlen($strip_str);
|
||||
$zip_path = substr($r['data']['display_path'], $count);
|
||||
}
|
||||
|
||||
if ($r['data']['is_dir']) {
|
||||
$zip->addEmptyDir($zip_path);
|
||||
|
||||
$d = q("SELECT id FROM attach WHERE folder = '%s'",
|
||||
dbesc($r['data']['hash'])
|
||||
);
|
||||
|
||||
$attach_ids = ids_to_array($d);
|
||||
self::zip_archive_handler($zip, $attach_ids, $attach_path, $pass++);
|
||||
}
|
||||
else {
|
||||
$file_path = $r['data']['content'];
|
||||
$zip->addFile($file_path, $zip_path);
|
||||
// compressing can be ressource intensive - just store the data
|
||||
$zip->setCompressionName($zip_path, ZipArchive::CM_STORE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $download_name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
203
Zotlabs/Module/Attach_edit.php
Normal file
203
Zotlabs/Module/Attach_edit.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
/**
|
||||
* @file Zotlabs/Module/Attach_edit.php
|
||||
*
|
||||
*/
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Access\AccessList;
|
||||
|
||||
class Attach_edit extends Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if (!local_channel() && !remote_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attach_ids = ((x($_POST, 'attach_ids')) ? $_POST['attach_ids'] : []);
|
||||
$attach_id = ((x($_POST, 'attach_id')) ? intval($_POST['attach_id']) : 0);
|
||||
$channel_id = ((x($_POST, 'channel_id')) ? intval($_POST['channel_id']) : 0);
|
||||
$dnd = ((x($_POST, 'dnd')) ? intval($_POST['dnd']) : 0);
|
||||
$permissions = ((x($_POST, 'permissions')) ? intval($_POST['permissions']) : 0);
|
||||
$return_path = ((x($_POST, 'return_path')) ? notags($_POST['return_path']) : 'cloud');
|
||||
$delete = ((x($_POST, 'delete')) ? intval($_POST['delete']) : 0);
|
||||
$newfolder = ((x($_POST, 'newfolder_' . $attach_id)) ? notags($_POST['newfolder_' . $attach_id]) : '');
|
||||
if(! $newfolder)
|
||||
$newfolder = ((x($_POST, 'newfolder')) ? notags($_POST['newfolder']) : '');
|
||||
$newfilename = ((x($_POST, 'newfilename_' . $attach_id)) ? notags($_POST['newfilename_' . $attach_id]) : '');
|
||||
$recurse = ((x($_POST, 'recurse_' . $attach_id)) ? intval($_POST['recurse_' . $attach_id]) : 0);
|
||||
if(! $recurse)
|
||||
$recurse = ((x($_POST, 'recurse')) ? intval($_POST['recurse']) : 0);
|
||||
$notify = ((x($_POST, 'notify_edit_' . $attach_id)) ? intval($_POST['notify_edit_' . $attach_id]) : 0);
|
||||
$copy = ((x($_POST, 'copy_' . $attach_id)) ? intval($_POST['copy_' . $attach_id]) : 0);
|
||||
if(! $copy)
|
||||
$copy = ((x($_POST, 'copy')) ? intval($_POST['copy']) : 0);
|
||||
|
||||
$categories = ((x($_POST, 'categories_' . $attach_id)) ? notags($_POST['categories_' . $attach_id]) : '');
|
||||
if(! $categories)
|
||||
$categories = ((x($_POST, 'categories')) ? notags($_POST['categories']) : '');
|
||||
|
||||
if($attach_id)
|
||||
$attach_ids[] = $attach_id;
|
||||
|
||||
$single = ((count($attach_ids) === 1) ? true : false);
|
||||
|
||||
$channel = channelx_by_n($channel_id);
|
||||
|
||||
if (! $channel) {
|
||||
notice(t('Channel not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$nick = $channel['channel_address'];
|
||||
$observer = App::get_observer();
|
||||
$observer_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||
$is_owner = ((local_channel() == $channel_id) ? true : false);
|
||||
|
||||
$ids_str = implode(',', $attach_ids);
|
||||
|
||||
$r = q("SELECT id, uid, hash, creator, folder, filename, is_photo, is_dir FROM attach WHERE id IN ( %s ) AND uid = %d",
|
||||
dbesc($ids_str),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
notice(t('File not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($r as $rr) {
|
||||
$actions_done = '';
|
||||
$attach_id = $rr['id'];
|
||||
$resource = $rr['hash'];
|
||||
$creator = $rr['creator'];
|
||||
$folder = $rr['folder'];
|
||||
$filename = $rr['filename'];
|
||||
$is_photo = intval($rr['is_photo']);
|
||||
$is_dir = intval($rr['is_dir']);
|
||||
$admin_delete = false;
|
||||
|
||||
$is_creator = (($creator == $observer_hash) ? true : false);
|
||||
$move = ((! $copy && ($folder !== $newfolder || (($single) ? $filename !== $newfilename : false))) ? true : false);
|
||||
|
||||
$perms = get_all_perms($channel_id, $observer_hash);
|
||||
|
||||
if (! ($perms['view_storage'] || is_site_admin())) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $perms['write_storage']) {
|
||||
if (is_site_admin()) {
|
||||
$admin_delete = true;
|
||||
}
|
||||
else {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$is_owner && !$admin_delete) {
|
||||
if(! $is_creator) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete) {
|
||||
attach_delete($channel_id, $resource, $is_photo);
|
||||
$actions_done .= 'delete,';
|
||||
}
|
||||
|
||||
if ($copy) {
|
||||
if($is_dir && $resource == $newfolder) {
|
||||
notice( t('Can not copy folder into itself.') . EOL);
|
||||
continue;
|
||||
}
|
||||
$x = attach_copy($channel_id, $resource, $newfolder, (($single) ? $newfilename : ''));
|
||||
if ($x['success'])
|
||||
$resource = $x['resource_id'];
|
||||
|
||||
$actions_done .= 'copy,';
|
||||
|
||||
}
|
||||
|
||||
if ($move) {
|
||||
if($is_dir && $resource == $newfolder) {
|
||||
notice( sprintf(t('Can not move folder "%s" into itself.'), $filename) . EOL);
|
||||
continue;
|
||||
}
|
||||
$x = attach_move($channel_id, $resource, $newfolder, (($single) ? $newfilename : ''));
|
||||
|
||||
$actions_done .= 'move,';
|
||||
|
||||
}
|
||||
|
||||
if(! $delete && ! $dnd) {
|
||||
if ($single || (! $single && $categories)) {
|
||||
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
|
||||
intval($channel_id),
|
||||
intval($attach_id),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
$cat = explode(',', $categories);
|
||||
if ($cat) {
|
||||
foreach($cat as $term) {
|
||||
$term = trim(escape_tags($term));
|
||||
if ($term) {
|
||||
$term_link = z_root() . '/cloud/' . $nick . '/?cat=' . $term;
|
||||
store_item_tag($channel_id, $attach_id, TERM_OBJ_FILE, TERM_CATEGORY, $term, $term_link);
|
||||
}
|
||||
}
|
||||
$actions_done .= 'cat_add,';
|
||||
}
|
||||
}
|
||||
else {
|
||||
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
|
||||
intval($channel_id),
|
||||
intval($attach_id),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
$actions_done .= 'cat_remove,';
|
||||
}
|
||||
|
||||
if ($is_owner && ($single || (! $single && $permissions))) {
|
||||
$acl = new AccessList($channel);
|
||||
$acl->set_from_array($_REQUEST);
|
||||
$x = $acl->get();
|
||||
|
||||
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true);
|
||||
$actions_done .= 'permissions,';
|
||||
|
||||
if ($notify) {
|
||||
attach_store_item($channel, $observer, $resource);
|
||||
$actions_done .= 'notify,';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $admin_delete && $actions_done) {
|
||||
$sync = attach_export_data($channel, $resource, (($delete) ? true : false));
|
||||
|
||||
if ($sync) {
|
||||
Libsync::build_sync_packet($channel_id, ['file' => [$sync]]);
|
||||
}
|
||||
}
|
||||
|
||||
logger('attach_edit: ' . $actions_done);
|
||||
|
||||
}
|
||||
|
||||
if($dnd || $delete) {
|
||||
json_return_and_die([ 'success' => true ]);
|
||||
}
|
||||
|
||||
goaway($return_path);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,9 @@ use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
|
||||
require_once('include/event.php');
|
||||
|
||||
@@ -47,11 +50,12 @@ class Cdav extends Controller {
|
||||
if($sigblock) {
|
||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
$r = q("select * from hubloc where hubloc_id_url = '%s'",
|
||||
dbesc($keyId)
|
||||
);
|
||||
if($r) {
|
||||
$c = channelx_by_hash($r[0]['hubloc_hash']);
|
||||
$r = Libzot::zot_record_preferred($r);
|
||||
$c = channelx_by_hash($r['hubloc_hash']);
|
||||
if($c) {
|
||||
$a = q("select * from account where account_id = %d limit 1",
|
||||
intval($c['channel_account_id'])
|
||||
@@ -157,10 +161,10 @@ class Cdav extends Controller {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Track CDAV updates from remote clients
|
||||
|
||||
$httpmethod = $_SERVER['REQUEST_METHOD'];
|
||||
$httpmethod = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if($httpmethod === 'PUT' || $httpmethod === 'DELETE') {
|
||||
|
||||
@@ -190,12 +194,12 @@ class Cdav extends Controller {
|
||||
if($x = get_cdav_id($principalUri, explode("/", $httpuri)[4], $cdavtable)) {
|
||||
|
||||
$cdavdata = $this->get_cdav_data($x['id'], $cdavtable);
|
||||
|
||||
|
||||
$etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false);
|
||||
|
||||
|
||||
// delete
|
||||
if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -206,7 +210,7 @@ class Cdav extends Controller {
|
||||
if($etag) {
|
||||
// update
|
||||
if($cdavdata['etag'] !== $etag)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -217,7 +221,7 @@ class Cdav extends Controller {
|
||||
}
|
||||
else {
|
||||
// new
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -337,7 +341,7 @@ class Cdav extends Controller {
|
||||
// set new calendar to be visible
|
||||
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'create',
|
||||
'uri' => $calendarUri,
|
||||
@@ -413,7 +417,7 @@ class Cdav extends Controller {
|
||||
$calendarData = $vcalendar->serialize();
|
||||
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -444,7 +448,7 @@ class Cdav extends Controller {
|
||||
$caldavBackend->updateCalendar($id, $patch);
|
||||
$patch->commit();
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'edit',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -510,7 +514,7 @@ class Cdav extends Controller {
|
||||
$calendarData = $vcalendar->serialize();
|
||||
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -536,7 +540,7 @@ class Cdav extends Controller {
|
||||
|
||||
$caldavBackend->deleteCalendarObject($id, $uri);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -594,7 +598,7 @@ class Cdav extends Controller {
|
||||
$calendarData = $vcalendar->serialize();
|
||||
$caldavBackend->updateCalendarObject($id, $uri, $calendarData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -653,7 +657,7 @@ class Cdav extends Controller {
|
||||
|
||||
$carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'create',
|
||||
'uri' => $addressbookUri,
|
||||
@@ -680,7 +684,7 @@ class Cdav extends Controller {
|
||||
$carddavBackend->updateAddressBook($id, $patch);
|
||||
$patch->commit();
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'edit',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -724,7 +728,7 @@ class Cdav extends Controller {
|
||||
$cardData = $vcard->serialize();
|
||||
$carddavBackend->createCard($id, $uri, $cardData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -762,8 +766,8 @@ class Cdav extends Controller {
|
||||
$cardData = $vcard->serialize();
|
||||
|
||||
$carddavBackend->updateCard($id, $uri, $cardData);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'update_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -788,7 +792,7 @@ class Cdav extends Controller {
|
||||
|
||||
$carddavBackend->deleteCard($id, $uri);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'delete_card',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -804,7 +808,7 @@ class Cdav extends Controller {
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
|
||||
if($src) {
|
||||
|
||||
|
||||
$carddata = @file_get_contents($src);
|
||||
|
||||
if($_REQUEST['c_upload']) {
|
||||
@@ -840,14 +844,14 @@ class Cdav extends Controller {
|
||||
$objects = new \Sabre\VObject\Splitter\VCard($carddata);
|
||||
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
|
||||
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||
|
||||
|
||||
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
|
||||
}
|
||||
|
||||
|
||||
$ids = [];
|
||||
import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backend, $ids, true);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
$sync => [
|
||||
'action' => 'import',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -1013,7 +1017,7 @@ class Cdav extends Controller {
|
||||
$catsenabled = feature_enabled(local_channel(), 'categories');
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
|
||||
$accesslist = new \Zotlabs\Access\AccessList($channel);
|
||||
$perm_defaults = $accesslist->get();
|
||||
|
||||
@@ -1167,7 +1171,7 @@ class Cdav extends Controller {
|
||||
|
||||
set_pconfig(local_channel(), 'cdav_calendar', $id, argv(4));
|
||||
|
||||
build_sync_packet(local_channel(), [
|
||||
Libsync::build_sync_packet(local_channel(), [
|
||||
'calendar' => [
|
||||
'action' => 'switch',
|
||||
'uri' => $cdavdata['uri'],
|
||||
@@ -1190,7 +1194,7 @@ class Cdav extends Controller {
|
||||
|
||||
$caldavBackend->deleteCalendar($id);
|
||||
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'calendar' => [
|
||||
'action' => 'drop',
|
||||
'uri' => $cdavdata['uri']
|
||||
@@ -1409,7 +1413,7 @@ class Cdav extends Controller {
|
||||
$carddavBackend->deleteAddressBook($id);
|
||||
|
||||
if($cdavdata)
|
||||
build_sync_packet($channel['channel_id'], [
|
||||
Libsync::build_sync_packet($channel['channel_id'], [
|
||||
'addressbook' => [
|
||||
'action' => 'drop',
|
||||
'uri' => $cdavdata['uri']
|
||||
@@ -1427,7 +1431,7 @@ class Cdav extends Controller {
|
||||
return;
|
||||
|
||||
$uri = 'principals/' . $channel['channel_address'];
|
||||
|
||||
|
||||
|
||||
$r = q("select * from principals where uri = '%s' limit 1",
|
||||
dbesc($uri)
|
||||
|
||||
@@ -130,9 +130,6 @@ class Channel extends Controller {
|
||||
|
||||
$noscript_content = get_config('system', 'noscript_content', '1');
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
$category = $datequery = $datequery2 = '';
|
||||
|
||||
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
||||
@@ -152,7 +149,6 @@ class Channel extends Controller {
|
||||
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
|
||||
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
|
||||
$order = ((x($_GET,'order')) ? notags($_GET['order']) : 'post');
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
$search = ((x($_GET,'search')) ? $_GET['search'] : EMPTY_STR);
|
||||
|
||||
$groups = array();
|
||||
@@ -187,8 +183,6 @@ class Channel extends Controller {
|
||||
|
||||
nav_set_selected('Channel Home');
|
||||
|
||||
$static = channel_manual_conv_update(App::$profile['profile_uid']);
|
||||
|
||||
// search terms header
|
||||
if($search) {
|
||||
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
|
||||
@@ -255,7 +249,9 @@ class Channel extends Controller {
|
||||
|
||||
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($search) {
|
||||
$search = escape_tags($search);
|
||||
@@ -270,7 +266,6 @@ class Channel extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/json+oembed',
|
||||
@@ -278,14 +273,6 @@ class Channel extends Controller {
|
||||
'title' => 'oembed'
|
||||
]);
|
||||
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if(($update) && (! $load)) {
|
||||
|
||||
if($mid) {
|
||||
@@ -294,7 +281,6 @@ class Channel extends Controller {
|
||||
dbesc($mid . '%'),
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
else {
|
||||
$r = q("SELECT parent AS item_id from item
|
||||
@@ -306,9 +292,7 @@ class Channel extends Controller {
|
||||
ORDER BY created DESC",
|
||||
intval(App::$profile['profile_uid'])
|
||||
);
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -406,7 +390,7 @@ class Channel extends Controller {
|
||||
$o .= '<div id="live-channel"></div>' . "\r\n";
|
||||
$o .= "<script> var profile_uid = " . App::$profile['profile_uid']
|
||||
. "; var netargs = '?f='; var profile_page = " . App::$pager['page']
|
||||
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
|
||||
. "; divmore_height = " . intval($maxheight) . ";</script>\r\n";
|
||||
|
||||
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
||||
'$baseurl' => z_root(),
|
||||
@@ -424,7 +408,6 @@ class Channel extends Controller {
|
||||
'$wall' => '1',
|
||||
'$fh' => '0',
|
||||
'$dm' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => $search,
|
||||
'$xchan' => '',
|
||||
@@ -437,7 +420,8 @@ class Channel extends Controller {
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$dend' => $datequery,
|
||||
'$dbegin' => $datequery2
|
||||
'$dbegin' => $datequery2,
|
||||
'$conv_mode' => 'channel'
|
||||
));
|
||||
|
||||
}
|
||||
@@ -476,6 +460,8 @@ class Channel extends Controller {
|
||||
if($mid)
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,11 @@ namespace Zotlabs\Module;
|
||||
*/
|
||||
|
||||
use Sabre\DAV as SDAV;
|
||||
use \Zotlabs\Storage;
|
||||
use \Zotlabs\Web\Controller;
|
||||
use \Zotlabs\Storage\BasicAuth;
|
||||
use \Zotlabs\Storage\Directory;
|
||||
use \Zotlabs\Storage\Browser;
|
||||
|
||||
|
||||
// composer autoloader for SabreDAV
|
||||
require_once('vendor/autoload.php');
|
||||
@@ -20,7 +24,7 @@ require_once('include/attach.php');
|
||||
* @brief Cloud Module.
|
||||
*
|
||||
*/
|
||||
class Cloud extends \Zotlabs\Web\Controller {
|
||||
class Cloud extends Controller {
|
||||
|
||||
/**
|
||||
* @brief Fires up the SabreDAV server.
|
||||
@@ -42,7 +46,7 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
|
||||
$auth = new \Zotlabs\Storage\BasicAuth();
|
||||
$auth = new BasicAuth();
|
||||
|
||||
$ob_hash = get_observer_hash();
|
||||
|
||||
@@ -72,7 +76,7 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
if($x !== \App::$query_string)
|
||||
goaway(z_root() . '/' . $x);
|
||||
|
||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
||||
$rootDirectory = new Directory('/', [], $auth);
|
||||
|
||||
// A SabreDAV server-object
|
||||
$server = new SDAV\Server($rootDirectory);
|
||||
@@ -85,7 +89,7 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
$is_readable = false;
|
||||
|
||||
// provide a directory view for the cloud in Hubzilla
|
||||
$browser = new \Zotlabs\Storage\Browser($auth);
|
||||
$browser = new Browser($auth);
|
||||
$auth->setBrowserPlugin($browser);
|
||||
|
||||
$server->addPlugin($browser);
|
||||
@@ -105,13 +109,13 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($browser->build_page)
|
||||
construct_page();
|
||||
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
function DAVException($err) {
|
||||
|
||||
|
||||
if($err instanceof \Sabre\DAV\Exception\NotFound) {
|
||||
notice( t('Not found') . EOL);
|
||||
}
|
||||
@@ -126,7 +130,7 @@ class Cloud extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
construct_page();
|
||||
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,11 +51,12 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
if($sigblock) {
|
||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
$r = q("select * from hubloc where hubloc_id_url = '%s'",
|
||||
dbesc($keyId)
|
||||
);
|
||||
if($r) {
|
||||
$c = channelx_by_hash($r[0]['hubloc_hash']);
|
||||
$r = Libzot::zot_record_preferred($r);
|
||||
$c = channelx_by_hash($r['hubloc_hash']);
|
||||
if($c) {
|
||||
$a = q("select * from account where account_id = %d limit 1",
|
||||
intval($c['channel_account_id'])
|
||||
@@ -99,7 +100,7 @@ class Dav extends \Zotlabs\Web\Controller {
|
||||
|
||||
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
|
||||
|
||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', [], $auth);
|
||||
|
||||
// A SabreDAV server-object
|
||||
$server = new SDAV\Server($rootDirectory);
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/dir_fns.php');
|
||||
@@ -15,7 +17,7 @@ class Directory extends Controller {
|
||||
|
||||
function init() {
|
||||
App::set_pager_itemspage(30);
|
||||
|
||||
|
||||
if(local_channel() && x($_GET,'ignore')) {
|
||||
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
|
||||
intval(local_channel()),
|
||||
@@ -26,12 +28,12 @@ class Directory extends Controller {
|
||||
|
||||
if(local_channel())
|
||||
App::$profile_uid = local_channel();
|
||||
|
||||
|
||||
$observer = get_observer_hash();
|
||||
$global_changed = false;
|
||||
$safe_changed = false;
|
||||
$pubforums_changed = false;
|
||||
|
||||
|
||||
if(array_key_exists('global',$_REQUEST)) {
|
||||
$globaldir = intval($_REQUEST['global']);
|
||||
$global_changed = true;
|
||||
@@ -41,7 +43,7 @@ class Directory extends Controller {
|
||||
if($observer)
|
||||
set_xconfig($observer,'directory','globaldir',$globaldir);
|
||||
}
|
||||
|
||||
|
||||
if(array_key_exists('safe',$_REQUEST)) {
|
||||
$safemode = intval($_REQUEST['safe']);
|
||||
$safe_changed = true;
|
||||
@@ -51,8 +53,8 @@ class Directory extends Controller {
|
||||
if($observer)
|
||||
set_xconfig($observer,'directory','safemode',$safemode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(array_key_exists('pubforums',$_REQUEST)) {
|
||||
$pubforums = intval($_REQUEST['pubforums']);
|
||||
$pubforums_changed = true;
|
||||
@@ -64,52 +66,52 @@ class Directory extends Controller {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(observer_prohibited()) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(get_config('system','block_public_directory',false) && (! get_observer_hash())) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$observer = get_observer_hash();
|
||||
|
||||
$globaldir = get_directory_setting($observer, 'globaldir');
|
||||
|
||||
$globaldir = Libzotdir::get_directory_setting($observer, 'globaldir');
|
||||
|
||||
// override your personal global search pref if we're doing a navbar search of the directory
|
||||
if(intval($_REQUEST['navsearch']))
|
||||
$globaldir = 1;
|
||||
|
||||
$safe_mode = get_directory_setting($observer, 'safemode');
|
||||
|
||||
$pubforums = get_directory_setting($observer, 'pubforums');
|
||||
|
||||
|
||||
$safe_mode = Libzotdir::get_directory_setting($observer, 'safemode');
|
||||
|
||||
$pubforums = Libzotdir::get_directory_setting($observer, 'pubforums');
|
||||
|
||||
$o = '';
|
||||
nav_set_selected('Directory');
|
||||
|
||||
|
||||
if(x($_POST,'search'))
|
||||
$search = notags(trim($_POST['search']));
|
||||
else
|
||||
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
|
||||
|
||||
|
||||
|
||||
|
||||
if(strpos($search,'=') && local_channel() && feature_enabled(local_channel(), 'advanced_dirsearch'))
|
||||
$advanced = $search;
|
||||
|
||||
|
||||
$keywords = (($_GET['keywords']) ? $_GET['keywords'] : '');
|
||||
|
||||
|
||||
// Suggest channels if no search terms or keywords are given
|
||||
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
|
||||
|
||||
|
||||
if($suggest) {
|
||||
|
||||
// the directory options have no effect in suggestion mode
|
||||
|
||||
|
||||
$globaldir = 1;
|
||||
$safe_mode = 1;
|
||||
$type = 0;
|
||||
@@ -120,7 +122,7 @@ class Directory extends Controller {
|
||||
notice( t('No default suggestions were found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Remember in which order the suggestions were
|
||||
$addresses = array();
|
||||
$common = array();
|
||||
@@ -129,7 +131,7 @@ class Directory extends Controller {
|
||||
$common[$rr['xchan_addr']] = ((intval($rr['total']) > 0) ? intval($rr['total']) - 1 : 0);
|
||||
$addresses[$rr['xchan_addr']] = $index++;
|
||||
}
|
||||
|
||||
|
||||
// Build query to get info about suggested people
|
||||
$advanced = '';
|
||||
foreach(array_keys($addresses) as $address) {
|
||||
@@ -137,13 +139,13 @@ class Directory extends Controller {
|
||||
}
|
||||
// Remove last space in the advanced query
|
||||
$advanced = rtrim($advanced);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$tpl = get_markup_template('directory_header.tpl');
|
||||
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
|
||||
$directory_admin = false;
|
||||
|
||||
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
@@ -154,19 +156,19 @@ class Directory extends Controller {
|
||||
}
|
||||
|
||||
if(! $url) {
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
$directory = Libzotdir::find_upstream_directory($dirmode);
|
||||
if((! $directory) || (! array_key_exists('url',$directory)) || (! $directory['url']))
|
||||
logger('CRITICAL: No directory server URL');
|
||||
$url = $directory['url'] . '/dirsearch';
|
||||
}
|
||||
|
||||
|
||||
$token = get_config('system','realm_token');
|
||||
|
||||
|
||||
|
||||
|
||||
logger('mod_directory: URL = ' . $url, LOGGER_DEBUG);
|
||||
|
||||
|
||||
$contacts = array();
|
||||
|
||||
|
||||
if(local_channel()) {
|
||||
$x = q("select abook_xchan from abook where abook_channel = %d",
|
||||
intval(local_channel())
|
||||
@@ -176,24 +178,24 @@ class Directory extends Controller {
|
||||
$contacts[] = $xx['abook_xchan'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($url) {
|
||||
|
||||
|
||||
$numtags = get_config('system','directorytags');
|
||||
|
||||
|
||||
$kw = ((intval($numtags) > 0) ? intval($numtags) : 50);
|
||||
|
||||
|
||||
if(get_config('system','disable_directory_keywords'))
|
||||
$kw = 0;
|
||||
|
||||
|
||||
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
|
||||
|
||||
|
||||
if($token)
|
||||
$query .= '&t=' . $token;
|
||||
|
||||
|
||||
if(! $globaldir)
|
||||
$query .= '&hub=' . App::get_hostname();
|
||||
|
||||
|
||||
if($search)
|
||||
$query .= '&name=' . urlencode($search) . '&keywords=' . urlencode($search);
|
||||
if(strpos($search,'@'))
|
||||
@@ -204,29 +206,29 @@ class Directory extends Controller {
|
||||
$query .= '&query=' . urlencode($advanced);
|
||||
if(! is_null($pubforums))
|
||||
$query .= '&pubforums=' . intval($pubforums);
|
||||
|
||||
|
||||
$directory_sort_order = get_config('system','directory_sort_order');
|
||||
if(! $directory_sort_order)
|
||||
$directory_sort_order = 'date';
|
||||
|
||||
|
||||
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : $directory_sort_order);
|
||||
|
||||
|
||||
if($sort_order)
|
||||
$query .= '&order=' . urlencode($sort_order);
|
||||
|
||||
|
||||
if(App::$pager['page'] != 1)
|
||||
$query .= '&p=' . App::$pager['page'];
|
||||
|
||||
|
||||
logger('mod_directory: query: ' . $query);
|
||||
|
||||
|
||||
$x = z_fetch_url($query);
|
||||
logger('directory: return from upstream: ' . print_r($x,true), LOGGER_DATA);
|
||||
|
||||
|
||||
if($x['success']) {
|
||||
$t = 0;
|
||||
$j = json_decode($x['body'],true);
|
||||
if($j) {
|
||||
|
||||
|
||||
if($j['results']) {
|
||||
|
||||
$results = $j['results'];
|
||||
@@ -235,23 +237,23 @@ class Directory extends Controller {
|
||||
}
|
||||
|
||||
$entries = array();
|
||||
|
||||
|
||||
$photo = 'thumb';
|
||||
|
||||
|
||||
foreach($results as $rr) {
|
||||
|
||||
|
||||
$profile_link = chanlink_url($rr['url']);
|
||||
|
||||
|
||||
$pdesc = (($rr['description']) ? $rr['description'] . '<br />' : '');
|
||||
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
|
||||
|
||||
$connect_link = ((local_channel()) ? z_root() . '/follow?f=&url=' . urlencode($rr['address']) : '');
|
||||
|
||||
// Checking status is disabled ATM until someone checks the performance impact more carefully
|
||||
//$online = remote_online_status($rr['address']);
|
||||
$online = '';
|
||||
|
||||
|
||||
if(in_array($rr['hash'],$contacts))
|
||||
$connect_link = '';
|
||||
|
||||
|
||||
$location = '';
|
||||
if(strlen($rr['locale']))
|
||||
$location .= $rr['locale'];
|
||||
@@ -265,53 +267,53 @@ class Directory extends Controller {
|
||||
$location .= ', ';
|
||||
$location .= $rr['country'];
|
||||
}
|
||||
|
||||
|
||||
$age = '';
|
||||
if(strlen($rr['birthday'])) {
|
||||
if(($years = age($rr['birthday'],'UTC','')) > 0)
|
||||
$age = $years;
|
||||
}
|
||||
|
||||
|
||||
$page_type = '';
|
||||
|
||||
|
||||
$rating_enabled = get_config('system','rating_enabled');
|
||||
|
||||
if($rr['total_ratings'] && $rating_enabled)
|
||||
$total_ratings = sprintf( tt("%d rating", "%d ratings", $rr['total_ratings']), $rr['total_ratings']);
|
||||
else
|
||||
$total_ratings = '';
|
||||
|
||||
|
||||
$profile = $rr;
|
||||
|
||||
|
||||
if ((x($profile,'locale') == 1)
|
||||
|| (x($profile,'region') == 1)
|
||||
|| (x($profile,'postcode') == 1)
|
||||
|| (x($profile,'country') == 1))
|
||||
|
||||
|
||||
$gender = ((x($profile,'gender') == 1) ? t('Gender: ') . $profile['gender']: False);
|
||||
|
||||
|
||||
$marital = ((x($profile,'marital') == 1) ? t('Status: ') . $profile['marital']: False);
|
||||
|
||||
|
||||
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage: ') : False);
|
||||
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
|
||||
|
||||
$homepageurl = ((x($profile,'homepage') == 1) ? html2plain($profile['homepage']) : '');
|
||||
|
||||
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
|
||||
|
||||
|
||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
|
||||
if ($about && $safe_mode) {
|
||||
$about = html2plain($about);
|
||||
}
|
||||
|
||||
|
||||
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
|
||||
|
||||
|
||||
|
||||
$out = '';
|
||||
|
||||
|
||||
if($keywords) {
|
||||
$keywords = str_replace(',',' ', $keywords);
|
||||
$keywords = str_replace(' ',' ', $keywords);
|
||||
$karr = explode(' ', $keywords);
|
||||
|
||||
|
||||
if($karr) {
|
||||
if(local_channel()) {
|
||||
$r = q("select keywords from profile where uid = %d and is_default = 1 limit 1",
|
||||
@@ -332,9 +334,9 @@ class Directory extends Controller {
|
||||
$out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'">' . $k . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$entry = array(
|
||||
'id' => ++$t,
|
||||
'profile_link' => $profile_link,
|
||||
@@ -366,7 +368,7 @@ class Directory extends Controller {
|
||||
'about' => $about,
|
||||
'about_label' => t('About:'),
|
||||
'conn_label' => t('Connect'),
|
||||
'forum_label' => t('Public Forum:'),
|
||||
'forum_label' => t('Public Forum:'),
|
||||
'connect' => $connect_link,
|
||||
'online' => $online,
|
||||
'kw' => (($out) ? t('Keywords: ') : ''),
|
||||
@@ -378,36 +380,36 @@ class Directory extends Controller {
|
||||
'common_count' => intval($common[$rr['address']]),
|
||||
'safe' => $safe_mode
|
||||
);
|
||||
|
||||
|
||||
$arr = array('contact' => $rr, 'entry' => $entry);
|
||||
|
||||
|
||||
call_hooks('directory_item', $arr);
|
||||
|
||||
|
||||
unset($profile);
|
||||
unset($location);
|
||||
|
||||
|
||||
if(! $arr['entry']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($sort_order == '' && $suggest) {
|
||||
$entries[$addresses[$rr['address']]] = $arr['entry']; // Use the same indexes as originally to get the best suggestion first
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
$entries[] = $arr['entry'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ksort($entries); // Sort array by key so that foreach-constructs work as expected
|
||||
|
||||
|
||||
if($j['keywords']) {
|
||||
App::$data['directory_keywords'] = $j['keywords'];
|
||||
}
|
||||
|
||||
|
||||
logger('mod_directory: entries: ' . print_r($entries,true), LOGGER_DATA);
|
||||
|
||||
|
||||
|
||||
|
||||
if($_REQUEST['aj']) {
|
||||
if($entries) {
|
||||
$o = replace_macros(get_markup_template('directajax.tpl'),array(
|
||||
@@ -422,9 +424,9 @@ class Directory extends Controller {
|
||||
}
|
||||
else {
|
||||
$maxheight = 94;
|
||||
|
||||
|
||||
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
|
||||
|
||||
|
||||
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$search' => $search,
|
||||
@@ -442,10 +444,10 @@ class Directory extends Controller {
|
||||
'$reversedate' => t('Oldest to Newest'),
|
||||
'$suggest' => $suggest ? '&suggest=1' : ''
|
||||
));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
if($_REQUEST['aj']) {
|
||||
@@ -463,7 +465,7 @@ class Directory extends Controller {
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
static public function reorder_results($results,$suggests) {
|
||||
|
||||
if(! $suggests)
|
||||
|
||||
@@ -192,7 +192,7 @@ class Dirsearch extends Controller {
|
||||
else {
|
||||
$qlimit = " LIMIT " . intval($perpage) . " OFFSET " . intval($startrec);
|
||||
if($return_total) {
|
||||
$r = q("SELECT COUNT(xchan_hash) AS total FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql ");
|
||||
$r = q("SELECT COUNT(xchan_hash) AS total FROM xchan left join xprof on xchan_hash = xprof_hash where $logic $sql_extra and xchan_network = 'zot6' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql ");
|
||||
if($r) {
|
||||
$ret['total_items'] = $r[0]['total'];
|
||||
}
|
||||
@@ -261,7 +261,7 @@ class Dirsearch extends Controller {
|
||||
else {
|
||||
|
||||
$r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash
|
||||
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
|
||||
where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
|
||||
$safesql $order $qlimit "
|
||||
);
|
||||
|
||||
|
||||
@@ -22,9 +22,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
$module_format = 'html';
|
||||
}
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
if(observer_prohibited()) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
@@ -183,22 +180,11 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
|
||||
@@ -229,7 +215,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
@@ -315,7 +300,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
dbesc($target_item['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
if($r === null) {
|
||||
// in case somebody turned off public access to sys channel content using permissions
|
||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||
@@ -335,7 +319,6 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
intval($sysid)
|
||||
);
|
||||
}
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -448,6 +431,8 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
@@ -11,17 +11,16 @@ require_once('include/photos.php');
|
||||
class File_upload extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
logger('file upload: ' . print_r($_REQUEST,true));
|
||||
logger('file upload: ' . print_r($_FILES,true));
|
||||
|
||||
|
||||
$channel = (($_REQUEST['channick']) ? channelx_by_nick($_REQUEST['channick']) : null);
|
||||
|
||||
|
||||
if(! $channel) {
|
||||
logger('channel not found');
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$_REQUEST['source'] = 'file_upload';
|
||||
|
||||
if($channel['channel_id'] != local_channel()) {
|
||||
@@ -40,13 +39,11 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
$r = attach_mkdir($channel, get_observer_hash(), $_REQUEST);
|
||||
if($r['success']) {
|
||||
$hash = $r['data']['hash'];
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($sync) {
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
goaway(z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path']);
|
||||
|
||||
goaway(z_root() . '/' . $_REQUEST['return_url']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -54,8 +51,6 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
$matches = [];
|
||||
$partial = false;
|
||||
|
||||
|
||||
|
||||
if(array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) {
|
||||
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches);
|
||||
if($pm) {
|
||||
@@ -69,7 +64,7 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
json_return_and_die($result);
|
||||
json_return_and_die($x);
|
||||
}
|
||||
else {
|
||||
header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
|
||||
@@ -83,7 +78,7 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
if(! array_key_exists('userfile',$_FILES)) {
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $_FILES['files']['name'],
|
||||
@@ -103,8 +98,9 @@ class File_upload extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/' . $_REQUEST['return_url']);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ class Filer extends \Zotlabs\Web\Controller {
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$x = q("update item set item_retained = 1 where id = %d and uid = %d",
|
||||
$x = q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['parent']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
@@ -28,10 +28,14 @@ class Filerm extends \Zotlabs\Web\Controller {
|
||||
intval($item_id),
|
||||
dbesc($term)
|
||||
);
|
||||
|
||||
$x = q("update item set item_retained = 0, changed = '%s' where id = %d and uid = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($item_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if(x($_SESSION,'return_url'))
|
||||
goaway(z_root() . '/' . $_SESSION['return_url']);
|
||||
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
notice( t('Deprecated!') . EOL);
|
||||
return;
|
||||
|
||||
$channel_id = ((x($_POST, 'uid')) ? intval($_POST['uid']) : 0);
|
||||
|
||||
if((! $channel_id) || (! local_channel()) || ($channel_id != local_channel())) {
|
||||
@@ -47,6 +50,9 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
notice( t('Deprecated!') . EOL);
|
||||
return;
|
||||
|
||||
if(argc() > 1)
|
||||
$which = argv(1);
|
||||
else {
|
||||
@@ -88,7 +94,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
if($json_return)
|
||||
if($json_return)
|
||||
json_return_and_die([ 'success' => false ]);
|
||||
return;
|
||||
}
|
||||
@@ -102,24 +108,23 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
if(! $r) {
|
||||
notice( t('File not found.') . EOL);
|
||||
|
||||
if($json_return)
|
||||
if($json_return)
|
||||
json_return_and_die([ 'success' => false ]);
|
||||
|
||||
goaway(z_root() . '/cloud/' . $which);
|
||||
}
|
||||
|
||||
if(local_channel() !== $owner) {
|
||||
if((local_channel() !== $owner) && !$admin_delete) {
|
||||
if($r[0]['creator'] && $r[0]['creator'] !== $ob_hash) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
|
||||
if($json_return)
|
||||
if($json_return)
|
||||
json_return_and_die([ 'success' => false ]);
|
||||
|
||||
goaway(z_root() . '/cloud/' . $which);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$f = $r[0];
|
||||
|
||||
$channel = channelx_by_n($owner);
|
||||
@@ -138,7 +143,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
||||
if($json_return)
|
||||
json_return_and_die([ 'success' => true ]);
|
||||
|
||||
goaway(dirname($url));
|
||||
//goaway(dirname($url));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,23 +2,24 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
/**
|
||||
* module: getfile
|
||||
*
|
||||
*
|
||||
* used for synchronising files and photos across clones
|
||||
*
|
||||
*
|
||||
* The site initiating the file operation will send a sync packet to known clones.
|
||||
* They will respond by building the DB structures they require, then will provide a
|
||||
* post request to this site to grab the file data. This is sent as a stream direct to
|
||||
* disk at the other end, avoiding memory issues.
|
||||
*
|
||||
* Since magic-auth cannot easily be used by the CURL process at the other end,
|
||||
* we will require a signed request which includes a timestamp. This should not be
|
||||
* used without SSL and is potentially vulnerable to replay if an attacker decrypts
|
||||
* we will require a signed request which includes a timestamp. This should not be
|
||||
* used without SSL and is potentially vulnerable to replay if an attacker decrypts
|
||||
* the SSL traffic fast enough. The amount of time slop is configurable but defaults
|
||||
* to 3 minutes.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -53,13 +54,13 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
$keyId = $sigblock['keyId'];
|
||||
|
||||
if($keyId) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where hubloc_addr = '%s' limit 1",
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where hubloc_id_url = '%s'",
|
||||
dbesc(str_replace('acct:','',$keyId))
|
||||
);
|
||||
if($r) {
|
||||
$hubloc = $r[0];
|
||||
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
$hubloc = Libzot::zot_record_preferred($r);
|
||||
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
|
||||
$header_verified = true;
|
||||
}
|
||||
@@ -73,15 +74,15 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
logger('post: ' . print_r($_POST,true),LOGGER_DEBUG,LOG_INFO);
|
||||
if($header_verified) {
|
||||
logger('HTTPSig verified');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$channel = channelx_by_hash($hash);
|
||||
|
||||
if((! $channel) || (! $time) || (! $sig)) {
|
||||
logger('error: missing info');
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if(isset($_POST['resolution']))
|
||||
$resolution = intval($_POST['resolution']);
|
||||
elseif(substr($resource,-2,1) == '-') {
|
||||
@@ -90,21 +91,21 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else {
|
||||
$resolution = (-1);
|
||||
}
|
||||
}
|
||||
|
||||
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
|
||||
if($slop < 1)
|
||||
$slop = 3;
|
||||
|
||||
|
||||
$d1 = datetime_convert('UTC','UTC',"now + $slop minutes");
|
||||
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
|
||||
|
||||
$d2 = datetime_convert('UTC','UTC',"now - $slop minutes");
|
||||
|
||||
if(! $header_verified) {
|
||||
if(($time > $d1) || ($time < $d2)) {
|
||||
logger('time outside allowable range');
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if(! rsa_verify($hash . '.' . $time,base64url_decode($sig),$channel['channel_pubkey'])) {
|
||||
logger('verify failed.');
|
||||
killme();
|
||||
@@ -136,20 +137,20 @@ class Getfile extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
echo dbunescbin($r[0]['content']);
|
||||
}
|
||||
}
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
$r = attach_by_hash($resource,$channel['channel_hash'],$revision);
|
||||
|
||||
|
||||
if(! $r['success']) {
|
||||
logger('attach_by_hash failed: ' . $r['message']);
|
||||
notice( $r['message'] . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$unsafe_types = array('text/html','text/css','application/javascript');
|
||||
|
||||
|
||||
if(in_array($r['data']['filetype'],$unsafe_types) && (! channel_codeallowed($channel['channel_id']))) {
|
||||
header('Content-type: text/plain');
|
||||
}
|
||||
|
||||
@@ -38,9 +38,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
if(!local_channel())
|
||||
return;
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = argv(1);
|
||||
}
|
||||
@@ -87,15 +84,9 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
goaway(z_root() . '/moderate/' . $target_item['id']);
|
||||
}
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sql_extra = item_permissions_sql($sys['channel_id']);
|
||||
@@ -148,8 +139,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
nav_set_selected('HQ');
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
|
||||
if($target_item) {
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
@@ -182,8 +171,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => 1,
|
||||
'$page' => '1',
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
@@ -249,8 +237,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
else {
|
||||
$r = [];
|
||||
@@ -275,6 +261,8 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
notice( t('Nothing to import.') . EOL);
|
||||
return;
|
||||
} else if(strpos($old_address, '@')) {
|
||||
// if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
|
||||
// if you copy the identity address from your profile page, make it work for convenience - WARNING: this is a utf-8 variant and NOT an ASCII ampersand. Please do not edit.
|
||||
$old_address = str_replace('@', '@', $old_address);
|
||||
}
|
||||
|
||||
@@ -231,7 +231,8 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
'hubloc_host' => \App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/post',
|
||||
'hubloc_sitekey' => get_config('system','pubkey'),
|
||||
'hubloc_updated' => datetime_convert()
|
||||
'hubloc_updated' => datetime_convert(),
|
||||
'hubloc_id_url' => channel_url($channel)
|
||||
]
|
||||
);
|
||||
|
||||
@@ -442,7 +443,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) {
|
||||
$abook['abook_not_here'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if($abook['abook_self']) {
|
||||
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
|
||||
@@ -584,11 +585,6 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
if(array_key_exists('item_id',$data) && $data['item_id'])
|
||||
import_item_ids($channel,$data['item_id']);
|
||||
|
||||
// send out refresh requests
|
||||
// notify old server that it may no longer be primary.
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id']));
|
||||
|
||||
// This will indirectly perform a refresh_all *and* update the directory
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id']));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,13 +7,10 @@ use Zotlabs\Lib\Libsync;
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
require_once('include/conversation.php');
|
||||
|
||||
class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
|
||||
private function reaction_to_activity($reaction) {
|
||||
|
||||
$acts = [
|
||||
@@ -24,7 +21,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
'abstain' => ACTIVITY_ABSTAIN ,
|
||||
'attendyes' => ACTIVITY_ATTEND ,
|
||||
'attendno' => ACTIVITY_ATTENDNO ,
|
||||
'attendmaybe' => ACTIVITY_ATTENDMAYBE
|
||||
'attendmaybe' => ACTIVITY_ATTENDMAYBE
|
||||
];
|
||||
|
||||
// unlike (etc.) reactions are an undo of positive reactions, rather than a negative action.
|
||||
@@ -42,10 +39,49 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
private function like_response($arr) {
|
||||
|
||||
if($arr['conv_mode'] === 'channel') {
|
||||
$parts = explode('@', $arr['owner_xchan']['xchan_addr']);
|
||||
profile_load($parts[0]);
|
||||
}
|
||||
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
$activities = q("SELECT item.*, item.id AS item_id FROM item
|
||||
WHERE uid = %d $item_normal
|
||||
AND thr_parent = '%s'
|
||||
AND verb IN ('%s', '%s', '%s', '%s', '%s')",
|
||||
intval($arr['item']['uid']),
|
||||
dbesc($arr['item']['mid']),
|
||||
dbesc(ACTIVITY_LIKE),
|
||||
dbesc(ACTIVITY_DISLIKE),
|
||||
dbesc(ACTIVITY_ATTEND),
|
||||
dbesc(ACTIVITY_ATTENDNO),
|
||||
dbesc(ACTIVITY_ATTENDMAYBE)
|
||||
);
|
||||
|
||||
xchan_query($activities,true);
|
||||
|
||||
$convitems[] = $arr['item'];
|
||||
$convitems = array_merge($convitems, $activities);
|
||||
|
||||
$convitems = fetch_post_tags($convitems,true);
|
||||
|
||||
$ret = [
|
||||
'success' => 1,
|
||||
'orig_id' => $arr['orig_item_id'], //this is required for pubstream items where $item_id != $item['id']
|
||||
'id' => $arr['item']['id'],
|
||||
'html' => conversation($convitems, $arr['conv_mode'], true, 'r_preview'),
|
||||
];
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
public function get() {
|
||||
|
||||
|
||||
$o = EMPTY_STR;
|
||||
|
||||
$sys_channel = get_sys_channel();
|
||||
@@ -56,7 +92,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
if((! $observer) || ($interactive)) {
|
||||
$o .= '<h1>' . t('Like/Dislike') . '</h1>';
|
||||
$o .= EOL . EOL;
|
||||
|
||||
|
||||
if(! $observer) {
|
||||
$_SESSION['return_url'] = \App::$query_string;
|
||||
$o .= t('This action is restricted to members.') . EOL;
|
||||
@@ -64,16 +100,17 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$verb = notags(trim($_GET['verb']));
|
||||
|
||||
$mode = (($_GET['conv_mode'] === 'channel') ? 'channel' : 'network');
|
||||
|
||||
if(! $verb)
|
||||
$verb = 'like';
|
||||
|
||||
|
||||
$activity = $this->reaction_to_activity($verb);
|
||||
|
||||
if(! $activity) {
|
||||
return EMPTY_STR;
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$is_rsvp = false;
|
||||
@@ -86,23 +123,23 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$object = $target = null;
|
||||
$post_type = EMPTY_STR;
|
||||
$objtype = EMPTY_STR;
|
||||
|
||||
|
||||
if(argc() == 3) {
|
||||
|
||||
|
||||
if(! $observer)
|
||||
killme();
|
||||
|
||||
|
||||
$extended_like = true;
|
||||
$obj_type = argv(1);
|
||||
$obj_id = argv(2);
|
||||
$public = true;
|
||||
|
||||
|
||||
if($obj_type == 'profile') {
|
||||
$r = q("select * from profile where profile_guid = '%s' limit 1",
|
||||
dbesc(argv(2))
|
||||
);
|
||||
if(! $r)
|
||||
killme();
|
||||
killme();
|
||||
$owner_uid = $r[0]['uid'];
|
||||
if($r[0]['is_default'])
|
||||
$public = true;
|
||||
@@ -128,54 +165,54 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
$post_type = t('channel');
|
||||
$objtype = ACTIVITY_OBJ_PROFILE;
|
||||
|
||||
|
||||
$profile = $r[0];
|
||||
}
|
||||
elseif($obj_type == 'thing') {
|
||||
|
||||
|
||||
$r = q("select * from obj where obj_type = %d and obj_obj = '%s' limit 1",
|
||||
intval(TERM_OBJ_THING),
|
||||
dbesc(argv(2))
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
if($interactive) {
|
||||
notice( t('Invalid request.') . EOL);
|
||||
return $o;
|
||||
}
|
||||
killme();
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$owner_uid = $r[0]['obj_channel'];
|
||||
|
||||
|
||||
$allow_cid = $r[0]['allow_cid'];
|
||||
$allow_gid = $r[0]['allow_gid'];
|
||||
$deny_cid = $r[0]['deny_cid'];
|
||||
$deny_gid = $r[0]['deny_gid'];
|
||||
if($allow_cid || $allow_gid || $deny_cid || $deny_gid)
|
||||
if($allow_cid || $allow_gid || $deny_cid || $deny_gid)
|
||||
$public = false;
|
||||
|
||||
|
||||
$post_type = t('thing');
|
||||
$objtype = ACTIVITY_OBJ_PROFILE;
|
||||
$tgttype = ACTIVITY_OBJ_THING;
|
||||
|
||||
|
||||
$links = array();
|
||||
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
|
||||
'href' => z_root() . '/thing/' . $r[0]['obj_obj']);
|
||||
if($r[0]['imgurl'])
|
||||
if($r[0]['imgurl'])
|
||||
$links[] = array('rel' => 'photo', 'href' => $r[0]['obj_imgurl']);
|
||||
|
||||
|
||||
$target = json_encode(array(
|
||||
'type' => $tgttype,
|
||||
'title' => $r[0]['obj_term'],
|
||||
'id' => z_root() . '/thing/' . $r[0]['obj_obj'],
|
||||
'link' => $links
|
||||
));
|
||||
|
||||
|
||||
$plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]';
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(! ($owner_uid && $r)) {
|
||||
if($interactive) {
|
||||
notice( t('Invalid request.') . EOL);
|
||||
@@ -183,11 +220,11 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
// The resultant activity is going to be a wall-to-wall post, so make sure this is allowed
|
||||
|
||||
|
||||
$perms = get_all_perms($owner_uid,$observer['xchan_hash']);
|
||||
|
||||
|
||||
if(! ($perms['post_like'] && $perms['view_profile'])) {
|
||||
if($interactive) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
@@ -195,7 +232,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$ch = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
|
||||
intval($owner_uid)
|
||||
);
|
||||
@@ -206,14 +243,14 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if(! $plink)
|
||||
$plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]';
|
||||
|
||||
|
||||
$object = json_encode(Activity::fetch_profile([ 'id' => channel_url($ch[0]) ]));
|
||||
|
||||
// second like of the same thing is "undo" for the first like
|
||||
|
||||
|
||||
$z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1",
|
||||
intval($ch[0]['channel_id']),
|
||||
dbesc($observer['xchan_hash']),
|
||||
@@ -221,11 +258,11 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
dbesc(($tgttype)?$tgttype:$objtype),
|
||||
dbesc($obj_id)
|
||||
);
|
||||
|
||||
|
||||
if($z) {
|
||||
$z[0]['deleted'] = 1;
|
||||
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $z));
|
||||
|
||||
|
||||
q("delete from likes where id = %d",
|
||||
intval($z[0]['id'])
|
||||
);
|
||||
@@ -248,17 +285,17 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(! $observer)
|
||||
killme();
|
||||
|
||||
|
||||
// this is used to like an item or comment
|
||||
|
||||
|
||||
$item_id = ((argc() == 2) ? notags(trim(argv(1))) : 0);
|
||||
|
||||
|
||||
logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG);
|
||||
|
||||
|
||||
// get the item. Allow linked photos (which are normally hidden) to be liked
|
||||
|
||||
$r = q("SELECT * FROM item WHERE id = %d
|
||||
and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
|
||||
$r = q("SELECT * FROM item WHERE 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($item_id)
|
||||
);
|
||||
@@ -304,7 +341,7 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$thread_owner = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['author_xchan'])
|
||||
);
|
||||
@@ -312,15 +349,14 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$item_author = $r[0];
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
$verbs = " '".dbesc($activity)."' ";
|
||||
|
||||
$multi_undo = false;
|
||||
|
||||
|
||||
$multi_undo = false;
|
||||
|
||||
// event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
|
||||
// we need to eradicate your first choice.
|
||||
|
||||
// we need to eradicate your first choice.
|
||||
|
||||
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
|
||||
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
|
||||
$multi_undo = 1;
|
||||
@@ -329,16 +365,16 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
|
||||
$multi_undo = true;
|
||||
}
|
||||
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
|
||||
$r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( $verbs ) $item_normal
|
||||
AND author_xchan = '%s' AND thr_parent = '%s' and uid = %d ",
|
||||
dbesc($observer['xchan_hash']),
|
||||
dbesc($item['mid']),
|
||||
intval($owner_uid)
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
// already liked it. Drop that item.
|
||||
require_once('include/items.php');
|
||||
@@ -350,30 +386,41 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
intval($rr['parent']),
|
||||
intval($rr['uid'])
|
||||
);
|
||||
// Prior activity was a duplicate of the one we're submitting, just undo it;
|
||||
// Prior activity was a duplicate of the one we're submitting, just undo it;
|
||||
// don't fall through and create another
|
||||
if(activity_match($rr['verb'],$activity))
|
||||
$multi_undo = false;
|
||||
|
||||
|
||||
// drop_item was not done interactively, so we need to invoke the notifier
|
||||
// in order to push the changes to connections
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$rr['id']));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if($interactive)
|
||||
return;
|
||||
|
||||
if(! $multi_undo)
|
||||
killme();
|
||||
|
||||
if(! $multi_undo) {
|
||||
$ret = self::like_response([
|
||||
'item' => $item,
|
||||
'orig_item_id' => $item_id,
|
||||
'owner_xchan' => $thread_owner,
|
||||
'conv_mode' => $mode
|
||||
]);
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$uuid = item_message_id();
|
||||
|
||||
|
||||
$arr = array();
|
||||
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = z_root() . (($is_rsvp) ? '/activity/' : '/item/') . $uuid;
|
||||
|
||||
@@ -386,38 +433,38 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
|
||||
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
|
||||
$post_type = t('event');
|
||||
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
|
||||
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||
|
||||
if($objtype === ACTIVITY_OBJ_NOTE && (! intval($item['item_thread_top'])))
|
||||
$objtype = ACTIVITY_OBJ_COMMENT;
|
||||
|
||||
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
|
||||
$object = json_encode(Activity::fetch_item( [ 'id' => $item['mid'] ]));
|
||||
|
||||
if(! intval($item['item_thread_top']))
|
||||
$post_type = 'comment';
|
||||
|
||||
$post_type = 'comment';
|
||||
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_notshown'] = 1;
|
||||
$arr['item_type'] = $item['item_type'];
|
||||
|
||||
|
||||
if(intval($item['item_wall']))
|
||||
$arr['item_wall'] = 1;
|
||||
|
||||
|
||||
// if this was a linked photo and was hidden, unhide it.
|
||||
|
||||
|
||||
if(intval($item['item_hidden'])) {
|
||||
$r = q("update item set item_hidden = 0 where id = %d",
|
||||
intval($item['id'])
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if($verb === 'like')
|
||||
$bodyverb = t('%1$s likes %2$s\'s %3$s');
|
||||
if($verb === 'dislike')
|
||||
@@ -434,12 +481,12 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
|
||||
if($verb === 'attendmaybe')
|
||||
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
|
||||
|
||||
|
||||
if(! isset($bodyverb))
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
if($extended_like) {
|
||||
$ulink = '[zrl=' . $ch[0]['xchan_url'] . '][bdi]' . $ch[0]['xchan_name'] . '[/bdi][/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
|
||||
@@ -456,65 +503,64 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
$deny_cid = $item['deny_cid'];
|
||||
$deny_gid = $item['deny_gid'];
|
||||
$private = $item['private'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
|
||||
$arr['uid'] = $owner_uid;
|
||||
|
||||
|
||||
$arr['item_flags'] = $item_flags;
|
||||
$arr['item_wall'] = $item_wall;
|
||||
$arr['item_flags'] = $item['item_flags'];
|
||||
$arr['item_wall'] = $item['item_wall'];
|
||||
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
|
||||
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
|
||||
$arr['author_xchan'] = $observer['xchan_hash'];
|
||||
|
||||
|
||||
|
||||
|
||||
$arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
|
||||
if($obj_type === 'thing' && $r[0]['imgurl']) {
|
||||
$arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
|
||||
}
|
||||
}
|
||||
if($obj_type === 'profile') {
|
||||
if($public) {
|
||||
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
|
||||
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
|
||||
}
|
||||
else
|
||||
$arr['body'] .= "\n\n[zmg=80x80]" . $profile['thumb'] . '[/zmg]';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$arr['verb'] = $activity;
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['obj'] = $object;
|
||||
|
||||
|
||||
if($target) {
|
||||
$arr['tgt_type'] = $tgttype;
|
||||
$arr['target'] = $target;
|
||||
}
|
||||
|
||||
|
||||
$arr['allow_cid'] = $allow_cid;
|
||||
$arr['allow_gid'] = $allow_gid;
|
||||
$arr['deny_cid'] = $deny_cid;
|
||||
$arr['deny_gid'] = $deny_gid;
|
||||
$arr['item_private'] = $private;
|
||||
|
||||
|
||||
call_hooks('post_local',$arr);
|
||||
|
||||
|
||||
$post = item_store($arr);
|
||||
$post = item_store($arr);
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
// save the conversation from expiration
|
||||
|
||||
if(local_channel() && array_key_exists('item',$post) && (intval($post['item']['id']) != intval($post['item']['parent'])))
|
||||
retain_item($post['item']['parent']);
|
||||
|
||||
retain_item($post['item']['parent']);
|
||||
|
||||
$arr['id'] = $post_id;
|
||||
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
|
||||
|
||||
|
||||
if($extended_like) {
|
||||
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
|
||||
intval($ch[0]['channel_id']),
|
||||
@@ -536,22 +582,26 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
dbesc($obj_id)
|
||||
);
|
||||
if($r)
|
||||
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
|
||||
|
||||
Libsync::build_sync_packet($ch[0]['channel_id'],array('likes' => $r));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$post_id));
|
||||
|
||||
|
||||
if($interactive) {
|
||||
notice( t('Action completed.') . EOL);
|
||||
$o .= t('Thank you.');
|
||||
return $o;
|
||||
}
|
||||
|
||||
killme();
|
||||
|
||||
$ret = self::like_response([
|
||||
'item' => $item,
|
||||
'orig_item_id' => $item_id,
|
||||
'owner_xchan' => $thread_owner,
|
||||
'conv_mode' => $mode
|
||||
]);
|
||||
json_return_and_die($ret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,22 +19,22 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$type = ((argc() > 1) ? argv(1) : 0);
|
||||
if (is_numeric($type)) {
|
||||
$item_id = intval($type);
|
||||
$type='item';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$item_id = ((argc() > 2) ? intval(argv(2)) : 0);
|
||||
}
|
||||
|
||||
|
||||
if(! $item_id)
|
||||
killme();
|
||||
|
||||
|
||||
if (! in_array($type, array('item', 'photo', 'attach', 'event', 'menu_item', 'chatroom')))
|
||||
killme();
|
||||
|
||||
|
||||
// we have different naming in in menu_item table and chatroom table
|
||||
switch($type) {
|
||||
case 'menu_item':
|
||||
@@ -47,17 +47,17 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$id = 'id';
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT * FROM %s WHERE $id = %d LIMIT 1",
|
||||
dbesc($type),
|
||||
intval($item_id)
|
||||
);
|
||||
|
||||
|
||||
if(! $r)
|
||||
killme();
|
||||
|
||||
|
||||
$item = $r[0];
|
||||
|
||||
|
||||
//we have different naming in in menu_item table and chatroom table
|
||||
switch($type) {
|
||||
case 'menu_item':
|
||||
@@ -70,37 +70,37 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$uid = $item['uid'];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if($uid != local_channel()) {
|
||||
echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>';
|
||||
killme();
|
||||
}
|
||||
|
||||
if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
|
||||
|
||||
if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
|
||||
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
|
||||
|
||||
|
||||
// if the post is private, but public_policy is blank ("visible to the internet"), and there aren't any
|
||||
// specific recipients, we're the recipient of a post with "bcc" or targeted recipients; so we'll just show it
|
||||
// as unknown specific recipients. The sender will have the visibility list and will fall through to the
|
||||
// next section.
|
||||
|
||||
|
||||
echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$allowed_users = expand_acl($item['allow_cid']);
|
||||
$allowed_groups = expand_acl($item['allow_gid']);
|
||||
$deny_users = expand_acl($item['deny_cid']);
|
||||
$deny_groups = expand_acl($item['deny_gid']);
|
||||
|
||||
|
||||
$o = '<div class="dropdown-item">' . t('Visible to:') . '</div>';
|
||||
$l = array();
|
||||
|
||||
|
||||
stringify_array_elms($allowed_groups,true);
|
||||
stringify_array_elms($allowed_users,true);
|
||||
stringify_array_elms($deny_groups,true);
|
||||
stringify_array_elms($deny_users,true);
|
||||
|
||||
|
||||
|
||||
$profile_groups = [];
|
||||
if($allowed_groups) {
|
||||
@@ -113,24 +113,24 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
if(count($profile_groups)) {
|
||||
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>';
|
||||
}
|
||||
|
||||
if(count($allowed_groups)) {
|
||||
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>';
|
||||
}
|
||||
if(count($allowed_users)) {
|
||||
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>';
|
||||
if($atokens) {
|
||||
foreach($atokens as $at) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
|
||||
$l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>';
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
if(count($profile_groups)) {
|
||||
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>';
|
||||
}
|
||||
|
||||
@@ -158,18 +158,18 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
if(count($deny_groups)) {
|
||||
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>';
|
||||
}
|
||||
if(count($deny_users)) {
|
||||
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>';
|
||||
|
||||
if($atokens) {
|
||||
foreach($atokens as $at) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) {
|
||||
$l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>';
|
||||
}
|
||||
}
|
||||
@@ -177,11 +177,11 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo $o . implode($l);
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -8,55 +8,65 @@ use Zotlabs\Daemon\Master;
|
||||
class Locs extends Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
|
||||
if($_REQUEST['primary']) {
|
||||
$hubloc_id = intval($_REQUEST['primary']);
|
||||
if($hubloc_id) {
|
||||
|
||||
|
||||
$r = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' limit 1",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
notice( t('Location not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
q("UPDATE hubloc SET hubloc_primary = 0 WHERE hubloc_primary = 1 AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_portable_id'])
|
||||
);
|
||||
|
||||
q("UPDATE hubloc SET hubloc_primary = 1 WHERE hubloc_id = %d AND hubloc_hash = '%s'",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
$x = q("select * from hubloc where hubloc_id = %d and hubloc_hash = '%s' ",
|
||||
intval($hubloc_id),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
hubloc_change_primary($x[0]);
|
||||
}
|
||||
|
||||
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($_REQUEST['drop']) {
|
||||
$hubloc_id = intval($_REQUEST['drop']);
|
||||
|
||||
|
||||
if($hubloc_id) {
|
||||
$r = q("select * from hubloc where hubloc_id = %d and hubloc_url != '%s' and hubloc_hash = '%s' limit 1",
|
||||
intval($hubloc_id),
|
||||
dbesc(z_root()),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
notice( t('Location not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(intval($r[0]['hubloc_primary'])) {
|
||||
$x = q("select hubloc_id from hubloc where hubloc_primary = 1 and hubloc_hash = '%s'",
|
||||
dbesc($channel['channel_hash'])
|
||||
@@ -70,7 +80,7 @@ class Locs extends Controller {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
q("UPDATE hubloc SET hubloc_deleted = 1 WHERE hubloc_id_url = '%s' AND (hubloc_hash = '%s' OR hubloc_hash = '%s')",
|
||||
dbesc($r[0]['hubloc_id_url']),
|
||||
dbesc($channel['channel_hash']),
|
||||
@@ -78,44 +88,41 @@ class Locs extends Controller {
|
||||
);
|
||||
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
|
||||
if($_REQUEST['sync']) {
|
||||
Master::Summon( [ 'Notifier', 'refresh_all', $channel['channel_id'] ] );
|
||||
info( t('Syncing locations') . EOL);
|
||||
goaway(z_root() . '/locs');
|
||||
}
|
||||
|
||||
|
||||
|
||||
$r = q("select * from hubloc where hubloc_hash = '%s'",
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
|
||||
if(! $r) {
|
||||
notice( t('No locations found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
$r[$x]['primary'] = (intval($r[$x]['hubloc_primary']) ? true : false);
|
||||
$r[$x]['deleted'] = (intval($r[$x]['hubloc_deleted']) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
$o = replace_macros(get_markup_template('locmanage.tpl'), array(
|
||||
'$header' => t('Manage Channel Locations'),
|
||||
'$loc' => t('Location'),
|
||||
@@ -129,8 +136,8 @@ class Locs extends Controller {
|
||||
'$last_resort' => t('Use this form to drop the location if the hub is no longer operating.'),
|
||||
'$hubs' => $r
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -44,10 +44,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o = '';
|
||||
|
||||
if($load) {
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
$arr = array('query' => App::$query_string);
|
||||
|
||||
call_hooks('network_content_init', $arr);
|
||||
@@ -64,7 +60,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$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']) : '');
|
||||
$static = ((x($_GET,'static')) ? intval($_GET['static']) : 0);
|
||||
$gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0);
|
||||
$category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
|
||||
$hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : '');
|
||||
@@ -213,8 +208,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$status_editor = status_editor($a,$x,false,'Network');
|
||||
$o .= $status_editor;
|
||||
|
||||
$static = channel_manual_conv_update(local_channel());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +363,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
'$dm' => (($dm) ? $dm : '0'),
|
||||
'$nouveau' => (($nouveau) ? $nouveau : '0'),
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||
'$search' => (($search) ? urlencode($search) : ''),
|
||||
@@ -494,8 +486,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$parents_str = '';
|
||||
|
||||
$simple_update = (($update) ? " and item_unseen = 1 " : '');
|
||||
|
||||
// This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day
|
||||
// or three and look at your matrix page - after opening up your browser. The first page loads just as it
|
||||
// should. All of a sudden a few seconds later, page 2 will get inserted at the beginning of the page
|
||||
@@ -507,16 +497,11 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
// which "arrived as you were reading page 1". We're going to do this
|
||||
// by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items
|
||||
// which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers...
|
||||
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
|
||||
if($nouveau && $load) {
|
||||
// "New Item View" - show all items unthreaded in reverse created date order
|
||||
$items = q("SELECT item.*, item.id AS item_id, created FROM item
|
||||
@@ -524,7 +509,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$net_query
|
||||
WHERE true $uids $item_normal
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$simple_update
|
||||
$sql_extra $sql_options $sql_nets
|
||||
$net_query2
|
||||
ORDER BY item.created DESC $pager_sql "
|
||||
@@ -570,7 +554,6 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra3 $sql_extra $sql_options $sql_nets $net_query2"
|
||||
);
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
// Then fetch all the children of the parents that are on this page
|
||||
@@ -605,6 +588,8 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(($items) && (! $update))
|
||||
$o .= alt_pager(count($items));
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ use Zotlabs\Web\Controller;
|
||||
* See spec/OpenWebAuth/Home.md
|
||||
* Requests to this endpoint should be signed using HTTP Signatures
|
||||
* using the 'Authorization: Signature' authentication method
|
||||
* If the signature verifies a token is returned.
|
||||
* If the signature verifies a token is returned.
|
||||
*
|
||||
* This token may be exchanged for an authenticated cookie.
|
||||
* This token may be exchanged for an authenticated cookie.
|
||||
*/
|
||||
|
||||
class Owa extends Controller {
|
||||
@@ -31,36 +31,34 @@ class Owa extends Controller {
|
||||
if ($sigblock) {
|
||||
$keyId = $sigblock['keyId'];
|
||||
if ($keyId) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
|
||||
dbesc(str_replace('acct:','',$keyId)),
|
||||
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
|
||||
WHERE hubloc_id_url = '%s'",
|
||||
dbesc($keyId)
|
||||
);
|
||||
if (! $r) {
|
||||
$found = discover_by_webbie(str_replace('acct:','',$keyId));
|
||||
if ($found) {
|
||||
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
|
||||
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
|
||||
dbesc(str_replace('acct:','',$keyId)),
|
||||
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
|
||||
WHERE hubloc_id_url = '%s'",
|
||||
dbesc($keyId)
|
||||
);
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $hubloc) {
|
||||
$verified = HTTPSig::verify(file_get_contents('php://input'));
|
||||
$verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
|
||||
if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
|
||||
logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
|
||||
logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA);
|
||||
logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA);
|
||||
$ret['success'] = true;
|
||||
$token = random_string(32);
|
||||
Verify::create('owt',0,$token,$hubloc['hubloc_addr']);
|
||||
Verify::create('owt',0,$token,$hubloc['hubloc_id_url']);
|
||||
$result = '';
|
||||
openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
|
||||
$ret['encrypted_token'] = base64url_encode($result);
|
||||
break;
|
||||
} else {
|
||||
logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_addr']);
|
||||
logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
call_hooks('cache_mode_hook', $cache_mode);
|
||||
|
||||
$observer_xchan = get_observer_hash();
|
||||
$cachecontrol = '';
|
||||
$cachecontrol = ', no-cache';
|
||||
|
||||
if(isset($type)) {
|
||||
|
||||
@@ -81,18 +81,18 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
}
|
||||
}
|
||||
|
||||
if(! $data) {
|
||||
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
|
||||
call_hooks('get_profile_photo',$d);
|
||||
|
||||
$resolution = $d['imgscale'];
|
||||
$uid = $d['channel_id'];
|
||||
$default = $d['default'];
|
||||
$data = $d['data'];
|
||||
$mimetype = $d['mimetype'];
|
||||
$modified = 0;
|
||||
if(! $data) {
|
||||
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
|
||||
call_hooks('get_profile_photo',$d);
|
||||
|
||||
$resolution = $d['imgscale'];
|
||||
$uid = $d['channel_id'];
|
||||
$default = $d['default'];
|
||||
$data = $d['data'];
|
||||
$mimetype = $d['mimetype'];
|
||||
$modified = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(! $data) {
|
||||
@@ -102,7 +102,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$modified = filemtime($default);
|
||||
}
|
||||
|
||||
$cachecontrol = ', must-revalidate';
|
||||
$cachecontrol .= ', must-revalidate';
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -169,6 +169,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
$url = z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($url);
|
||||
goaway($url);
|
||||
}
|
||||
$cachecontrol = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,7 +272,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
// in the event that infrastructure caching is present.
|
||||
$smaxage = intval($maxage/12);
|
||||
|
||||
header("Cache-Control: no-cache, s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol);
|
||||
header("Cache-Control: s-maxage=" . $smaxage . ", max-age=" . $maxage . $cachecontrol);
|
||||
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,11 +12,11 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
function init() {
|
||||
|
||||
nav_set_selected('Profiles', 'settings/profiles');
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if((argc() > 2) && (argv(1) === "drop") && intval(argv(2))) {
|
||||
$r = q("SELECT * FROM profile WHERE id = %d AND uid = %d AND is_default = 0 LIMIT 1",
|
||||
intval(argv(2)),
|
||||
@@ -28,11 +28,11 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
return; // NOTREACHED
|
||||
}
|
||||
$profile_guid = $r['profile_guid'];
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_drop', 't');
|
||||
|
||||
|
||||
// move every contact using this profile as their default to the user default
|
||||
|
||||
|
||||
$r = q("UPDATE abook SET abook_profile = (SELECT profile_guid FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1) WHERE abook_profile = '%s' AND abook_channel = %d ",
|
||||
intval(local_channel()),
|
||||
dbesc($profile_guid),
|
||||
@@ -44,34 +44,34 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
if($r)
|
||||
info( t('Profile deleted.') . EOL);
|
||||
|
||||
// @fixme this is a much more complicated sync - add any changed abook entries and
|
||||
|
||||
// @fixme this is a much more complicated sync - add any changed abook entries and
|
||||
// also add deleted flag to profile structure
|
||||
// profiles_build_sync is just here as a placeholder - it doesn't work at all here
|
||||
|
||||
|
||||
// profiles_build_sync(local_channel());
|
||||
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if((argc() > 1) && (argv(1) === 'new')) {
|
||||
|
||||
|
||||
// check_form_security_token_redirectOnErr('/profiles', 'profile_new', 't');
|
||||
|
||||
|
||||
$r0 = q("SELECT id FROM profile WHERE uid = %d",
|
||||
intval(local_channel()));
|
||||
$num_profiles = count($r0);
|
||||
|
||||
|
||||
$name = t('Profile-') . ($num_profiles + 1);
|
||||
|
||||
|
||||
$r1 = q("SELECT fullname, photo, thumb FROM profile WHERE uid = %d AND is_default = 1 LIMIT 1",
|
||||
intval(local_channel()));
|
||||
|
||||
|
||||
$r2 = profile_store_lowlevel(
|
||||
[
|
||||
'aid' => intval(get_account_id()),
|
||||
@@ -83,27 +83,27 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'thumb' => $r1[0]['thumb']
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$r3 = q("SELECT id FROM profile WHERE uid = %d AND profile_name = '%s' LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
|
||||
info( t('New profile created.') . EOL);
|
||||
if(count($r3) == 1)
|
||||
goaway(z_root() . '/profiles/' . $r3[0]['id']);
|
||||
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if((argc() > 2) && (argv(1) === 'clone')) {
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_clone', 't');
|
||||
|
||||
|
||||
$r0 = q("SELECT id FROM profile WHERE uid = %d",
|
||||
intval(local_channel()));
|
||||
$num_profiles = count($r0);
|
||||
|
||||
|
||||
$name = t('Profile-') . ($num_profiles + 1);
|
||||
$r1 = q("SELECT * FROM profile WHERE uid = %d AND id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
@@ -116,30 +116,30 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
unset($r1[0]['id']);
|
||||
$r1[0]['is_default'] = 0;
|
||||
$r1[0]['publish'] = 0;
|
||||
$r1[0]['publish'] = 0;
|
||||
$r1[0]['profile_name'] = dbesc($name);
|
||||
$r1[0]['profile_guid'] = dbesc(random_string());
|
||||
|
||||
|
||||
create_table_from_array('profile', $r1[0]);
|
||||
|
||||
|
||||
$r3 = q("SELECT id FROM profile WHERE uid = %d AND profile_name = '%s' LIMIT 1",
|
||||
intval(local_channel()),
|
||||
dbesc($name)
|
||||
);
|
||||
info( t('New profile created.') . EOL);
|
||||
|
||||
|
||||
profiles_build_sync(local_channel());
|
||||
|
||||
|
||||
if(($r3) && (count($r3) == 1))
|
||||
goaway(z_root() . '/profiles/' . $r3[0]['id']);
|
||||
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
|
||||
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
if((argc() > 2) && (argv(1) === 'export')) {
|
||||
|
||||
|
||||
$r1 = q("SELECT * FROM profile WHERE uid = %d AND id = %d LIMIT 1",
|
||||
intval(local_channel()),
|
||||
intval(argv(2))
|
||||
@@ -151,7 +151,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
header('content-type: application/octet_stream');
|
||||
header('content-disposition: attachment; filename="' . $r1[0]['profile_name'] . '.json"' );
|
||||
|
||||
|
||||
unset($r1[0]['id']);
|
||||
unset($r1[0]['aid']);
|
||||
unset($r1[0]['uid']);
|
||||
@@ -162,10 +162,10 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
echo json_encode($r1[0]);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Run profile_load() here to make sure the theme is set before
|
||||
// we start loading content
|
||||
if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
|
||||
@@ -187,28 +187,28 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
\App::$error = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$chan = \App::get_channel();
|
||||
|
||||
|
||||
profile_load($chan['channel_address'],$r[0]['id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
require_once('include/activities.php');
|
||||
|
||||
|
||||
$namechanged = false;
|
||||
|
||||
|
||||
|
||||
|
||||
// import from json export file.
|
||||
// Only import fields that are allowed on this hub
|
||||
|
||||
|
||||
if(x($_FILES,'userfile')) {
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
$filesize = intval($_FILES['userfile']['size']);
|
||||
@@ -230,10 +230,10 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
call_hooks('profile_post', $_POST);
|
||||
|
||||
|
||||
|
||||
|
||||
if((argc() > 1) && (argv(1) !== "new") && intval(argv(1))) {
|
||||
$orig = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1",
|
||||
intval(\App::$argv[1]),
|
||||
@@ -243,26 +243,26 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
notice( t('Profile not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
|
||||
|
||||
|
||||
|
||||
$is_default = (($orig[0]['is_default']) ? 1 : 0);
|
||||
|
||||
|
||||
$profile_name = notags(trim($_POST['profile_name']));
|
||||
if(! strlen($profile_name)) {
|
||||
notice( t('Profile Name is required.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$dob = $_POST['dob'] ? escape_tags(trim($_POST['dob'])) : '0000-00-00'; // FIXME: Needs to be validated?
|
||||
|
||||
|
||||
$y = substr($dob,0,4);
|
||||
if((! ctype_digit($y)) || ($y < 1900))
|
||||
$ignore_year = true;
|
||||
else
|
||||
$ignore_year = false;
|
||||
|
||||
|
||||
if($dob != '0000-00-00') {
|
||||
if(strpos($dob,'0000-') === 0) {
|
||||
$ignore_year = true;
|
||||
@@ -272,12 +272,12 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
if($ignore_year)
|
||||
$dob = '0000-' . $dob;
|
||||
}
|
||||
|
||||
|
||||
$name = escape_tags(trim($_POST['name']));
|
||||
|
||||
|
||||
if($orig[0]['fullname'] != $name) {
|
||||
$namechanged = true;
|
||||
|
||||
|
||||
$v = validate_channelname($name);
|
||||
if($v) {
|
||||
notice($v);
|
||||
@@ -285,7 +285,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$name = $orig[0]['fullname'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$pdesc = escape_tags(trim($_POST['pdesc']));
|
||||
$gender = escape_tags(trim($_POST['gender']));
|
||||
$address = escape_tags(trim($_POST['address']));
|
||||
@@ -301,10 +301,10 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$hometown = escape_tags(trim($_POST['hometown']));
|
||||
$politic = escape_tags(trim($_POST['politic']));
|
||||
$religion = escape_tags(trim($_POST['religion']));
|
||||
|
||||
|
||||
$likes = fix_mce_lf(escape_tags(trim($_POST['likes'])));
|
||||
$dislikes = fix_mce_lf(escape_tags(trim($_POST['dislikes'])));
|
||||
|
||||
|
||||
$about = fix_mce_lf(escape_tags(trim($_POST['about'])));
|
||||
$interest = fix_mce_lf(escape_tags(trim($_POST['interest'])));
|
||||
$contact = fix_mce_lf(escape_tags(trim($_POST['contact'])));
|
||||
@@ -316,11 +316,11 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$romance = fix_mce_lf(escape_tags(trim($_POST['romance'])));
|
||||
$work = fix_mce_lf(escape_tags(trim($_POST['work'])));
|
||||
$education = fix_mce_lf(escape_tags(trim($_POST['education'])));
|
||||
|
||||
|
||||
$hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
|
||||
|
||||
|
||||
// start fresh and create a new vcard. TODO: preserve the original guid or whatever else needs saving
|
||||
// $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null);
|
||||
// $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null);
|
||||
|
||||
$orig_vcard = null;
|
||||
|
||||
@@ -347,7 +347,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
5 => $postal_code,
|
||||
6 => $country_name
|
||||
];
|
||||
|
||||
|
||||
$profile_vcard = update_vcard($defcard,$orig_vcard);
|
||||
|
||||
$orig_vcard = \Sabre\VObject\Reader::read($profile_vcard);
|
||||
@@ -370,19 +370,19 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
linkify_tags($romance, local_channel());
|
||||
linkify_tags($work, local_channel());
|
||||
linkify_tags($education, local_channel());
|
||||
|
||||
|
||||
|
||||
|
||||
$with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : '');
|
||||
|
||||
|
||||
if(! strlen($howlong))
|
||||
$howlong = NULL_DATE;
|
||||
else
|
||||
$howlong = datetime_convert(date_default_timezone_get(),'UTC',$howlong);
|
||||
|
||||
|
||||
// linkify the relationship target if applicable
|
||||
|
||||
|
||||
$withchanged = false;
|
||||
|
||||
|
||||
if(strlen($with)) {
|
||||
if($with != strip_tags($orig[0]['partner'])) {
|
||||
$withchanged = true;
|
||||
@@ -392,7 +392,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$lookup = substr($lookup,1);
|
||||
$lookup = str_replace('_',' ', $lookup);
|
||||
$newname = $lookup;
|
||||
|
||||
|
||||
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1",
|
||||
dbesc($newname),
|
||||
intval(local_channel())
|
||||
@@ -407,8 +407,8 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$prf = $r[0]['xchan_url'];
|
||||
$newname = $r[0]['xchan_name'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if($prf) {
|
||||
$with = str_replace($lookup,'<a href="' . $prf . '">' . $newname . '</a>', $with);
|
||||
if(strpos($with,'@') === 0)
|
||||
@@ -418,7 +418,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
$with = $orig[0]['partner'];
|
||||
}
|
||||
|
||||
|
||||
$profile_fields_basic = get_profile_fields_basic();
|
||||
$profile_fields_advanced = get_profile_fields_advanced();
|
||||
$advanced = ((feature_enabled(local_channel(),'advanced_profiles')) ? true : false);
|
||||
@@ -426,7 +426,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$fields = $profile_fields_advanced;
|
||||
else
|
||||
$fields = $profile_fields_basic;
|
||||
|
||||
|
||||
$z = q("select * from profdef where true");
|
||||
if($z) {
|
||||
foreach($z as $zz) {
|
||||
@@ -453,7 +453,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$changes = array();
|
||||
$value = '';
|
||||
if($is_default) {
|
||||
@@ -513,12 +513,12 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$comma2 = (($region && $country_name) ? ', ' : '');
|
||||
$value = $locality . $comma1 . $region . $comma2 . $country_name;
|
||||
}
|
||||
|
||||
|
||||
profile_activity($changes,$value);
|
||||
|
||||
}
|
||||
|
||||
$r = q("UPDATE profile
|
||||
|
||||
}
|
||||
|
||||
$r = q("UPDATE profile
|
||||
SET profile_name = '%s',
|
||||
fullname = '%s',
|
||||
pdesc = '%s',
|
||||
@@ -591,10 +591,10 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
if($r)
|
||||
info( t('Profile updated.') . EOL);
|
||||
|
||||
|
||||
$r = q("select * from profile where id = %d and uid = %d limit 1",
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
@@ -603,9 +603,9 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
require_once('include/zot.php');
|
||||
Libsync::build_sync_packet(local_channel(),array('profile' => $r));
|
||||
}
|
||||
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
if($namechanged && $is_default) {
|
||||
$r = q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
|
||||
dbesc($name),
|
||||
@@ -617,7 +617,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if($is_default) {
|
||||
// reload the info for the sidebar widget - why does this not work?
|
||||
profile_load($channel['channel_address']);
|
||||
@@ -625,24 +625,24 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
$o = '';
|
||||
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
require_once('include/channel.php');
|
||||
|
||||
|
||||
$profile_fields_basic = get_profile_fields_basic();
|
||||
$profile_fields_advanced = get_profile_fields_advanced();
|
||||
|
||||
|
||||
if(((argc() > 1) && (intval(argv(1)))) || !feature_enabled(local_channel(),'multi_profiles')) {
|
||||
if(feature_enabled(local_channel(),'multi_profiles'))
|
||||
$id = \App::$argv[1];
|
||||
@@ -652,7 +652,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
if($x)
|
||||
$id = $x[0]['id'];
|
||||
}
|
||||
}
|
||||
$r = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1",
|
||||
intval($id),
|
||||
intval(local_channel())
|
||||
@@ -661,20 +661,20 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
notice( t('Profile not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$editselect = 'none';
|
||||
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array(
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => $editselect,
|
||||
));
|
||||
|
||||
|
||||
$advanced = ((feature_enabled(local_channel(),'advanced_profiles')) ? true : false);
|
||||
if($advanced)
|
||||
$fields = $profile_fields_advanced;
|
||||
else
|
||||
$fields = $profile_fields_basic;
|
||||
|
||||
|
||||
$hide_friends = array(
|
||||
'hide_friends',
|
||||
t('Hide your connections list from viewers of this profile'),
|
||||
@@ -682,36 +682,36 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'',
|
||||
array(t('No'),t('Yes'))
|
||||
);
|
||||
|
||||
|
||||
$q = q("select * from profdef where true");
|
||||
if($q) {
|
||||
$extra_fields = array();
|
||||
|
||||
|
||||
foreach($q as $qq) {
|
||||
$mine = q("select v from profext where k = '%s' and hash = '%s' and channel_id = %d limit 1",
|
||||
dbesc($qq['field_name']),
|
||||
dbesc($qq['field_name']),
|
||||
dbesc($r[0]['profile_guid']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
if(array_key_exists($qq['field_name'],$fields)) {
|
||||
$extra_fields[] = array($qq['field_name'],$qq['field_desc'],(($mine) ? $mine[0]['v'] : ''), $qq['field_help']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//logger('extra_fields: ' . print_r($extra_fields,true));
|
||||
|
||||
$vc = $r[0]['profile_vcard'];
|
||||
$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
|
||||
$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
|
||||
$vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] );
|
||||
|
||||
|
||||
$f = get_config('system','birthday_input_format');
|
||||
if(! $f)
|
||||
$f = 'ymd';
|
||||
|
||||
|
||||
$is_default = (($r[0]['is_default']) ? 1 : 0);
|
||||
|
||||
|
||||
$tpl = get_markup_template("profile_edit.tpl");
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$multi_profiles' => ((feature_enabled(local_channel(),'multi_profiles')) ? true : false),
|
||||
@@ -749,7 +749,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$default' => t('This is your default profile.') . EOL . translate_scope(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_profile'))),
|
||||
'$advanced' => $advanced,
|
||||
'$name' => array('name', t('Your full name'), $r[0]['fullname'], t('Required'), '*'),
|
||||
'$pdesc' => array('pdesc', t('Title/Description'), $r[0]['pdesc']),
|
||||
'$pdesc' => array('pdesc', t('Short title/tescription'), $r[0]['pdesc'], t('Maximal 190 characters'), '', 'maxlength="190"'),
|
||||
'$dob' => dob($r[0]['dob']),
|
||||
'$hide_friends' => $hide_friends,
|
||||
'$address' => array('address', t('Street address'), $r[0]['address']),
|
||||
@@ -802,18 +802,18 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$delete' => t('Delete'),
|
||||
'$cancel' => t('Cancel'),
|
||||
));
|
||||
|
||||
|
||||
$arr = array('profile' => $r[0], 'entry' => $o);
|
||||
call_hooks('profile_edit', $arr);
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
$r = q("SELECT * FROM profile WHERE uid = %d",
|
||||
local_channel());
|
||||
if($r) {
|
||||
|
||||
|
||||
$tpl = get_markup_template('profile_entry.tpl');
|
||||
foreach($r as $rr) {
|
||||
$profiles .= replace_macros($tpl, array(
|
||||
@@ -821,24 +821,24 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$id' => $rr['id'],
|
||||
'$alt' => t('Profile Image'),
|
||||
'$profile_name' => $rr['profile_name'],
|
||||
'$visible' => (($rr['is_default'])
|
||||
? '<strong>' . translate_scope(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_profile'))) . '</strong>'
|
||||
'$visible' => (($rr['is_default'])
|
||||
? '<strong>' . translate_scope(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_profile'))) . '</strong>'
|
||||
: '<a href="' . z_root() . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>')
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
$tpl_header = get_markup_template('profile_listing_header.tpl');
|
||||
$o .= replace_macros($tpl_header,array(
|
||||
'$header' => t('Edit Profiles'),
|
||||
'$cr_new' => t('Create New'),
|
||||
'$cr_new_link' => 'profiles/new?t=' . get_form_security_token("profile_new"),
|
||||
'$profiles' => $profiles
|
||||
));
|
||||
|
||||
));
|
||||
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Pubsites extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
require_once('include/dir_fns.php');
|
||||
require_once('include/dir_fns.php');
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
|
||||
|
||||
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
|
||||
$url = z_root() . '/dirsearch';
|
||||
}
|
||||
if(! $url) {
|
||||
$directory = find_upstream_directory($dirmode);
|
||||
$directory = Libzotdir::find_upstream_directory($dirmode);
|
||||
$url = $directory['url'] . '/dirsearch';
|
||||
}
|
||||
$url .= '/sites';
|
||||
@@ -20,12 +21,12 @@ class Pubsites extends \Zotlabs\Web\Controller {
|
||||
$rating_enabled = get_config('system','rating_enabled');
|
||||
|
||||
$o .= '<div class="generic-content-wrapper">';
|
||||
|
||||
|
||||
$o .= '<div class="section-title-wrapper"><h2>' . t('Public Hubs') . '</h2></div>';
|
||||
|
||||
$o .= '<div class="section-content-tools-wrapper"><div class="descriptive-text">' .
|
||||
|
||||
$o .= '<div class="section-content-tools-wrapper"><div class="descriptive-text">' .
|
||||
t('The listed hubs allow public registration for the $Projectname network. All hubs in the network are interlinked so membership on any of them conveys membership in the network as a whole. Some hubs may require subscription or provide tiered service plans. The hub itself <strong>may</strong> provide additional details.') . '</div>' . EOL;
|
||||
|
||||
|
||||
$ret = z_fetch_url($url);
|
||||
if($ret['success']) {
|
||||
$j = json_decode($ret['body'],true);
|
||||
@@ -48,8 +49,8 @@ class Pubsites extends \Zotlabs\Web\Controller {
|
||||
$host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3));
|
||||
$rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="fa fa-check-square-o"></i> ' . t('Rate') . '</a></td>' : '');
|
||||
$location = '';
|
||||
if(!empty($jj['location'])) {
|
||||
$location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="fa fa-globe"></i> ' . $jj['location'] . '</p>';
|
||||
if(!empty($jj['location'])) {
|
||||
$location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="fa fa-globe"></i> ' . $jj['location'] . '</p>';
|
||||
}
|
||||
else {
|
||||
$location = '<br /> ';
|
||||
@@ -61,14 +62,14 @@ class Pubsites extends \Zotlabs\Web\Controller {
|
||||
$o .= '</tr>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$o .= '</table>';
|
||||
|
||||
|
||||
$o .= '</div></div>';
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -23,9 +23,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
if((observer_prohibited(true))) {
|
||||
return login();
|
||||
}
|
||||
@@ -59,7 +56,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$item_normal = item_normal();
|
||||
$item_normal_update = item_normal_update();
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
$net = ((array_key_exists('net',$_REQUEST)) ? escape_tags($_REQUEST['net']) : '');
|
||||
|
||||
$title = replace_macros(get_markup_template("section_title.tpl"),array(
|
||||
@@ -103,11 +99,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$o .= status_editor($a,$x,false,'Pubstream');
|
||||
$o .= '</div>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(! $update && !$load) {
|
||||
|
||||
@@ -116,8 +107,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
if(!$mid)
|
||||
$_SESSION['static_loadtime'] = datetime_convert();
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1);
|
||||
|
||||
$maxheight = get_config('system','home_divmore_height');
|
||||
if(! $maxheight)
|
||||
$maxheight = 400;
|
||||
@@ -148,7 +137,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$list' => '0',
|
||||
'$static' => $static,
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$search' => '',
|
||||
'$xchan' => '',
|
||||
@@ -200,14 +188,10 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$net_query2 = (($net) ? " and xchan_network = '" . protect_sprintf(dbesc($net)) . "' " : '');
|
||||
|
||||
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
|
||||
|
||||
$simple_update = (($_SESSION['loadtime']) ? " AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' " : '');
|
||||
|
||||
if($load)
|
||||
$simple_update = '';
|
||||
|
||||
if($static && $simple_update)
|
||||
$simple_update .= " and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' ";
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
//logger('update: ' . $update . ' load: ' . $load);
|
||||
|
||||
@@ -220,10 +204,10 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT parent AS item_id FROM item
|
||||
left join abook on item.author_xchan = abook.abook_xchan
|
||||
$net_query
|
||||
WHERE mid like '%s' $uids $item_normal
|
||||
WHERE mid = '%s' $uids $item_normal
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra3 $sql_extra $sql_nets $net_query2 LIMIT 1",
|
||||
dbesc($mid . '%')
|
||||
$sql_extra3 $sql_extra $sql_nets $net_query2",
|
||||
dbesc($mid)
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -243,10 +227,10 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT parent AS item_id FROM item
|
||||
left join abook on item.author_xchan = abook.abook_xchan
|
||||
$net_query
|
||||
WHERE mid like '%s' $uids $item_normal_update $simple_update
|
||||
WHERE mid = '%s' $uids $item_normal_update $simple_update
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra3 $sql_extra $sql_nets $net_query2 LIMIT 1",
|
||||
dbesc($mid . '%')
|
||||
$sql_extra3 $sql_extra $sql_nets $net_query2",
|
||||
dbesc($mid)
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -259,7 +243,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$sql_extra3 $sql_extra $sql_nets $net_query2"
|
||||
);
|
||||
}
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
}
|
||||
|
||||
// Then fetch all the children of the parents that are on this page
|
||||
@@ -291,7 +274,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
|
||||
// fake it
|
||||
$mode = (($hashtags) ? 'search' : 'pubstream');
|
||||
|
||||
|
||||
$o .= conversation($items,$mode,$update,$page_mode);
|
||||
|
||||
if($mid)
|
||||
@@ -300,6 +283,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
if(($items) && (! $update))
|
||||
$o .= alt_pager(count($items));
|
||||
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ require_once('include/zot.php');
|
||||
|
||||
/**
|
||||
* remote post
|
||||
*
|
||||
*
|
||||
* https://yoursite/rpost?f=&title=&body=&remote_return=
|
||||
*
|
||||
* This can be called via either GET or POST, use POST for long body content as suhosin often limits GET parameter length
|
||||
@@ -20,7 +20,7 @@ require_once('include/zot.php');
|
||||
* body= Body of post
|
||||
* url= URL which will be parsed and the results appended to the body
|
||||
* source= Source application
|
||||
* post_id= post_id of post to 'share' (local use only)
|
||||
* post_id= post_id of post to 'share' (local use only)
|
||||
* remote_return= absolute URL to return after posting is finished
|
||||
* type= choices are 'html' or 'bbcode', default is 'bbcode'
|
||||
*
|
||||
@@ -32,16 +32,16 @@ require_once('include/zot.php');
|
||||
class Rpost extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
$o = '';
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
if(remote_channel()) {
|
||||
// redirect to your own site.
|
||||
// We can only do this with a GET request so you'll need to keep the text short or risk getting truncated
|
||||
// by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin
|
||||
// blocks them.
|
||||
|
||||
|
||||
$url = get_rpost_path(\App::get_observer());
|
||||
// make sure we're not looping to our own hub
|
||||
if(($url) && (! stristr($url, \App::get_hostname()))) {
|
||||
@@ -53,10 +53,10 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
goaway($url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The login procedure is going to bugger our $_REQUEST variables
|
||||
// so save them in the session.
|
||||
|
||||
|
||||
if(array_key_exists('body',$_REQUEST)) {
|
||||
$_SESSION['rpost'] = $_REQUEST;
|
||||
}
|
||||
@@ -64,14 +64,14 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
nav_set_selected('Post');
|
||||
|
||||
|
||||
// If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables
|
||||
|
||||
|
||||
if((! array_key_exists('body',$_REQUEST)) && (array_key_exists('rpost',$_SESSION))) {
|
||||
$_REQUEST = $_SESSION['rpost'];
|
||||
unset($_SESSION['rpost']);
|
||||
}
|
||||
|
||||
|
||||
if(array_key_exists('channel',$_REQUEST)) {
|
||||
$r = q("select channel_id from channel where channel_account_id = %d and channel_address = '%s' limit 1",
|
||||
intval(get_account_id()),
|
||||
@@ -82,7 +82,7 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
$change = change_channel($r[0]['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($_REQUEST['remote_return']) {
|
||||
$_SESSION['remote_return'] = $_REQUEST['remote_return'];
|
||||
}
|
||||
@@ -91,21 +91,27 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
goaway($_SESSION['remote_return']);
|
||||
goaway(z_root() . '/network');
|
||||
}
|
||||
|
||||
|
||||
$plaintext = true;
|
||||
|
||||
|
||||
if(array_key_exists('type', $_REQUEST) && $_REQUEST['type'] === 'html') {
|
||||
require_once('include/html2bbcode.php');
|
||||
$_REQUEST['body'] = html2bbcode($_REQUEST['body']);
|
||||
$_REQUEST['body'] = html2bbcode($_REQUEST['body']);
|
||||
}
|
||||
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
|
||||
$channel_acl = $acl->get();
|
||||
|
||||
|
||||
if($_REQUEST['acl']) {
|
||||
$acl = new \Zotlabs\Access\AccessList([]);
|
||||
$acl->set($_REQUEST['acl']);
|
||||
$channel_acl = $acl->get();
|
||||
}
|
||||
else {
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$channel_acl = $acl->get();
|
||||
}
|
||||
|
||||
|
||||
if($_REQUEST['url']) {
|
||||
$x = z_fetch_url(z_root() . '/linkinfo?f=&url=' . urlencode($_REQUEST['url']));
|
||||
if($x['success'])
|
||||
@@ -115,7 +121,7 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
if($_REQUEST['post_id']) {
|
||||
$_REQUEST['body'] .= '[share=' . intval($_REQUEST['post_id']) . '][/share]';
|
||||
}
|
||||
|
||||
|
||||
$x = array(
|
||||
'is_owner' => true,
|
||||
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
|
||||
@@ -137,19 +143,19 @@ class Rpost extends \Zotlabs\Web\Controller {
|
||||
'bbcode' => true,
|
||||
'jotnets' => true
|
||||
);
|
||||
|
||||
|
||||
$editor = status_editor($a,$x,false,'Rpost');
|
||||
|
||||
|
||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||
'$title' => t('Edit post'),
|
||||
'$cancel' => '',
|
||||
'$editor' => $editor
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,9 +19,6 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if($load)
|
||||
$_SESSION['loadtime'] = datetime_convert();
|
||||
|
||||
nav_set_selected('Search');
|
||||
|
||||
require_once("include/bbcode.php");
|
||||
@@ -54,8 +51,6 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
$search = ((x($_GET,'tag')) ? trim(escape_tags(rawurldecode($_GET['tag']))) : '');
|
||||
}
|
||||
|
||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||
|
||||
$o .= search($search,'search-box','/search',((local_channel()) ? true : false));
|
||||
|
||||
if(strpos($search,'#') === 0) {
|
||||
@@ -105,9 +100,6 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
$static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 0);
|
||||
|
||||
|
||||
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
|
||||
// because browser prefetching might change it on us. We have to deliver it with the page.
|
||||
|
||||
@@ -131,7 +123,6 @@ class Search extends \Zotlabs\Web\Controller {
|
||||
'$dm' => '0',
|
||||
'$nouveau' => '0',
|
||||
'$wall' => '0',
|
||||
'$static' => $static,
|
||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
||||
'$search' => (($tag) ? urlencode('#') : '') . $search,
|
||||
|
||||
@@ -28,7 +28,6 @@ class Display {
|
||||
$user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0);
|
||||
$nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0);
|
||||
$title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0);
|
||||
$manual_update = ((array_key_exists('manual_update',$_POST)) ? intval($_POST['manual_update']) : 0);
|
||||
$start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0);
|
||||
|
||||
$browser_update = ((x($_POST,'browser_update')) ? intval($_POST['browser_update']) : 0);
|
||||
@@ -47,7 +46,6 @@ class Display {
|
||||
set_pconfig(local_channel(),'system','itemspage', $itemspage);
|
||||
set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile));
|
||||
set_pconfig(local_channel(),'system','title_tosource',$title_tosource);
|
||||
set_pconfig(local_channel(),'system','manual_conversation_update', $manual_update);
|
||||
set_pconfig(local_channel(),'system','channel_menu', $channel_menu);
|
||||
set_pconfig(local_channel(),'system','start_menu', $start_menu);
|
||||
|
||||
@@ -200,7 +198,6 @@ class Display {
|
||||
'$itemspage' => array('itemspage', t("Maximum number of conversations to load at any time:"), $itemspage, t('Maximum of 30 items')),
|
||||
'$nosmile' => array('nosmile', t("Show emoticons (smilies) as images"), 1-intval($nosmile), '', $yes_no),
|
||||
'$channel_menu' => [ 'channel_menu', t('Provide channel menu in navigation bar'), get_pconfig(local_channel(),'system','channel_menu',get_config('system','channel_menu',0)), t('Default: channel menu located in app menu'),$yes_no ],
|
||||
'$manual_update' => array('manual_update', t('Manual conversation updates'), channel_manual_conv_update(local_channel()), t('Default is on, turning this off may increase screen jumping'), $yes_no),
|
||||
'$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no),
|
||||
'$theme_config' => $theme_config,
|
||||
'$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no]
|
||||
|
||||
@@ -123,7 +123,7 @@ class Sse_bs extends Controller {
|
||||
$mids[] = '\'' . dbesc(@base64url_decode(substr($a,4))) . '\'';
|
||||
}
|
||||
|
||||
$str = implode($mids, ',');
|
||||
$str = implode(',', $mids);
|
||||
|
||||
$x = [ 'channel_id' => self::$uid, 'update' => 'unset' ];
|
||||
call_hooks('update_unseen',$x);
|
||||
@@ -162,7 +162,7 @@ class Sse_bs extends Controller {
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1 AND item_wall = 0 AND item_private IN (0, 1)
|
||||
@@ -190,7 +190,7 @@ class Sse_bs extends Controller {
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_wall = 0 AND item_private IN (0, 1)
|
||||
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
|
||||
AND author_xchan != '%s'
|
||||
@@ -231,10 +231,10 @@ class Sse_bs extends Controller {
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1 AND item_wall = 0 AND item_private = 2
|
||||
AND item_unseen = 1 AND item_private = 2
|
||||
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
|
||||
AND author_xchan != '%s'
|
||||
$item_normal
|
||||
@@ -259,8 +259,8 @@ class Sse_bs extends Controller {
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_wall = 0 AND item_private = 2
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_private = 2
|
||||
$item_normal
|
||||
$sql_extra
|
||||
AND author_xchan != '%s'",
|
||||
@@ -300,10 +300,10 @@ class Sse_bs extends Controller {
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1 AND item_wall = 1
|
||||
AND item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)
|
||||
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
|
||||
AND author_xchan != '%s'
|
||||
$item_normal
|
||||
@@ -328,8 +328,8 @@ class Sse_bs extends Controller {
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_wall = 1
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d and item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)
|
||||
$item_normal
|
||||
$sql_extra
|
||||
AND author_xchan != '%s'",
|
||||
@@ -379,7 +379,7 @@ class Sse_bs extends Controller {
|
||||
$item_normal = item_normal();
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
$items = q("SELECT * FROM item
|
||||
WHERE uid = %d
|
||||
AND created <= '%s'
|
||||
AND item_unseen = 1
|
||||
@@ -410,7 +410,7 @@ class Sse_bs extends Controller {
|
||||
|
||||
}
|
||||
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
$r = q("SELECT count(id) as total FROM item
|
||||
WHERE uid = %d AND item_unseen = 1
|
||||
AND created > '%s'
|
||||
$item_normal
|
||||
@@ -516,7 +516,7 @@ class Sse_bs extends Controller {
|
||||
$p_str = ids_to_querystr($p, 'parent');
|
||||
$p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
|
||||
|
||||
$r = q("select mid from item
|
||||
$r = q("select mid from item
|
||||
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $sql_extra $item_normal",
|
||||
intval(self::$uid),
|
||||
dbesc($forums[$x]['xchan_hash']),
|
||||
@@ -577,7 +577,7 @@ class Sse_bs extends Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
$r = q("SELECT * FROM item
|
||||
$r = q("SELECT * FROM item
|
||||
WHERE verb = '%s'
|
||||
AND obj_type IN ('Document', 'Video', 'Audio', 'Image')
|
||||
AND uid = %d
|
||||
|
||||
@@ -7,7 +7,7 @@ use Zotlabs\Lib\Libzot;
|
||||
class Zfinger extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/crypto.php');
|
||||
|
||||
@@ -26,7 +26,7 @@ class Zfinger extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($chan) {
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],'acct:' . channel_reddress($chan));
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'], channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
}
|
||||
else {
|
||||
@@ -37,7 +37,7 @@ class Zfinger extends \Zotlabs\Web\Controller {
|
||||
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
use Sabre\DAV;
|
||||
use App;
|
||||
|
||||
/**
|
||||
* @brief Provides a DAV frontend for the webbrowser.
|
||||
@@ -76,49 +77,82 @@ class Browser extends DAV\Browser\Plugin {
|
||||
* @param string $path which should be displayed
|
||||
*/
|
||||
public function generateDirectoryIndex($path) {
|
||||
// (owner_id = channel_id) is visitor owner of this directory?
|
||||
$is_owner = ((local_channel() && $this->auth->owner_id == local_channel()) ? true : false);
|
||||
|
||||
if ($this->auth->getTimezone())
|
||||
date_default_timezone_set($this->auth->getTimezone());
|
||||
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/text.php');
|
||||
if ($this->auth->owner_nick) {
|
||||
$html = '';
|
||||
|
||||
$nick = $this->auth->owner_nick;
|
||||
$channel_id = $this->auth->owner_id;
|
||||
|
||||
// Is visitor owner of this directory?
|
||||
$is_owner = ((local_channel() && $channel_id == local_channel()) ? true : false);
|
||||
$cat = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : '');
|
||||
|
||||
if ($this->auth->getTimezone()) {
|
||||
date_default_timezone_set($this->auth->getTimezone());
|
||||
}
|
||||
|
||||
$files = $this->server->getPropertiesForPath($path, array(
|
||||
'{DAV:}displayname',
|
||||
'{DAV:}resourcetype',
|
||||
'{DAV:}getcontenttype',
|
||||
'{DAV:}getcontentlength',
|
||||
'{DAV:}getlastmodified',
|
||||
), 1);
|
||||
|
||||
$files = $this->server->getPropertiesForPath($path, [], 1);
|
||||
$parent = $this->server->tree->getNodeForPath($path);
|
||||
|
||||
$parentpath = array();
|
||||
// only show parent if not leaving /cloud/; TODO how to improve this?
|
||||
if ($path && $path != "cloud") {
|
||||
list($parentUri) = \Sabre\Uri\split($path);
|
||||
$fullPath = \Sabre\HTTP\encodePath($this->server->getBaseUri() . $parentUri);
|
||||
$arr = explode('/', $parent->os_path);
|
||||
end($arr);
|
||||
$folder_parent = ((isset($arr[1])) ? prev($arr) : '');
|
||||
|
||||
$parentpath['icon'] = $this->enableAssets ? '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="' . t('parent') . '"></a>' : '';
|
||||
$parentpath['path'] = $fullPath;
|
||||
$folder_list = attach_folder_select_list($channel_id);
|
||||
|
||||
$siteroot_disabled = get_config('system', 'cloud_disable_siteroot');
|
||||
$is_root_folder = (($path === 'cloud/' . $nick) ? true : false);
|
||||
|
||||
$parent_path = '';
|
||||
|
||||
if ($channel_id && ! $cat && !($siteroot_disabled && $is_root_folder)) {
|
||||
list($parent_uri) = \Sabre\Uri\split($path);
|
||||
$parent_path = \Sabre\HTTP\encodePath($this->server->getBaseUri() . $parent_uri);
|
||||
}
|
||||
|
||||
$f = array();
|
||||
$embedable_video_types = [
|
||||
'video/mp4',
|
||||
'video/ogg',
|
||||
'video/webm'
|
||||
];
|
||||
|
||||
$embedable_audio_types = [
|
||||
'audio/mpeg',
|
||||
'audio/wav',
|
||||
'audio/ogg',
|
||||
'audio/webm'
|
||||
];
|
||||
|
||||
$f = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$ft = array();
|
||||
|
||||
$ft = [];
|
||||
$type = null;
|
||||
|
||||
// This is the current directory, we can skip it
|
||||
if (rtrim($file['href'], '/') == $path) continue;
|
||||
$href = rtrim($file['href'], '/');
|
||||
|
||||
list(, $name) = \Sabre\Uri\split($file['href']);
|
||||
// This is the current directory - skip it
|
||||
if ($href === $path)
|
||||
continue;
|
||||
|
||||
$node = $this->server->tree->getNodeForPath($href);
|
||||
$data = $node->data;
|
||||
$attach_hash = $data['hash'];
|
||||
$folder_hash = $node->folder_hash;
|
||||
|
||||
list(, $filename) = \Sabre\Uri\split($href);
|
||||
|
||||
$name = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $filename;
|
||||
$name = $this->escapeHTML($name);
|
||||
|
||||
$size = isset($file[200]['{DAV:}getcontentlength']) ? (int)$file[200]['{DAV:}getcontentlength'] : '';
|
||||
|
||||
$lastmodified = ((isset($file[200]['{DAV:}getlastmodified'])) ? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') : '');
|
||||
|
||||
if (isset($file[200]['{DAV:}resourcetype'])) {
|
||||
|
||||
$type = $file[200]['{DAV:}resourcetype']->getValue();
|
||||
|
||||
// resourcetype can have multiple values
|
||||
@@ -128,22 +162,22 @@ class Browser extends DAV\Browser\Plugin {
|
||||
// Some name mapping is preferred
|
||||
switch ($v) {
|
||||
case '{DAV:}collection' :
|
||||
$type[$k] = t('Collection');
|
||||
$type[$k] = 'Collection';
|
||||
break;
|
||||
case '{DAV:}principal' :
|
||||
$type[$k] = t('Principal');
|
||||
$type[$k] = 'Principal';
|
||||
break;
|
||||
case '{urn:ietf:params:xml:ns:carddav}addressbook' :
|
||||
$type[$k] = t('Addressbook');
|
||||
$type[$k] = 'Addressbook';
|
||||
break;
|
||||
case '{urn:ietf:params:xml:ns:caldav}calendar' :
|
||||
$type[$k] = t('Calendar');
|
||||
$type[$k] = 'Calendar';
|
||||
break;
|
||||
case '{urn:ietf:params:xml:ns:caldav}schedule-inbox' :
|
||||
$type[$k] = t('Schedule Inbox');
|
||||
$type[$k] = 'Schedule Inbox';
|
||||
break;
|
||||
case '{urn:ietf:params:xml:ns:caldav}schedule-outbox' :
|
||||
$type[$k] = t('Schedule Outbox');
|
||||
$type[$k] = 'Schedule Outbox';
|
||||
break;
|
||||
case '{http://calendarserver.org/ns/}calendar-proxy-read' :
|
||||
$type[$k] = 'Proxy-Read';
|
||||
@@ -158,124 +192,173 @@ class Browser extends DAV\Browser\Plugin {
|
||||
|
||||
// If no resourcetype was found, we attempt to use
|
||||
// the contenttype property
|
||||
if (!$type && isset($file[200]['{DAV:}getcontenttype'])) {
|
||||
if (! $type && isset($file[200]['{DAV:}getcontenttype'])) {
|
||||
$type = $file[200]['{DAV:}getcontenttype'];
|
||||
}
|
||||
if (!$type) $type = t('Unknown');
|
||||
|
||||
$size = isset($file[200]['{DAV:}getcontentlength']) ? (int)$file[200]['{DAV:}getcontentlength'] : '';
|
||||
$lastmodified = ((isset($file[200]['{DAV:}getlastmodified'])) ? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') : '');
|
||||
if (! $type) {
|
||||
$type = $data['filetype'];
|
||||
}
|
||||
|
||||
$fullPath = \Sabre\HTTP\encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/'));
|
||||
|
||||
$displayName = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $name;
|
||||
|
||||
$displayName = $this->escapeHTML($displayName);
|
||||
$type = $this->escapeHTML($type);
|
||||
|
||||
|
||||
$icon = '';
|
||||
|
||||
if ($this->enableAssets) {
|
||||
$node = $this->server->tree->getNodeForPath(($path ? $path . '/' : '') . $name);
|
||||
foreach (array_reverse($this->iconMap) as $class=>$iconName) {
|
||||
if ($node instanceof $class) {
|
||||
$icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24"></a>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$parentHash = '';
|
||||
$owner = $this->auth->owner_id;
|
||||
$splitPath = explode('/', $fullPath);
|
||||
if (count($splitPath) > 3) {
|
||||
for ($i = 3; $i < count($splitPath); $i++) {
|
||||
$attachName = urldecode($splitPath[$i]);
|
||||
$attachHash = $this->findAttachHash($owner, $parentHash, $attachName);
|
||||
$parentHash = $attachHash;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// generate preview icons for tile view.
|
||||
// generate preview icons for tile view.
|
||||
// Currently we only handle images, but this could potentially be extended with plugins
|
||||
// to provide document and video thumbnails. SVG, PDF and office documents have some
|
||||
// to provide document and video thumbnails. SVG, PDF and office documents have some
|
||||
// security concerns and should only be allowed on single-user sites with tightly controlled
|
||||
// upload access. system.thumbnail_security should be set to 1 if you want to include these
|
||||
// types
|
||||
// upload access. system.thumbnail_security should be set to 1 if you want to include these
|
||||
// types
|
||||
|
||||
$is_creator = false;
|
||||
$photo_icon = '';
|
||||
$preview_style = intval(get_config('system','thumbnail_security',0));
|
||||
|
||||
$r = q("select content, creator from attach where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($attachHash),
|
||||
intval($owner)
|
||||
);
|
||||
$is_creator = (($data['creator'] === get_observer_hash()) ? true : false);
|
||||
|
||||
if($r) {
|
||||
$is_creator = (($r[0]['creator'] === get_observer_hash()) ? true : false);
|
||||
if(file_exists(dbunescbin($r[0]['content']) . '.thumb')) {
|
||||
$photo_icon = 'data:image/jpeg;base64,' . base64_encode(file_get_contents(dbunescbin($r[0]['content']) . '.thumb'));
|
||||
// logger('found thumb: ' . $photo_icon);
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($type,'image/') === 0 && $attachHash) {
|
||||
$r = q("select resource_id, imgscale from photo where resource_id = '%s' and imgscale in ( %d, %d ) order by imgscale asc limit 1",
|
||||
dbesc($attachHash),
|
||||
if(strpos($type,'image/') === 0 && $attach_hash) {
|
||||
$p = q("select resource_id, imgscale from photo where resource_id = '%s' and imgscale in ( %d, %d ) order by imgscale asc limit 1",
|
||||
dbesc($attach_hash),
|
||||
intval(PHOTO_RES_320),
|
||||
intval(PHOTO_RES_PROFILE_80)
|
||||
);
|
||||
if($r) {
|
||||
$photo_icon = 'photo/' . $r[0]['resource_id'] . '-' . $r[0]['imgscale'];
|
||||
if($p) {
|
||||
$photo_icon = 'photo/' . $p[0]['resource_id'] . '-' . $p[0]['imgscale'];
|
||||
}
|
||||
if($type === 'image/svg+xml' && $preview_style > 0) {
|
||||
$photo_icon = $fullPath;
|
||||
$photo_icon = $href;
|
||||
}
|
||||
}
|
||||
|
||||
$g = [ 'resource_id' => $attachHash, 'thumbnail' => $photo_icon, 'security' => $preview_style ];
|
||||
$g = [ 'resource_id' => $attach_hash, 'thumbnail' => $photo_icon, 'security' => $preview_style ];
|
||||
call_hooks('file_thumbnail', $g);
|
||||
$photo_icon = $g['thumbnail'];
|
||||
|
||||
$lockstate = (($data['allow_cid'] || $data['allow_gid'] || $data['deny_cid'] || $data['deny_gid']) ? 'lock' : 'unlock');
|
||||
$id = $data['id'];
|
||||
|
||||
$attachIcon = ""; // "<a href=\"attach/".$attachHash."\" title=\"".$displayName."\"><i class=\"fa fa-arrow-circle-o-down\"></i></a>";
|
||||
if($id) {
|
||||
$terms = q("select * from term where oid = %d AND otype = %d",
|
||||
intval($id),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
|
||||
$categories = [];
|
||||
$terms_str = '';
|
||||
if($terms) {
|
||||
foreach($terms as $t) {
|
||||
$term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
|
||||
if(! trim($term))
|
||||
continue;
|
||||
$categories[] = array('term' => $term, 'url' => $t['url']);
|
||||
if ($terms_str)
|
||||
$terms_str .= ',';
|
||||
$terms_str .= $term;
|
||||
}
|
||||
$ft['terms'] = replace_macros(get_markup_template('item_categories.tpl'),array(
|
||||
'$categories' => $categories
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// put the array for this file together
|
||||
$ft['attachId'] = $this->findAttachIdByHash($attachHash);
|
||||
$ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->owner_nick;
|
||||
$ft['attach_id'] = $id;
|
||||
$ft['icon'] = $icon;
|
||||
$ft['photo_icon'] = $photo_icon;
|
||||
$ft['attachIcon'] = (($size) ? $attachIcon : '');
|
||||
// @todo Should this be an item value, not a global one?
|
||||
$ft['is_owner'] = $is_owner;
|
||||
$ft['is_creator'] = $is_creator;
|
||||
$ft['fullPath'] = $fullPath;
|
||||
$ft['displayName'] = $displayName;
|
||||
$ft['rel_path'] = (($data) ? '/cloud/' . $nick .'/' . $data['display_path'] : $href);
|
||||
$ft['full_path'] = z_root() . (($data) ? '/cloud/' . $nick .'/' . $data['display_path'] : $href);
|
||||
$ft['name'] = $name;
|
||||
$ft['type'] = $type;
|
||||
$ft['size'] = $size;
|
||||
$ft['sizeFormatted'] = userReadableSize($size);
|
||||
$ft['lastmodified'] = (($lastmodified) ? datetime_convert('UTC', date_default_timezone_get(), $lastmodified) : '');
|
||||
$ft['iconFromType'] = getIconFromType($type);
|
||||
$ft['collection'] = (($type === 'Collection') ? true : false);
|
||||
$ft['size_formatted'] = userReadableSize($size);
|
||||
$ft['last_modified'] = (($lastmodified) ? datetime_convert('UTC', date_default_timezone_get(), $lastmodified) : '');
|
||||
$ft['icon_from_type'] = getIconFromType($type);
|
||||
|
||||
$ft['allow_cid'] = acl2json($data['allow_cid']);
|
||||
$ft['allow_gid'] = acl2json($data['allow_gid']);
|
||||
$ft['deny_cid'] = acl2json($data['deny_cid']);
|
||||
$ft['deny_gid'] = acl2json($data['deny_gid']);
|
||||
|
||||
$ft['raw_allow_cid'] = $data['allow_cid'];
|
||||
$ft['raw_allow_gid'] = $data['allow_gid'];
|
||||
$ft['raw_deny_cid'] = $data['deny_cid'];
|
||||
$ft['raw_deny_gid'] = $data['deny_gid'];
|
||||
|
||||
$ft['lockstate'] = $lockstate;
|
||||
$ft['resource'] = $data['hash'];
|
||||
$ft['folder'] = $data['folder'];
|
||||
$ft['revision'] = $data['revision'];
|
||||
$ft['newfilename'] = ['newfilename_' . $id, t('Change filename to'), $name];
|
||||
$ft['categories'] = ['categories_' . $id, t('Categories'), $terms_str];
|
||||
|
||||
// create a copy of the list which we can alter for the current resource
|
||||
$folders = $folder_list;
|
||||
|
||||
if($data['is_dir']) {
|
||||
|
||||
$rm_path = $folders[$folder_hash];
|
||||
// can not copy a folder into itself or own child folders
|
||||
foreach($folders as $k => $v) {
|
||||
if(strpos($v, $rm_path) === 0)
|
||||
unset($folders[$k]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$ft['newfolder'] = ['newfolder_' . $id, t('Select a target location'), $data['folder'], '', $folders];
|
||||
$ft['copy'] = ['copy_' . $id, t('Copy to target location'), 0, '', [t('No'), t('Yes')]];
|
||||
$ft['recurse'] = ['recurse_' . $id, t('Set permissions for all files and sub folders'), 0, '', [t('No'), t('Yes')]];
|
||||
$ft['notify'] = ['notify_edit_' . $id, t('Notify your contacts about this file'), 0, '', [t('No'), t('Yes')]];
|
||||
|
||||
$embed_bbcode = '';
|
||||
$link_bbcode = '';
|
||||
$attach_bbcode = '';
|
||||
|
||||
if($data['is_photo']) {
|
||||
$embed_bbcode = '[zmg]' . $ft['full_path'] . '[/zmg]';
|
||||
}
|
||||
elseif(strpos($type, 'video') === 0 && in_array($type, $embedable_video_types)) {
|
||||
$embed_bbcode = '[zvideo]' . $ft['full_path'] . '[/zvideo]';
|
||||
}
|
||||
elseif(strpos($type, 'audio') === 0 && in_array($type, $embedable_audio_types)) {
|
||||
$embed_bbcode = '[zaudio]' . $ft['full_path'] . '[/zaudio]';
|
||||
}
|
||||
$ft['embed_bbcode'] = $embed_bbcode;
|
||||
|
||||
if(! $data['is_dir']) {
|
||||
$attach_bbcode = '[attachment]' . $data['hash'] . ',' . $data['revision'] . '[/attachment]';
|
||||
}
|
||||
$ft['attach_bbcode'] = $attach_bbcode;
|
||||
|
||||
$link_bbcode = '[zrl=' . $ft['full_path'] . ']' . $ft['name'] . '[/zrl]';
|
||||
$ft['link_bbcode'] = $link_bbcode;
|
||||
|
||||
$f[] = $ft;
|
||||
|
||||
}
|
||||
|
||||
|
||||
$output = '';
|
||||
if ($this->enablePost) {
|
||||
$this->server->emit('onHTMLActionsPanel', array($parent, &$output, $path));
|
||||
$this->server->emit('onHTMLActionsPanel', [$parent, &$output, $path]);
|
||||
}
|
||||
|
||||
$deftiles = (($is_owner) ? 0 : 1);
|
||||
|
||||
$tiles = ((array_key_exists('cloud_tiles',$_SESSION)) ? intval($_SESSION['cloud_tiles']) : $deftiles);
|
||||
$_SESSION['cloud_tiles'] = $tiles;
|
||||
|
||||
$html .= replace_macros(get_markup_template('cloud.tpl'), array(
|
||||
'$header' => t('Files') . ": " . $this->escapeHTML($path) . "/",
|
||||
|
||||
$header = (($cat) ? t('File category') . ": " . $this->escapeHTML($cat) : t('Files'));
|
||||
|
||||
$channel = channelx_by_n($channel_id);
|
||||
if($channel) {
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$channel_acl = $acl->get();
|
||||
$lockstate = (($acl->is_private()) ? 'lock' : 'unlock');
|
||||
}
|
||||
|
||||
$html = replace_macros(get_markup_template('cloud.tpl'), array(
|
||||
'$header' => $header,
|
||||
'$total' => t('Total'),
|
||||
'$actionspanel' => $output,
|
||||
'$shared' => t('Shared'),
|
||||
@@ -283,9 +366,12 @@ class Browser extends DAV\Browser\Plugin {
|
||||
'$upload' => t('Add Files'),
|
||||
'$is_owner' => $is_owner,
|
||||
'$is_admin' => is_site_admin(),
|
||||
'$admin_delete' => t('Admin Delete'),
|
||||
'$parentpath' => $parentpath,
|
||||
'$cpath' => bin2hex(\App::$query_string),
|
||||
'$admin_delete_label' => t('Admin Delete'),
|
||||
'$parentpath' => $parent_path,
|
||||
'$folder_parent' => $folder_parent,
|
||||
'$folder' => $parent->folder_hash,
|
||||
'$is_root_folder' => $is_root_folder,
|
||||
'$cpath' => bin2hex(App::$query_string),
|
||||
'$tiles' => intval($_SESSION['cloud_tiles']),
|
||||
'$entries' => $f,
|
||||
'$name' => t('Name'),
|
||||
@@ -293,17 +379,43 @@ class Browser extends DAV\Browser\Plugin {
|
||||
'$size' => t('Size'),
|
||||
'$lastmod' => t('Last Modified'),
|
||||
'$parent' => t('parent'),
|
||||
'$edit' => t('Edit'),
|
||||
'$delete' => t('Delete'),
|
||||
'$nick' => $this->auth->getCurrentUser()
|
||||
'$submit_label' => t('Submit'),
|
||||
'$cancel_label' => t('Cancel'),
|
||||
'$delete_label' => t('Delete'),
|
||||
'$channel_id' => $channel_id,
|
||||
'$cpdesc' => t('Copy/paste this code to attach file to a post'),
|
||||
'$cpldesc' => t('Copy/paste this URL to link file from a web page'),
|
||||
'$categories' => ['categories', t('Categories')],
|
||||
'$recurse' => ['recurse', t('Set permissions for all files and sub folders'), 0, '', [t('No'), t('Yes')]],
|
||||
'$newfolder' => ['newfolder', t('Select a target location'), $parent->folder_hash, '', $folder_list],
|
||||
'$copy' => ['copy', t('Copy to target location'), 0, '', [t('No'), t('Yes')]],
|
||||
'$return_path' => $path,
|
||||
'$lockstate' => $lockstate,
|
||||
'$allow_cid' => acl2json($channel_acl['allow_cid']),
|
||||
'$allow_gid' => acl2json($channel_acl['allow_gid']),
|
||||
'$deny_cid' => acl2json($channel_acl['deny_cid']),
|
||||
'$deny_gid' => acl2json($channel_acl['deny_gid']),
|
||||
'$is_owner' => $is_owner,
|
||||
'$select_all_label' => t('Select All'),
|
||||
'$bulk_actions_label' => t('Bulk Actions'),
|
||||
'$adjust_permissions_label' => t('Adjust Permissions'),
|
||||
'$move_copy_label' => t('Move or Copy'),
|
||||
'$categories_label' => t('Categories'),
|
||||
'$download_label' => t('Download'),
|
||||
'$info_label' => t('Info'),
|
||||
'$rename_label' => t('Rename'),
|
||||
'$post_label' => t('Post'),
|
||||
'$attach_bbcode_label' => t('Attachment BBcode'),
|
||||
'$embed_bbcode_label' => t('Embed BBcode'),
|
||||
'$link_bbcode_label' => t('Link BBcode'),
|
||||
'$close_label' => t('Close')
|
||||
));
|
||||
|
||||
|
||||
$a = false;
|
||||
|
||||
nav_set_selected('Files');
|
||||
|
||||
\App::$page['content'] = $html;
|
||||
App::$page['content'] = $html;
|
||||
load_pdl();
|
||||
|
||||
$current_theme = \Zotlabs\Render\Theme::current();
|
||||
@@ -335,6 +447,7 @@ class Browser extends DAV\Browser\Plugin {
|
||||
// SimpleCollection, we won't need to show the panel either.
|
||||
if (get_class($node) === 'Sabre\\DAV\\SimpleCollection')
|
||||
return;
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
$aclselect = null;
|
||||
@@ -387,10 +500,39 @@ class Browser extends DAV\Browser\Plugin {
|
||||
$special = 'cloud/' . $this->auth->owner_nick;
|
||||
$count = strlen($special);
|
||||
|
||||
if(strpos($path,$special) === 0)
|
||||
$path = trim(substr($path,$count),'/');
|
||||
|
||||
|
||||
if(strpos($path,$special) === 0)
|
||||
$display_path = trim(substr($path,$count),'/');
|
||||
|
||||
$breadcrumbs_html = '';
|
||||
|
||||
if($display_path && ! $_REQUEST['cat'] && ! $_SESSION['cloud_tiles']){
|
||||
$breadcrumbs = [];
|
||||
$folders = explode('/', $display_path);
|
||||
$folder_hashes = explode('/', $node->os_path);
|
||||
$breadcrumb_path = z_root() . '/cloud/' . $this->auth->owner_nick;
|
||||
|
||||
$breadcrumbs[] = [
|
||||
'name' => $this->auth->owner_nick,
|
||||
'hash' => '',
|
||||
'path' => $breadcrumb_path
|
||||
];
|
||||
|
||||
foreach($folders as $i => $name) {
|
||||
$breadcrumb_path .= '/' . $name;
|
||||
$breadcrumbs[] = [
|
||||
'name' => $name,
|
||||
'hash' => $folder_hashes[$i],
|
||||
'path' => $breadcrumb_path
|
||||
];
|
||||
}
|
||||
|
||||
$breadcrumbs_html = replace_macros(get_markup_template('breadcrumb.tpl'), array(
|
||||
'$breadcrumbs' => $breadcrumbs
|
||||
));
|
||||
}
|
||||
|
||||
$output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array(
|
||||
'$folder_header' => t('Create new folder'),
|
||||
'$folder_submit' => t('Create'),
|
||||
@@ -404,11 +546,12 @@ class Browser extends DAV\Browser\Plugin {
|
||||
'$deny_cid' => acl2json($channel_acl['deny_cid']),
|
||||
'$deny_gid' => acl2json($channel_acl['deny_gid']),
|
||||
'$lockstate' => $lockstate,
|
||||
'$return_url' => \App::$cmd,
|
||||
'$path' => $path,
|
||||
'$folder' => find_folder_hash_by_path($this->auth->owner_id, $path),
|
||||
'$return_url' => $path,
|
||||
'$folder' => $node->folder_hash,
|
||||
'$dragdroptext' => t('Drop files here to immediately upload'),
|
||||
'$notify' => ['notify', t('Show in your contacts shared folder'), 0, '', [t('No'), t('Yes')]]
|
||||
'$notify' => ['notify', t('Show in your contacts shared folder'), 0, '', [t('No'), t('Yes')]],
|
||||
'$breadcrumbs_html' => $breadcrumbs_html,
|
||||
'$drop_area_label' => t('You can select files via the upload button or drop them right here or into an existing folder.')
|
||||
));
|
||||
}
|
||||
|
||||
@@ -453,6 +596,21 @@ class Browser extends DAV\Browser\Plugin {
|
||||
return $hash;
|
||||
}
|
||||
|
||||
protected function findAttachHashFlat($owner, $attachName) {
|
||||
$r = q("SELECT hash FROM attach WHERE uid = %d AND filename = '%s' ORDER BY edited DESC LIMIT 1",
|
||||
intval($owner),
|
||||
dbesc($attachName)
|
||||
);
|
||||
$hash = '';
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$hash = $rr['hash'];
|
||||
}
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an attachment's id for a given hash.
|
||||
*
|
||||
|
||||
@@ -25,7 +25,10 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
* @var string $red_path
|
||||
*/
|
||||
private $red_path;
|
||||
private $folder_hash;
|
||||
public $folder_hash;
|
||||
public $data;
|
||||
|
||||
|
||||
/**
|
||||
* @brief The full path as seen in the browser.
|
||||
* /cloud + $red_path
|
||||
@@ -41,7 +44,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
*
|
||||
* @var string $os_path
|
||||
*/
|
||||
private $os_path = '';
|
||||
public $os_path = '';
|
||||
|
||||
/**
|
||||
* @brief Sets up the directory node, expects a full path.
|
||||
@@ -49,7 +52,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
* @param string $ext_path a full path
|
||||
* @param BasicAuth &$auth_plugin
|
||||
*/
|
||||
public function __construct($ext_path, &$auth_plugin) {
|
||||
public function __construct($ext_path, $data, &$auth_plugin) {
|
||||
// $ext_path = urldecode($ext_path);
|
||||
logger('directory ' . $ext_path, LOGGER_DATA);
|
||||
$this->ext_path = $ext_path;
|
||||
@@ -61,6 +64,8 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
}
|
||||
$this->auth = $auth_plugin;
|
||||
$this->folder_hash = '';
|
||||
$this->data = $data;
|
||||
|
||||
$this->getDir();
|
||||
|
||||
if($this->auth->browser) {
|
||||
@@ -116,7 +121,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
|
||||
$modulename = \App::$module;
|
||||
if ($this->red_path === '/' && $name === $modulename) {
|
||||
return new Directory('/' . $modulename, $this->auth);
|
||||
return new Directory('/' . $modulename, [], $this->auth);
|
||||
}
|
||||
|
||||
$x = $this->FileData($this->ext_path . '/' . $name, $this->auth);
|
||||
@@ -269,8 +274,8 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
dbesc($f),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
dbesc($allow_cid),
|
||||
dbesc($allow_gid),
|
||||
dbesc($deny_cid),
|
||||
@@ -293,7 +298,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
else {
|
||||
$size = file_put_contents($f, $data);
|
||||
}
|
||||
|
||||
|
||||
// delete attach entry if file_put_contents() failed
|
||||
if ($size === false) {
|
||||
logger('file_put_contents() failed to ' . $f);
|
||||
@@ -374,7 +379,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$args = array( 'resource_id' => $hash, 'album' => $album, 'os_syspath' => $f, 'os_path' => $xpath['os_path'], 'display_path' => $xpath['path'], 'filename' => $name, 'getimagesize' => $gis, 'directory' => $direct);
|
||||
$p = photo_upload($c[0], \App::get_observer(), $args);
|
||||
}
|
||||
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $hash ]);
|
||||
|
||||
$sync = attach_export_data($c[0], $hash);
|
||||
@@ -402,13 +407,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
|
||||
if ($r) {
|
||||
|
||||
// When initiated from DAV, set the 'force' flag on attach_mkdir(). This will cause the operation to report success even if the
|
||||
// folder already exists.
|
||||
// When initiated from DAV, set the 'force' flag on attach_mkdir(). This will cause the operation to report success even if the
|
||||
// folder already exists.
|
||||
|
||||
require_once('include/attach.php');
|
||||
$result = attach_mkdir($r[0], $this->auth->observer, array('filename' => $name, 'folder' => $this->folder_hash, 'force' => true));
|
||||
|
||||
if($result['success']) {
|
||||
|
||||
$sync = attach_export_data($r[0],$result['data']['hash']);
|
||||
logger('createDirectory: attach_export_data returns $sync:' . print_r($sync, true), LOGGER_DEBUG);
|
||||
|
||||
@@ -476,15 +482,16 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
|
||||
public function moveInto($targetName,$sourcePath, DAV\INode $sourceNode) {
|
||||
|
||||
if(! $this->auth->owner_id) {
|
||||
return false;
|
||||
}
|
||||
$channel_id = $this->auth->owner_id;
|
||||
// Files have $sourceNode->data['hash'] set. For directories rely on $sourceNode->folder_hash.
|
||||
$resource_id = ((isset($sourceNode->data['hash'])) ? $sourceNode->data['hash'] : $sourceNode->folder_hash);
|
||||
$new_folder_hash = $this->folder_hash;
|
||||
|
||||
if(! ($sourceNode->data && $sourceNode->data->hash)) {
|
||||
if(!$channel_id && !$resource_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
return attach_move($this->auth->owner_id, $sourceNode->data->hash, $this->folder_hash);
|
||||
$ret = attach_move($channel_id, $resource_id, $new_folder_hash);
|
||||
return $ret['success'];
|
||||
|
||||
}
|
||||
|
||||
@@ -515,6 +522,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$file = trim($file, '/');
|
||||
$path_arr = explode('/', $file);
|
||||
|
||||
|
||||
if (! $path_arr)
|
||||
return;
|
||||
|
||||
@@ -609,6 +617,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$file = trim($file, '/');
|
||||
$path_arr = explode('/', $file);
|
||||
|
||||
$cat = $_REQUEST['cat'];
|
||||
|
||||
|
||||
if (! $path_arr)
|
||||
return null;
|
||||
|
||||
@@ -679,7 +690,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$_SESSION['cloud_sort'] = 'name';
|
||||
|
||||
switch($_SESSION['cloud_sort']) {
|
||||
case 'size':
|
||||
case 'size':
|
||||
$suffix = ' order by is_dir desc, filesize asc ';
|
||||
break;
|
||||
// The following provides inconsistent results for directories because we re-calculate the date for directories based on the most recent change
|
||||
@@ -692,17 +703,34 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
break;
|
||||
}
|
||||
|
||||
$r = q("select $prefix id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, created, edited from attach where folder = '%s' and uid = %d $perms $suffix",
|
||||
dbesc($folder),
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($cat) {
|
||||
$r = q("select $prefix attach.id, attach.uid, attach.hash, attach.filename, attach.is_photo,
|
||||
attach.filetype, attach.filesize, attach.revision, attach.folder, attach.creator,
|
||||
attach.flags, attach.is_dir, attach.created, attach.edited, attach.display_path,
|
||||
attach.allow_cid, attach.allow_gid, attach.deny_cid, attach.deny_gid from attach
|
||||
left join term on attach.id = term.oid
|
||||
where term.term = '%s' and attach.uid = %d $perms $suffix",
|
||||
dbesc($cat),
|
||||
intval($channel_id)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("select $prefix attach.id, attach.uid, attach.hash, attach.filename, attach.is_photo,
|
||||
attach.filetype, attach.filesize, attach.revision, attach.folder, attach.creator,
|
||||
attach.flags, attach.is_dir, attach.created, attach.edited, attach.display_path,
|
||||
attach.allow_cid, attach.allow_gid, attach.deny_cid, attach.deny_gid from attach
|
||||
where folder = '%s' and uid = %d $perms $suffix",
|
||||
dbesc($folder),
|
||||
intval($channel_id)
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($r as $rr) {
|
||||
if(\App::$module === 'cloud' && (strpos($rr['filename'],'.') === 0) && (! get_pconfig($channel_id,'system','show_dot_files')) )
|
||||
continue;
|
||||
|
||||
// @FIXME I don't think we use revisions currently in attach structures.
|
||||
// In case we see any in the wild provide a unique filename. This
|
||||
// In case we see any in the wild provide a unique filename. This
|
||||
// name may or may not be accessible
|
||||
|
||||
if($rr['revision'])
|
||||
@@ -710,13 +738,12 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
|
||||
//logger('filename: ' . $rr['filename'], LOGGER_DEBUG);
|
||||
if (intval($rr['is_dir'])) {
|
||||
$ret[] = new Directory($path . '/' . $rr['filename'], $auth);
|
||||
$ret[] = new Directory($path . '/' . $rr['filename'], $rr, $auth);
|
||||
}
|
||||
else {
|
||||
$ret[] = new File($path . '/' . $rr['filename'], $rr, $auth);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -738,15 +765,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0",
|
||||
$r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0 and profile.is_default = 1",
|
||||
intval(PAGE_HIDDEN)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish']) {
|
||||
if ((perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish'])|| $rr['channel_id'] == $this->auth->channel_id) {
|
||||
logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA);
|
||||
$ret[] = new Directory($rr['channel_address'], $auth);
|
||||
$ret[] = new Directory($rr['channel_address'], [], $auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -778,7 +804,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
}
|
||||
|
||||
if ((! $file) || ($file === '/')) {
|
||||
return new Directory('/', $auth);
|
||||
return new Directory('/', [], $auth);
|
||||
}
|
||||
|
||||
$file = trim($file, '/');
|
||||
@@ -848,7 +874,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
if ($test)
|
||||
return true;
|
||||
// final component was a directory.
|
||||
return new Directory($file, $auth);
|
||||
return new Directory($file, [], $auth);
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
@@ -867,7 +893,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
return true;
|
||||
|
||||
if (intval($r[0]['is_dir'])) {
|
||||
return new Directory($path . '/' . $r[0]['filename'], $auth);
|
||||
return new Directory($path . '/' . $r[0]['filename'], [], $auth);
|
||||
}
|
||||
else {
|
||||
return new File($path . '/' . $r[0]['filename'], $r[0], $auth);
|
||||
@@ -888,7 +914,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$used = 0;
|
||||
$limit = 0;
|
||||
$free = 0;
|
||||
|
||||
|
||||
if ($this->auth->owner_id) {
|
||||
$channel = channelx_by_n($this->auth->owner_id);
|
||||
if($channel) {
|
||||
@@ -919,5 +945,4 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
return [ (int) $used, (int) $free ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
34
Zotlabs/Update/_1240.php
Normal file
34
Zotlabs/Update/_1240.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1240 {
|
||||
|
||||
function run() {
|
||||
|
||||
q("START TRANSACTION");
|
||||
|
||||
// remove broken xchan entries
|
||||
$r0 = dbq("DELETE FROM xchan WHERE xchan_hash = ''");
|
||||
|
||||
// remove broken hubloc entries
|
||||
$r1 = dbq("DELETE FROM hubloc WHERE hubloc_hash = ''");
|
||||
|
||||
// fix legacy zot hubloc_id_url
|
||||
$r2 = dbq("UPDATE hubloc
|
||||
SET hubloc_id_url = CONCAT(hubloc_url, '/channel/', SUBSTRING(hubloc_addr FROM 1 FOR POSITION('@' IN hubloc_addr) -1))
|
||||
WHERE hubloc_network = 'zot'
|
||||
AND hubloc_id_url = ''"
|
||||
);
|
||||
|
||||
if($r0 && $r1 && $r2) {
|
||||
q("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
q("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -151,13 +151,13 @@ class HTTPSig {
|
||||
|
||||
$result['signer'] = $sig_block['keyId'];
|
||||
|
||||
$key = self::get_key($key,$keytype,$result['signer']);
|
||||
$cached_key = self::get_key($key,$keytype,$result['signer']);
|
||||
|
||||
if(! ($key && $key['public_key'])) {
|
||||
if(! ($cached_key && $cached_key['public_key'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$x = rsa_verify($signed_data,$sig_block['signature'],$key['public_key'],$algorithm);
|
||||
$x = rsa_verify($signed_data,$sig_block['signature'],$cached_key['public_key'],$algorithm);
|
||||
|
||||
logger('verified: ' . $x, LOGGER_DEBUG);
|
||||
|
||||
@@ -166,15 +166,15 @@ class HTTPSig {
|
||||
// try again, ignoring the local actor (xchan) cache and refetching the key
|
||||
// from its source
|
||||
|
||||
$fkey = self::get_key($key,$keytype,$result['signer'],true);
|
||||
$fetched_key = self::get_key($key,$keytype,$result['signer'],true);
|
||||
|
||||
if ($fkey && $fkey['public_key']) {
|
||||
$y = rsa_verify($signed_data,$sig_block['signature'],$fkey['public_key'],$algorithm);
|
||||
if ($fetched_key && $fetched_key['public_key']) {
|
||||
$y = rsa_verify($signed_data,$sig_block['signature'],$fetched_key['public_key'],$algorithm);
|
||||
logger('verified: (cache reload) ' . $x, LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
if (! $y) {
|
||||
logger('verify failed for ' . $result['signer'] . ' alg=' . $algorithm . (($fkey['public_key']) ? '' : ' no key'));
|
||||
logger('verify failed for ' . $result['signer'] . ' alg=' . $algorithm . (($fetched_key['public_key']) ? '' : ' no key'));
|
||||
$sig_block['signature'] = base64_encode($sig_block['signature']);
|
||||
logger('affected sigblock: ' . print_r($sig_block,true));
|
||||
logger('headers: ' . print_r($headers,true));
|
||||
@@ -184,6 +184,8 @@ class HTTPSig {
|
||||
|
||||
}
|
||||
|
||||
$key = (($fetched_key) ? $fetched_key : $cached_key);
|
||||
|
||||
$result['portable_id'] = $key['portable_id'];
|
||||
$result['header_valid'] = true;
|
||||
|
||||
@@ -212,6 +214,9 @@ class HTTPSig {
|
||||
|
||||
static function get_key($key,$keytype,$id) {
|
||||
|
||||
if(is_array($key))
|
||||
btlogger('key is array: ' . print_r($key,true));
|
||||
|
||||
if($key) {
|
||||
if(function_exists($key)) {
|
||||
return $key($id);
|
||||
@@ -241,7 +246,7 @@ class HTTPSig {
|
||||
|
||||
function convertKey($key) {
|
||||
|
||||
if(strstr($key,'RSA ')) {
|
||||
if(strstr($key,'RSA ')) {
|
||||
return rsatopem($key);
|
||||
}
|
||||
elseif(substr($key,0,5) === 'data:') {
|
||||
@@ -450,7 +455,7 @@ class HTTPSig {
|
||||
foreach($headers as $h) {
|
||||
header($h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ class Categories {
|
||||
if(($articles) && (! Apps::system_app_installed(App::$profile['profile_uid'],'Articles')))
|
||||
return '';
|
||||
|
||||
if((! App::$profile['profile_uid'])
|
||||
$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')))) {
|
||||
return '';
|
||||
}
|
||||
@@ -29,12 +31,14 @@ class Categories {
|
||||
$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);
|
||||
$srchurl = str_replace(array('?f=','&f=', '/?'),array('', '', ''),$srchurl);
|
||||
|
||||
if($cards)
|
||||
return cardcategories_widget($srchurl, $cat);
|
||||
elseif($articles)
|
||||
return articlecategories_widget($srchurl, $cat);
|
||||
elseif($files)
|
||||
return filecategories_widget($srchurl, $cat);
|
||||
else
|
||||
return categories_widget($srchurl, $cat);
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
require_once('include/dir_fns.php');
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Dirsort {
|
||||
function widget($arr) {
|
||||
return dir_sort_links();
|
||||
return Libzotdir::dir_sort_links();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class Finger {
|
||||
$headers = [];
|
||||
$headers['X-Zot-Channel'] = $channel['channel_address'] . '@' . \App::get_hostname();
|
||||
$headers['X-Zot-Nonce'] = random_string();
|
||||
$xhead = HTTPSig::create_sig($headers,$channel['channel_prvkey'],'acct:' . channel_reddress($channel));
|
||||
$xhead = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel));
|
||||
|
||||
$retries = 0;
|
||||
|
||||
@@ -100,7 +100,7 @@ class Finger {
|
||||
$result = z_post_url('http://' . $host . $rhs,$postvars, $retries, [ 'headers' => $xhead ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$rhs .= '?f=&address=' . urlencode($address) . '&token=' . self::$token;
|
||||
|
||||
|
||||
@@ -226,18 +226,18 @@ class Zot6Handler implements IHandler {
|
||||
if ($recipients) {
|
||||
// basically this means "unfriend"
|
||||
foreach ($recipients as $recip) {
|
||||
$r = q("select channel.*,xchan.* from channel
|
||||
$channel = q("select channel.*,xchan.* from channel
|
||||
left join xchan on channel_hash = xchan_hash
|
||||
where channel_hash = '%s' limit 1",
|
||||
dbesc($recip)
|
||||
);
|
||||
if ($r) {
|
||||
$r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1",
|
||||
intval($r[0]['channel_id']),
|
||||
if ($channel) {
|
||||
$abook = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1",
|
||||
intval($channel[0]['channel_id']),
|
||||
dbesc($sender)
|
||||
);
|
||||
if ($r) {
|
||||
contact_remove($r[0]['channel_id'],$r[0]['abook_id']);
|
||||
if ($abook) {
|
||||
contact_remove($channel[0]['channel_id'],$abook[0]['abook_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
version: 2
|
||||
url: $baseurl/mail/combined
|
||||
requires: local_channel
|
||||
name: Mail
|
||||
photo: icon:envelope
|
||||
categories: nav_featured_app, Personal
|
||||
BIN
app/mail.png
BIN
app/mail.png
Binary file not shown.
|
Before Width: | Height: | Size: 4.8 KiB |
24
boot.php
24
boot.php
@@ -50,10 +50,10 @@ require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '5.0.2' );
|
||||
define ( 'STD_VERSION', '5.2' );
|
||||
define ( 'ZOT_REVISION', '6.0' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1239 );
|
||||
define ( 'DB_UPDATE_VERSION', 1240 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
@@ -82,11 +82,16 @@ define ( 'DIRECTORY_MODE_STANDALONE', 0x0100); // A detached (off the grid) hub
|
||||
define ( 'DIRECTORY_REALM', 'RED_GLOBAL');
|
||||
define ( 'DIRECTORY_FALLBACK_MASTER', 'https://hub.netzgemeinde.eu');
|
||||
|
||||
$DIRECTORY_FALLBACK_SERVERS = array(
|
||||
'https://hub.netzgemeinde.eu',
|
||||
'https://zotsite.net',
|
||||
'https://hub.libranet.de'
|
||||
);
|
||||
|
||||
function get_directory_fallback_servers() {
|
||||
$ret = [
|
||||
'https://hub.netzgemeinde.eu',
|
||||
'https://zotsite.net',
|
||||
'https://hub.libranet.de'
|
||||
];
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -355,6 +360,7 @@ define ( 'UPDATE_FLAGS_UPDATED', 0x0001);
|
||||
define ( 'UPDATE_FLAGS_FORCED', 0x0002);
|
||||
define ( 'UPDATE_FLAGS_DELETED', 0x1000);
|
||||
|
||||
define ( 'HUBLOC_OFFLINE', 0x0001);
|
||||
|
||||
define ( 'DROPITEM_NORMAL', 0);
|
||||
define ( 'DROPITEM_PHASE1', 1);
|
||||
@@ -433,7 +439,7 @@ define ( 'TERM_FORUM', 11 );
|
||||
define ( 'TERM_EMOJI', 12 );
|
||||
|
||||
define ( 'TERM_OBJ_POST', 1 );
|
||||
define ( 'TERM_OBJ_PHOTO', 2 );
|
||||
define ( 'TERM_OBJ_FILE', 2 );
|
||||
define ( 'TERM_OBJ_PROFILE', 3 );
|
||||
define ( 'TERM_OBJ_CHANNEL', 4 );
|
||||
define ( 'TERM_OBJ_OBJECT', 5 );
|
||||
@@ -2017,7 +2023,7 @@ function proc_run(){
|
||||
}
|
||||
|
||||
$args = array_map('escapeshellarg',$args);
|
||||
$cmdline = implode($args," ");
|
||||
$cmdline = implode(' ', $args);
|
||||
|
||||
if(is_windows()) {
|
||||
$cwd = getcwd();
|
||||
|
||||
152
composer.json
152
composer.json
@@ -1,76 +1,80 @@
|
||||
{
|
||||
"name" : "zotlabs/hubzilla",
|
||||
"type" : "application",
|
||||
"description" : "Hubzilla is a powerful platform for creating interconnected websites featuring a decentralized identity, communications, and permissions framework built using common webserver technology.",
|
||||
"keywords" : [
|
||||
"CMS",
|
||||
"identity",
|
||||
"decentralisation",
|
||||
"permission",
|
||||
"SSO",
|
||||
"ZOT"
|
||||
],
|
||||
"homepage" : "http://framagit.org/hubzilla/core/",
|
||||
"license" : "MIT",
|
||||
"authors" : [{
|
||||
"name" : "Mike Macgirvin",
|
||||
"role" : "founder"
|
||||
}
|
||||
],
|
||||
"support" : {
|
||||
"issues" : "https://framagit.org/hubzilla/core/issues",
|
||||
"source" : "https://framagit.org/hubzilla/core/"
|
||||
},
|
||||
"require" : {
|
||||
"php" : ">=5.5",
|
||||
"ext-curl" : "*",
|
||||
"ext-gd" : "*",
|
||||
"ext-mbstring" : "*",
|
||||
"ext-xml" : "*",
|
||||
"ext-openssl" : "*",
|
||||
"sabre/dav" : "^4.0",
|
||||
"michelf/php-markdown" : "^1.7",
|
||||
"bshaffer/oauth2-server-php": "^1.9",
|
||||
"ezyang/htmlpurifier": "^4.9",
|
||||
"simplepie/simplepie": "~1.5",
|
||||
"league/html-to-markdown": "^4.4",
|
||||
"pear/text_languagedetect": "^1.0",
|
||||
"commerceguys/intl": "~1.0.5",
|
||||
"lukasreschke/id3parser": "^0.0.3",
|
||||
"smarty/smarty": "~3.1",
|
||||
"ramsey/uuid": "^3.8",
|
||||
"twbs/bootstrap": "^4.3.1",
|
||||
"blueimp/jquery-file-upload": "^10.3",
|
||||
"desandro/imagesloaded": "^4.1"
|
||||
},
|
||||
"require-dev" : {
|
||||
"phpunit/phpunit" : "@stable",
|
||||
"behat/behat" : "@stable",
|
||||
"behat/mink-extension": "@stable",
|
||||
"behat/mink-goutte-driver": "@stable",
|
||||
"php-mock/php-mock-phpunit": "@stable",
|
||||
"phpunit/dbunit": "@stable",
|
||||
"phpmd/phpmd": "^2.6",
|
||||
"squizlabs/php_codesniffer": "*"
|
||||
},
|
||||
"autoload" : {
|
||||
"psr-4" : {
|
||||
"Hubzilla\\" : "include/",
|
||||
"Zotlabs\\" : "Zotlabs/"
|
||||
}
|
||||
},
|
||||
"autoload-dev" : {
|
||||
"psr-4" : {
|
||||
"Zotlabs\\Tests\\Unit\\" : "tests/unit"
|
||||
}
|
||||
},
|
||||
"minimum-stability" : "stable",
|
||||
"config" : {
|
||||
"notify-on-install" : false,
|
||||
"optimize-autoloader" : true
|
||||
},
|
||||
"repositories": [{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/simplepie/simplepie"
|
||||
}]
|
||||
"name": "zotlabs/hubzilla",
|
||||
"type": "application",
|
||||
"description": "Hubzilla is a powerful platform for creating interconnected websites featuring a decentralized identity, communications, and permissions framework built using common webserver technology.",
|
||||
"keywords": [
|
||||
"CMS",
|
||||
"identity",
|
||||
"decentralisation",
|
||||
"permission",
|
||||
"SSO",
|
||||
"ZOT"
|
||||
],
|
||||
"homepage": "http://framagit.org/hubzilla/core/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mike Macgirvin",
|
||||
"role": "founder"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://framagit.org/hubzilla/core/issues",
|
||||
"source": "https://framagit.org/hubzilla/core/"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5",
|
||||
"ext-curl": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-openssl": "*",
|
||||
"sabre/dav": "^4.0",
|
||||
"michelf/php-markdown": "^1.7",
|
||||
"bshaffer/oauth2-server-php": "^1.9",
|
||||
"ezyang/htmlpurifier": "^4.9",
|
||||
"simplepie/simplepie": "~1.5",
|
||||
"league/html-to-markdown": "^4.4",
|
||||
"pear/text_languagedetect": "^1.0",
|
||||
"commerceguys/intl": "~1.0.5",
|
||||
"lukasreschke/id3parser": "^0.0.3",
|
||||
"smarty/smarty": "~3.1",
|
||||
"ramsey/uuid": "^4.1",
|
||||
"twbs/bootstrap": "^4.3.1",
|
||||
"blueimp/jquery-file-upload": "^10.3",
|
||||
"desandro/imagesloaded": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.4",
|
||||
"behat/behat": "@stable",
|
||||
"behat/mink-extension": "@stable",
|
||||
"behat/mink-goutte-driver": "@stable",
|
||||
"php-mock/php-mock-phpunit": "^2.6",
|
||||
"phpmd/phpmd": "^2.6",
|
||||
"squizlabs/php_codesniffer": "*",
|
||||
"php-mock/php-mock": "^2.2",
|
||||
"dms/phpunit-arraysubset-asserts": "^0.2.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hubzilla\\": "include/",
|
||||
"Zotlabs\\": "Zotlabs/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Zotlabs\\Tests\\Unit\\": "tests/unit"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"notify-on-install": false,
|
||||
"optimize-autoloader": true
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/simplepie/simplepie"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
4033
composer.lock
generated
4033
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -82,7 +82,6 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
|
||||
$r = q("SELECT id, hash, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$groups .= '<optgroup label = "' . t('Privacy Groups').'">';
|
||||
foreach($r as $rr) {
|
||||
@@ -110,13 +109,23 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
|
||||
if($dialog_description) {
|
||||
$forums = get_forum_channels(local_channel(),1);
|
||||
if($forums) {
|
||||
$groups .= '<optgroup label = "' . t('Forums').'">';
|
||||
$forums_count = 0;
|
||||
$forum_otions = '';
|
||||
foreach($forums as $f) {
|
||||
if($f['no_post_perms'])
|
||||
continue;
|
||||
|
||||
$private = (($f['private_forum']) ? ' (' . t('Private Forum') . ')' : '');
|
||||
$selected = (($single_group && $f['hash'] === $allow_cid[0]) ? ' selected = "selected" ' : '');
|
||||
$groups .= '<option id="^' . $f['abook_id'] . '" value="^' . $f['xchan_hash'] . '"' . $selected . '>' . $f['xchan_name'] . $private . '</option>' . "\r\n";
|
||||
$forum_otions .= '<option id="^' . $f['abook_id'] . '" value="^' . $f['xchan_hash'] . '"' . $selected . '>' . $f['xchan_name'] . $private . '</option>' . "\r\n";
|
||||
$forums_count++;
|
||||
}
|
||||
$groups .= '</optgroup>';
|
||||
if($forums_count) {
|
||||
$groups .= '<optgroup label = "' . t('Forums').'">';
|
||||
$groups .= $forum_otions;
|
||||
$groups .= '</optgroup>';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -300,6 +300,44 @@ function attach_by_hash($hash, $observer_hash, $rev = 0) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find an attachment by id.
|
||||
*
|
||||
* Returns the entire attach structure including data.
|
||||
*
|
||||
* This could exhaust memory so most useful only when immediately sending the data.
|
||||
*
|
||||
* @param string $hash
|
||||
* @param string $observer_hash
|
||||
* @return array
|
||||
*/
|
||||
function attach_by_id($id, $observer_hash) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
|
||||
// Check for existence, which will also provide us the owner uid
|
||||
|
||||
$r = q("SELECT * FROM attach WHERE id = %d",
|
||||
intval($id)
|
||||
);
|
||||
if(! $r) {
|
||||
$ret['message'] = t('Item was not found.');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if(! attach_can_view($r[0]['uid'], $observer_hash, $r[0]['hash'])) {
|
||||
$ret['message'] = t('Permission denied.');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r[0]['content'] = dbunescbin($r[0]['content']);
|
||||
|
||||
$ret['success'] = true;
|
||||
$ret['data'] = $r[0];
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function attach_can_view($uid,$ob_hash,$resource) {
|
||||
|
||||
$sql_extra = permissions_sql($uid,$ob_hash);
|
||||
@@ -647,17 +685,15 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$pathname = filepath_macro($newalbum);
|
||||
}
|
||||
elseif(array_key_exists('folder',$arr)) {
|
||||
$x = q("select filename from attach where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['folder']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($x)
|
||||
$pathname = $x[0]['filename'];
|
||||
$pathname = find_path_by_hash($channel['channel_id'], $arr['folder']);
|
||||
}
|
||||
else {
|
||||
$pathname = filepath_macro($album);
|
||||
}
|
||||
}
|
||||
elseif(array_key_exists('folder',$arr)) {
|
||||
$pathname = find_path_by_hash($channel['channel_id'], $arr['folder']);
|
||||
}
|
||||
if(! $pathname) {
|
||||
$pathname = filepath_macro($upload_path);
|
||||
}
|
||||
@@ -807,6 +843,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$os_relpath = ltrim($os_relpath,'/');
|
||||
|
||||
$os_path = $os_relpath;
|
||||
|
||||
$display_path = ltrim($pathname . '/' . $filename,'/');
|
||||
|
||||
if($src) {
|
||||
@@ -890,7 +927,6 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
$r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, content, created, edited, os_path, display_path, allow_cid, allow_gid,deny_cid, deny_gid )
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
|
||||
intval($channel['channel_account_id']),
|
||||
@@ -1122,7 +1158,6 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
|
||||
if(! is_dir($os_basepath))
|
||||
os_mkdir($os_basepath,STORAGE_DEFAULT_PERMISSIONS, true);
|
||||
|
||||
|
||||
$os_basepath .= '/';
|
||||
|
||||
if(! perm_is_allowed($channel_id, $observer_hash, 'write_storage')) {
|
||||
@@ -1432,7 +1467,7 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
|
||||
$channel_address = (($c) ? $c[0]['channel_address'] : 'notfound');
|
||||
$photo_sql = (($is_photo) ? " and is_photo = 1 " : '');
|
||||
|
||||
$r = q("SELECT hash, os_storage, flags, is_dir, is_photo, folder FROM attach WHERE hash = '%s' AND uid = %d $photo_sql limit 1",
|
||||
$r = q("SELECT id, hash, os_storage, flags, is_dir, is_photo, folder FROM attach WHERE hash = '%s' AND uid = %d $photo_sql limit 1",
|
||||
dbesc($resource),
|
||||
intval($channel_id)
|
||||
);
|
||||
@@ -1453,6 +1488,12 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
|
||||
intval($channel_id),
|
||||
intval($r[0]['id']),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
|
||||
// If resource is a directory delete everything in the directory recursive
|
||||
if(intval($r[0]['is_dir'])) {
|
||||
$x = q("SELECT hash, os_storage, is_dir, flags FROM attach WHERE folder = '%s' AND uid = %d",
|
||||
@@ -1534,7 +1575,7 @@ function attach_drop_photo($channel_id,$resource) {
|
||||
$interactive = (($x[0]['item_hidden']) ? false : true);
|
||||
drop_item($x[0]['id'], $interactive, $stage);
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1",
|
||||
dbesc($resource),
|
||||
intval($channel_id)
|
||||
@@ -1544,7 +1585,7 @@ function attach_drop_photo($channel_id,$resource) {
|
||||
@unlink(dbunescbin($i['content']));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
q("DELETE FROM photo WHERE uid = %d AND resource_id = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($resource)
|
||||
@@ -1740,6 +1781,29 @@ function find_filename_by_hash($channel_id, $attachHash) {
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the display_path of an attachment in a given channel.
|
||||
*
|
||||
* @param int $channel_id
|
||||
* The id of the channel
|
||||
* @param string $attachHash
|
||||
* The hash of the attachment
|
||||
* @return string
|
||||
* The filename of the attachment
|
||||
*/
|
||||
function find_path_by_hash($channel_id, $attachHash) {
|
||||
$r = q("SELECT display_path FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
intval($channel_id),
|
||||
dbesc($attachHash)
|
||||
);
|
||||
$display_path = '';
|
||||
if ($r) {
|
||||
$display_path = $r[0]['display_path'];
|
||||
}
|
||||
|
||||
return $display_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pipes $in to $out in 16KB chunks.
|
||||
*
|
||||
@@ -2306,6 +2370,18 @@ function attach_export_data($channel, $resource_id, $deleted = false) {
|
||||
$r[0]['content'] = dbunescbin($r[0]['content']);
|
||||
|
||||
$hash_ptr = $r[0]['folder'];
|
||||
|
||||
$r[0]['term'] = [];
|
||||
|
||||
$term = q("SELECT * FROM term WHERE uid = %d AND oid = %d AND otype = %d",
|
||||
intval($channel['channel_id']),
|
||||
intval($r[0]['id']),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
|
||||
if ($term)
|
||||
$r[0]['term'] = array_reverse($term);
|
||||
|
||||
$paths[] = $r[0];
|
||||
} while($hash_ptr);
|
||||
|
||||
@@ -2314,7 +2390,6 @@ function attach_export_data($channel, $resource_id, $deleted = false) {
|
||||
|
||||
$ret['attach'] = $paths;
|
||||
|
||||
|
||||
if($attach_ptr['is_photo']) {
|
||||
|
||||
// This query could potentially result in a few megabytes of data use.
|
||||
@@ -2495,7 +2570,7 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* This function performs an in place directory-to-directory move of a stored attachment or photo.
|
||||
* This function performs an in place directory-to-directory move of a stored resource.
|
||||
* The data is physically moved in the store/nickname storage location and the paths adjusted
|
||||
* in the attach structure (and if applicable the photo table). The new 'album name' is recorded
|
||||
* for photos and will show up immediately there.
|
||||
@@ -2507,60 +2582,64 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat
|
||||
* @param int $channel_id
|
||||
* @param int $resource_id
|
||||
* @param string $new_folder_hash
|
||||
* @return void|boolean
|
||||
* @param (optional) string $newname
|
||||
* @param (optional) boolean $recurse
|
||||
* @return array Associative array with:
|
||||
* * \e boolean \b success
|
||||
* * \e string \b resource_id
|
||||
*/
|
||||
function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '', $recurse = true) {
|
||||
|
||||
$ret = [
|
||||
'success' => false,
|
||||
'resource_id' => $resource_id
|
||||
];
|
||||
|
||||
$c = channelx_by_n($channel_id);
|
||||
if(! ($c && $resource_id))
|
||||
return false;
|
||||
|
||||
return $ret;
|
||||
|
||||
// find the resource to be moved
|
||||
|
||||
$r = q("select * from attach where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if(! $r) {
|
||||
logger('resource_id not found');
|
||||
return false;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$oldstorepath = dbunescbin($r[0]['content']);
|
||||
|
||||
|
||||
// find the resource we are moving to
|
||||
|
||||
if($new_folder_hash) {
|
||||
$n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1",
|
||||
dbesc($new_folder_hash),
|
||||
intval($channel_id)
|
||||
);
|
||||
if(! $n)
|
||||
return false;
|
||||
return $ret;
|
||||
|
||||
$newdirname = $n[0]['filename'];
|
||||
$newalbumname = $n[0]['display_path'];
|
||||
$newstorepath = dbunescbin($n[0]['content']) . '/' . $resource_id;
|
||||
}
|
||||
else {
|
||||
|
||||
// root directory
|
||||
|
||||
$newdirname = EMPTY_STR;
|
||||
$newalbumname = EMPTY_STR;
|
||||
$newstorepath = 'store/' . $c['channel_address'] . '/' . $resource_id;
|
||||
}
|
||||
|
||||
rename($oldstorepath,$newstorepath);
|
||||
if ($recurse) {
|
||||
rename($oldstorepath,$newstorepath);
|
||||
}
|
||||
|
||||
// duplicate detection. If 'overwrite' is specified, return false because we can't yet do that.
|
||||
|
||||
$filename = $r[0]['filename'];
|
||||
|
||||
// don't do duplicate check unless our parent folder has changed.
|
||||
|
||||
if($r[0]['folder'] !== $new_folder_hash) {
|
||||
$oldfilename = $r[0]['filename'];
|
||||
$filename = (($newname) ? basename($newname) : $oldfilename);
|
||||
|
||||
// duplicate detection.
|
||||
if($recurse) {
|
||||
$s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ",
|
||||
dbesc($filename),
|
||||
dbesc($new_folder_hash)
|
||||
@@ -2568,9 +2647,10 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
|
||||
if($s) {
|
||||
$overwrite = get_pconfig($channel_id,'system','overwrite_dup_files');
|
||||
// If 'overwrite' is specified, return false because we can't yet do that.
|
||||
if($overwrite) {
|
||||
/// @fixme
|
||||
return;
|
||||
return $ret;
|
||||
}
|
||||
else {
|
||||
if(strpos($filename,'.') !== false) {
|
||||
@@ -2586,7 +2666,8 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
if(preg_match('/(.*?)\([0-9]{1,}\)$/',$basename,$matches))
|
||||
$basename = $matches[1];
|
||||
|
||||
$v = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ",
|
||||
$v = q("select filename from attach where uid = %d and ( filename = '%s' OR filename like '%s' ) and folder = '%s' ",
|
||||
intval($channel_id),
|
||||
dbesc($basename . $ext),
|
||||
dbesc($basename . '(%)' . $ext),
|
||||
dbesc($new_folder_hash)
|
||||
@@ -2609,12 +2690,14 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
while($found);
|
||||
$filename = $basename . '(' . $x . ')' . $ext;
|
||||
}
|
||||
else
|
||||
else {
|
||||
$filename = $basename . $ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
q("update attach set content = '%s', folder = '%s', filename = '%s' where id = %d",
|
||||
dbescbin($newstorepath),
|
||||
dbesc($new_folder_hash),
|
||||
@@ -2631,7 +2714,6 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
|
||||
|
||||
if($r[0]['is_photo']) {
|
||||
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s'
|
||||
where resource_id = '%s' and uid = %d",
|
||||
@@ -2643,11 +2725,24 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
q("update photo set content = '%s' where resource_id = '%s' and uid = %d and imgscale = 0",
|
||||
q("update photo set content = CASE imgscale WHEN 0 THEN '%s' ELSE CONCAT('%s', '-', imgscale) END where resource_id = '%s' and uid = %d and os_storage = 1",
|
||||
dbescbin($newstorepath),
|
||||
dbescbin($newstorepath),
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
// now rename the thumbnails in os_storage - the original should have been copied before already
|
||||
$ps = q("SELECT content, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and imgscale > 0 and os_storage = 1",
|
||||
intval($channel_id),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
if ($recurse) {
|
||||
foreach($ps as $p) {
|
||||
rename($oldstorepath . '-' . $p['imgscale'], $p['content']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($r[0]['is_dir']) {
|
||||
@@ -2658,19 +2753,223 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
$rs = attach_move($channel_id,$xv['hash'],$r[0]['hash']);
|
||||
if(! $rs) {
|
||||
$rs = attach_move($channel_id, $xv['hash'], $r[0]['hash'], '', false);
|
||||
if(! $rs['success']) {
|
||||
$move_success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $move_success;
|
||||
|
||||
$ret['success'] = $move_success;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return true;
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function performs an in place directory-to-directory copy of a stored resource.
|
||||
* The data is physically copyed in the store/nickname storage location and the paths adjusted
|
||||
* in the attach structure (and if applicable the photo table). The new 'album name' is recorded
|
||||
* for photos and will show up immediately there.
|
||||
* This takes a channel_id, attach.hash of the file to copy (this is the same as a photo resource_id), and
|
||||
* the attach.hash of the new parent folder, which must already exist. If $new_folder_hash is blank or empty,
|
||||
* the new file is copyed to the root of the channel's storage area.
|
||||
*
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @param int $resource_id
|
||||
* @param string $new_folder_hash
|
||||
* @param (optional) string $newname
|
||||
* @param (optional) boolean $recurse
|
||||
* @return array Associative array with:
|
||||
* * \e boolean \b success
|
||||
* * \e string \b resource_id of the new resource
|
||||
*/
|
||||
function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '', $recurse = true) {
|
||||
|
||||
$ret = [
|
||||
'success' => false,
|
||||
'resource_id' => ''
|
||||
];
|
||||
|
||||
$c = channelx_by_n($channel_id);
|
||||
if(! ($c && $resource_id))
|
||||
return $ret;
|
||||
|
||||
// find the resource to be copied
|
||||
$r = q("select * from attach where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
if(! $r) {
|
||||
logger('resource_id not found');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$a = $r[0];
|
||||
$new_resource_id = new_uuid();
|
||||
|
||||
$ret['resource_id'] = $new_resource_id;
|
||||
|
||||
$oldstorepath = dbunescbin($r[0]['content']);
|
||||
|
||||
// find the resource we are copying to
|
||||
if($new_folder_hash) {
|
||||
$n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1",
|
||||
dbesc($new_folder_hash),
|
||||
intval($channel_id)
|
||||
);
|
||||
if(! $n) {
|
||||
logger('new_folder_hash not found');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$newdirname = $n[0]['filename'];
|
||||
$newalbumname = $n[0]['display_path'];
|
||||
$newstorepath = dbunescbin($n[0]['content']) . '/' . $new_resource_id;
|
||||
}
|
||||
else {
|
||||
// root directory
|
||||
$newdirname = EMPTY_STR;
|
||||
$newalbumname = EMPTY_STR;
|
||||
$newstorepath = 'store/' . $c['channel_address'] . '/' . $new_resource_id;
|
||||
}
|
||||
|
||||
if(is_dir($oldstorepath)) {
|
||||
os_mkdir($newstorepath,STORAGE_DEFAULT_PERMISSIONS,true);
|
||||
}
|
||||
else {
|
||||
copy($oldstorepath,$newstorepath);
|
||||
}
|
||||
|
||||
$oldfilename = $r[0]['filename'];
|
||||
$filename = (($newname) ? basename($newname) : $oldfilename);
|
||||
|
||||
// duplicate detection. If 'overwrite' is specified, return false because we can't yet do that.
|
||||
if($recurse) {
|
||||
$s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ",
|
||||
dbesc($filename),
|
||||
dbesc($new_folder_hash)
|
||||
);
|
||||
|
||||
if($s) {
|
||||
$overwrite = get_pconfig($channel_id,'system','overwrite_dup_files');
|
||||
if($overwrite) {
|
||||
/// @fixme
|
||||
return $ret;
|
||||
}
|
||||
else {
|
||||
if(strpos($filename,'.') !== false) {
|
||||
$basename = substr($filename,0,strrpos($filename,'.'));
|
||||
$ext = substr($filename,strrpos($filename,'.'));
|
||||
}
|
||||
else {
|
||||
$basename = $filename;
|
||||
$ext = '';
|
||||
}
|
||||
|
||||
$matches = false;
|
||||
if(preg_match('/(.*?)\([0-9]{1,}\)$/',$basename,$matches))
|
||||
$basename = $matches[1];
|
||||
|
||||
$v = q("select filename from attach where uid = %d and ( filename = '%s' OR filename like '%s' ) and folder = '%s' ",
|
||||
intval($channel_id),
|
||||
dbesc($basename . $ext),
|
||||
dbesc($basename . '(%)' . $ext),
|
||||
dbesc($new_folder_hash)
|
||||
);
|
||||
|
||||
if($v) {
|
||||
$x = 1;
|
||||
|
||||
do {
|
||||
$found = false;
|
||||
foreach($v as $vv) {
|
||||
if($vv['filename'] === $basename . '(' . $x . ')' . $ext) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($found)
|
||||
$x++;
|
||||
}
|
||||
while($found);
|
||||
$filename = $basename . '(' . $x . ')' . $ext;
|
||||
}
|
||||
else {
|
||||
$filename = $basename . $ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($a['id']);
|
||||
$a['hash'] = $new_resource_id;
|
||||
$a['content'] = $newstorepath;
|
||||
$a['folder'] = $new_folder_hash;
|
||||
$a['filename'] = $filename;
|
||||
|
||||
create_table_from_array('attach', $a, ['content']);
|
||||
|
||||
$x = attach_syspaths($channel_id, $new_resource_id);
|
||||
|
||||
q("update attach set os_path = '%s', display_path = '%s' where hash = '%s'",
|
||||
dbesc($x['os_path']),
|
||||
dbesc($x['path']),
|
||||
dbesc($new_resource_id)
|
||||
);
|
||||
|
||||
if($a['is_photo']) {
|
||||
|
||||
$ps = q("SELECT * FROM photo WHERE uid = %d AND resource_id = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
foreach($ps as $p) {
|
||||
unset($p['id']);
|
||||
$p['resource_id'] = $new_resource_id;
|
||||
$p['album'] = $newalbumname;
|
||||
$p['filename'] = $filename;
|
||||
$p['os_path'] = $x['os_path'];
|
||||
$p['display_path'] = $x['path'];
|
||||
if($p['os_storage']) {
|
||||
$p['content'] = (($p['imgscale'] == 0) ? $newstorepath : $newstorepath . '-' . $p['imgscale']);
|
||||
|
||||
//the original should have been copied before already
|
||||
if($p['imgscale'] > 0)
|
||||
copy($oldstorepath, $p['content']);
|
||||
}
|
||||
create_table_from_array('photo', $p, ['content']);
|
||||
}
|
||||
}
|
||||
|
||||
if($r[0]['is_dir']) {
|
||||
$copy_success = true;
|
||||
$x = q("select hash from attach where folder = '%s' and uid = %d",
|
||||
dbesc($r[0]['hash']),
|
||||
intval($channel_id)
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
$rs = attach_copy($channel_id,$xv['hash'],$new_resource_id, '', false);
|
||||
if(! $rs['success']) {
|
||||
$copy_success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ret['success'] = $copy_success;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to generate a select input box of all your folders
|
||||
@@ -2688,10 +2987,7 @@ function attach_folder_select_list($channel_id) {
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$x = attach_folder_rpaths($r,$rv);
|
||||
if($x) {
|
||||
$out[$x[0]] = $x[1];
|
||||
}
|
||||
$out[$rv['hash']] = $rv['display_path'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2721,7 +3017,7 @@ function attach_folder_rpaths($all_folders,$that_folder) {
|
||||
if(! $found)
|
||||
$error = true;
|
||||
}
|
||||
while((! $found) && (! $error) && ($parent_hash != ''));
|
||||
while((! $error) && ($parent_hash != ''));
|
||||
}
|
||||
|
||||
return (($error) ? false : [ $current_hash , $path ]);
|
||||
|
||||
@@ -111,7 +111,7 @@ function process_cdav_card($f, &$vcard, $edit = false) {
|
||||
function import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backend, &$ids, $notice = false) {
|
||||
|
||||
$i = 0;
|
||||
$newid = (count($ids) ? false : true);
|
||||
$newid = (count($ids) ? false : true);
|
||||
|
||||
while ($object = $objects->getNext()) {
|
||||
|
||||
@@ -161,7 +161,7 @@ function import_cdav_card($id, $ext, $table, $column, $objects, $profile, $backe
|
||||
);
|
||||
}
|
||||
|
||||
if($notice && $exp == 'vcf') {
|
||||
if($notice && $ext == 'vcf') {
|
||||
notice(
|
||||
'<strong>' . t('INVALID CARD DISMISSED!') . '</strong>' . EOL .
|
||||
'<strong>' . t('Name: ') . '</strong>' . (($object->FN) ? $object->FN : t('Unknown')) . EOL .
|
||||
|
||||
@@ -651,7 +651,7 @@ function change_channel_keys($channel) {
|
||||
foreach($h as $hv) {
|
||||
$hv['hubloc_guid_sig'] = $sig;
|
||||
$hv['hubloc_hash'] = $hash;
|
||||
$hv['hubloc_url_sig'] = base64url_encode(rsa_sign(z_root(),$modifed['channel_prvkey']));
|
||||
$hv['hubloc_url_sig'] = base64url_encode(rsa_sign(z_root(),$modified['channel_prvkey']));
|
||||
hubloc_store_lowlevel($hv);
|
||||
}
|
||||
}
|
||||
@@ -929,12 +929,22 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
|
||||
$ret['abook'] = $r;
|
||||
|
||||
for($x = 0; $x < count($ret['abook']); $x ++) {
|
||||
|
||||
|
||||
$xchans[] = $ret['abook'][$x]['abook_xchan'];
|
||||
$my_perms = [];
|
||||
$their_perms = [];
|
||||
$newconfig = [];
|
||||
$abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
|
||||
|
||||
// Partly revert of commit 85cf25a2a8bfbbfe10de485d4affd54626fbbfa4
|
||||
if($abconfig) {
|
||||
$ret['abook'][$x]['abconfig'] = $abconfig;
|
||||
}
|
||||
|
||||
/* This was added in commit 85cf25a2a8bfbbfe10de485d4affd54626fbbfa4
|
||||
* Seems unfinished work on zap compatibility for cloning.
|
||||
* It breaks cloning of abconfig for hubzilla - reverted to the above code.
|
||||
|
||||
if($abconfig) {
|
||||
foreach ($abconfig as $abc) {
|
||||
|
||||
@@ -951,24 +961,28 @@ function identity_basic_export($channel_id, $sections = null, $zap_compat = fals
|
||||
}
|
||||
$newconfig[] = $abc;
|
||||
}
|
||||
|
||||
|
||||
$ret['abook'][$x]['abconfig'] = $newconfig;
|
||||
|
||||
if ($zap_compat) {
|
||||
$ret['abook'][$x]['abconfig'][] = [ 'chan' => $channel_id, 'xchan' => $ret['abook'][$x]['abook_chan'], 'cat' => 'system', 'k' => 'my_perms', 'v' => implode(',',$my_perms) ];
|
||||
$ret['abook'][$x]['abconfig'][] = [ 'chan' => $channel_id, 'xchan' => $ret['abook'][$x]['abook_chan'], 'cat' => 'system', 'k' => 'their_perms', 'v' => implode(',',$their_perms) ];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
translate_abook_perms_outbound($ret['abook'][$x]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// pick up the zot6 xchan and hublocs also
|
||||
|
||||
|
||||
|
||||
// pick up the zot xchan and hublocs also
|
||||
|
||||
if($ret['channel']['channel_portable_id']) {
|
||||
$xchans[] = $ret['channel']['channel_portable_id'];
|
||||
}
|
||||
|
||||
|
||||
stringify_array_elms($xchans);
|
||||
}
|
||||
|
||||
@@ -1801,7 +1815,7 @@ function advanced_profile() {
|
||||
$profile['howlong'] = relative_date(App::$profile['howlong'], t('for %1$d %2$s'));
|
||||
}
|
||||
|
||||
if(App::$profile['keywords']) {
|
||||
if(App::$profile['keywords']) {
|
||||
$keywords = str_replace(',',' ', App::$profile['keywords']);
|
||||
$keywords = str_replace(' ',' ', $keywords);
|
||||
$karr = explode(' ', $keywords);
|
||||
@@ -2573,26 +2587,6 @@ function channel_reddress($channel) {
|
||||
return strtolower($channel['channel_address'] . '@' . App::get_hostname());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get manual channel conversation update config.
|
||||
*
|
||||
* Check the channel config \e manual_conversation_update, if not set fall back
|
||||
* to global system config, defaults to 1 if nothing set.
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @return int
|
||||
*/
|
||||
function channel_manual_conv_update($channel_id) {
|
||||
|
||||
$x = get_pconfig($channel_id, 'system', 'manual_conversation_update');
|
||||
if($x === false)
|
||||
$x = get_config('system', 'manual_conversation_update', 1);
|
||||
|
||||
return intval($x);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return parsed HTML remote_login template.
|
||||
*
|
||||
@@ -2876,7 +2870,7 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
|
||||
attach_delete($channel_id,$rv['hash']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$r = q("select id from item where uid = %d", intval($channel_id));
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
@@ -2959,7 +2953,7 @@ function channel_remove_final($channel_id) {
|
||||
q("delete from abook where abook_channel = %d", intval($channel_id));
|
||||
q("delete from abconfig where chan = %d", intval($channel_id));
|
||||
q("delete from pconfig where uid = %d", intval($channel_id));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ function abook_connections($channel_id, $sql_conditions = '') {
|
||||
intval($channel_id)
|
||||
);
|
||||
return(($r) ? $r : array());
|
||||
}
|
||||
}
|
||||
|
||||
function abook_self($channel_id) {
|
||||
$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d
|
||||
@@ -79,7 +79,7 @@ function abook_self($channel_id) {
|
||||
intval($channel_id)
|
||||
);
|
||||
return(($r) ? $r[0] : array());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function vcard_from_xchan($xchan, $observer = null, $mode = '') {
|
||||
@@ -119,14 +119,15 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') {
|
||||
if(array_key_exists('channel_id',$xchan))
|
||||
App::$profile_uid = $xchan['channel_id'];
|
||||
|
||||
$url = (($observer)
|
||||
? z_root() . '/magic?f=&owa=1&bdest=' . bin2hex($xchan['xchan_url']) . '&addr=' . $xchan['xchan_addr']
|
||||
$url = (($observer)
|
||||
? z_root() . '/magic?f=&owa=1&bdest=' . bin2hex($xchan['xchan_url']) . '&addr=' . $xchan['xchan_addr']
|
||||
: $xchan['xchan_url']
|
||||
);
|
||||
|
||||
|
||||
return replace_macros(get_markup_template('xchan_vcard.tpl'),array(
|
||||
'$name' => $xchan['xchan_name'],
|
||||
'$photo' => ((is_array(App::$profile) && array_key_exists('photo',App::$profile)) ? App::$profile['photo'] : $xchan['xchan_photo_l']),
|
||||
'$addr' => (($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']),
|
||||
'$photo' => $xchan['xchan_photo_m'],
|
||||
'$follow' => (($xchan['xchan_addr']) ? $xchan['xchan_addr'] : $xchan['xchan_url']),
|
||||
'$link' => zid($xchan['xchan_url']),
|
||||
'$connect' => $connect,
|
||||
@@ -177,10 +178,10 @@ function abook_toggle_flag($abook,$flag) {
|
||||
);
|
||||
|
||||
|
||||
// if unsetting the archive bit, update the timestamps so we'll try to connect for an additional 30 days.
|
||||
// if unsetting the archive bit, update the timestamps so we'll try to connect for an additional 30 days.
|
||||
|
||||
if(($flag === ABOOK_FLAG_ARCHIVED) && (intval($abook['abook_archived']))) {
|
||||
$r = q("update abook set abook_connected = '%s', abook_updated = '%s'
|
||||
$r = q("update abook set abook_connected = '%s', abook_updated = '%s'
|
||||
where abook_id = %d and abook_channel = %d",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
@@ -210,7 +211,7 @@ function mark_orphan_hubsxchans() {
|
||||
if($dirmode == DIRECTORY_MODE_NORMAL)
|
||||
return;
|
||||
|
||||
$r = q("update hubloc set hubloc_error = 1 where hubloc_error = 0
|
||||
$r = q("update hubloc set hubloc_error = 1 where hubloc_error = 0
|
||||
and hubloc_network = 'zot' and hubloc_connected < %s - interval %s",
|
||||
db_utcnow(), db_quoteinterval('36 day')
|
||||
);
|
||||
@@ -301,9 +302,9 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) {
|
||||
);
|
||||
|
||||
// Cannot delete just one side of the conversation since we do not allow
|
||||
// you to block private mail replies. This would leave open a gateway for abuse.
|
||||
// you to block private mail replies. This would leave open a gateway for abuse.
|
||||
// Both participants are owners of the conversation and both can remove it.
|
||||
|
||||
|
||||
$r = q("delete from mail where ( from_xchan = '%s' or to_xchan = '%s' )",
|
||||
dbesc($xchan),
|
||||
dbesc($xchan)
|
||||
@@ -356,7 +357,7 @@ function contact_remove($channel_id, $abook_id) {
|
||||
call_hooks('connection_remove',$x);
|
||||
|
||||
|
||||
$archive = get_pconfig($channel_id, 'system','archive_removed_contacts');
|
||||
$archive = get_pconfig($channel_id, 'system', 'archive_removed_contacts');
|
||||
if($archive) {
|
||||
q("update abook set abook_archived = 1 where abook_id = %d and abook_channel = %d",
|
||||
intval($abook_id),
|
||||
@@ -387,7 +388,7 @@ function contact_remove($channel_id, $abook_id) {
|
||||
$already_saved = [];
|
||||
foreach($r as $rr) {
|
||||
$w = $x = $y = null;
|
||||
|
||||
|
||||
// optimise so we only process newly seen parent items
|
||||
if (in_array($rr['parent'],$already_saved)) {
|
||||
continue;
|
||||
@@ -423,7 +424,7 @@ function contact_remove($channel_id, $abook_id) {
|
||||
drop_item($rr['id'],false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
q("delete from abook where abook_id = %d and abook_channel = %d",
|
||||
intval($abook['abook_id']),
|
||||
intval($channel_id)
|
||||
@@ -471,7 +472,7 @@ function random_profile() {
|
||||
|
||||
$r = q("select xchan_url, xchan_hash from xchan left join hubloc on hubloc_hash = xchan_hash where
|
||||
xchan_hidden = 0 and xchan_system = 0 and
|
||||
xchan_network = 'zot' and xchan_deleted = 0 and
|
||||
xchan_network = 'zot6' and xchan_deleted = 0 and
|
||||
hubloc_connected > %s - interval %s order by $randfunc limit 1",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('30 day')
|
||||
@@ -501,17 +502,17 @@ function update_vcard($arr,$vcard = null) {
|
||||
|
||||
$fn = $arr['fn'];
|
||||
|
||||
|
||||
|
||||
// This isn't strictly correct and could be a cause for concern.
|
||||
// 'N' => array_reverse(explode(' ', $fn))
|
||||
|
||||
|
||||
// What we really want is
|
||||
// What we really want is
|
||||
// 'N' => Adams;John;Quincy;Reverend,Dr.;III
|
||||
// which is a very difficult parsing problem especially if you allow
|
||||
// the surname to contain spaces. The only way to be sure to get it
|
||||
// right is to provide a form to input all the various fields and not
|
||||
// try to extract it from the FN.
|
||||
// right is to provide a form to input all the various fields and not
|
||||
// try to extract it from the FN.
|
||||
|
||||
if(! $vcard) {
|
||||
$vcard = new \Sabre\VObject\Component\VCard([
|
||||
@@ -689,12 +690,12 @@ function get_vcard_array($vc,$id) {
|
||||
if(is_array($entry['address'])) {
|
||||
array_walk($entry['address'],'array_escape_tags');
|
||||
}
|
||||
else {
|
||||
else {
|
||||
$entry['address'] = (string) escape_tags($entry['address']);
|
||||
}
|
||||
|
||||
$adrs[] = $entry;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -768,7 +769,7 @@ function vcard_query(&$r) {
|
||||
if($a) {
|
||||
foreach($a as $av) {
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
if($r[$x]['abook_xchan'] == $av['xchan']) {
|
||||
if($r[$x]['abook_xchan'] == $av['xchan']) {
|
||||
$vctmp = \Sabre\VObject\Reader::read($av['v']);
|
||||
$r[$x]['vcard'] = (($vctmp) ? get_vcard_array($vctmp,$r[$x]['abook_id']) : [] );
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ function categories_widget($baseurl,$selected = '') {
|
||||
dbesc(ACTIVITY_UPDATE)
|
||||
);
|
||||
}
|
||||
else
|
||||
else
|
||||
$r = unserialize($content);
|
||||
|
||||
$terms = array();
|
||||
@@ -206,6 +206,40 @@ function articlecategories_widget($baseurl,$selected = '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
function filecategories_widget($baseurl,$selected = '') {
|
||||
|
||||
$perms = permissions_sql(App::$profile['profile_uid']);
|
||||
|
||||
$terms = array();
|
||||
$r = q("select distinct(term.term)
|
||||
from term join attach on term.oid = attach.id
|
||||
where attach.uid = %d
|
||||
and term.uid = attach.uid
|
||||
and term.ttype = %d
|
||||
and term.otype = %d
|
||||
$perms
|
||||
order by term.term asc",
|
||||
intval(App::$profile['profile_uid']),
|
||||
intval(TERM_CATEGORY),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
|
||||
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 common_friends_visitor_widget($profile_uid,$cnt = 25) {
|
||||
|
||||
@@ -511,6 +511,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
|
||||
$jsreload = '';
|
||||
|
||||
$preview = (($page_mode === 'preview') ? true : false);
|
||||
$r_preview = (($page_mode === 'r_preview') ? true : false);
|
||||
$previewing = (($preview) ? ' preview ' : '');
|
||||
$preview_lbl = t('This is an unsaved preview');
|
||||
|
||||
@@ -873,11 +874,13 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
|
||||
}
|
||||
|
||||
|
||||
|
||||
$item['pagedrop'] = $page_dropping;
|
||||
|
||||
if($item['id'] == $item['parent']) {
|
||||
if($item['id'] == $item['parent'] || $r_preview) {
|
||||
|
||||
$item_object = new Zotlabs\Lib\ThreadItem($item);
|
||||
|
||||
$conv->add_thread($item_object);
|
||||
if(($page_mode === 'list') || ($page_mode === 'pager_list')) {
|
||||
$item_object->set_template('conv_list.tpl');
|
||||
|
||||
@@ -16,7 +16,6 @@ require_once('include/permissions.php');
|
||||
* @return array
|
||||
*/
|
||||
function find_upstream_directory($dirmode) {
|
||||
global $DIRECTORY_FALLBACK_SERVERS;
|
||||
|
||||
$preferred = get_config('system','directory_server');
|
||||
|
||||
@@ -28,7 +27,7 @@ function find_upstream_directory($dirmode) {
|
||||
);
|
||||
if(($r) && ($r[0]['site_flags'] & DIRECTORY_MODE_STANDALONE)) {
|
||||
$preferred = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,14 +38,16 @@ function find_upstream_directory($dirmode) {
|
||||
* from our list of directory servers. However, if we're a directory
|
||||
* server ourself, point at the local instance
|
||||
* We will then set this value so this should only ever happen once.
|
||||
* Ideally there will be an admin setting to change to a different
|
||||
* Ideally there will be an admin setting to change to a different
|
||||
* directory server if you don't like our choice or if circumstances change.
|
||||
*/
|
||||
|
||||
$directory_fallback_servers = get_directory_fallback_servers();
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
if ($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
$toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS));
|
||||
$preferred = $DIRECTORY_FALLBACK_SERVERS[$toss];
|
||||
$toss = mt_rand(0,count($directory_fallback_servers));
|
||||
$preferred = $directory_fallback_servers[$toss];
|
||||
set_config('system','directory_server',$preferred);
|
||||
} else{
|
||||
set_config('system','directory_server',z_root());
|
||||
@@ -94,7 +95,7 @@ function get_directory_setting($observer, $setting) {
|
||||
$ret = get_config('directory', $setting);
|
||||
|
||||
|
||||
// 'safemode' is the default if there is no observer or no established preference.
|
||||
// 'safemode' is the default if there is no observer or no established preference.
|
||||
|
||||
if($setting == 'safemode' && $ret === false)
|
||||
$ret = 1;
|
||||
@@ -152,8 +153,8 @@ function dir_sort_links() {
|
||||
*
|
||||
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
|
||||
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
|
||||
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||
* directly if the rater's signature matches.
|
||||
*
|
||||
* @param int $dirmode;
|
||||
@@ -189,7 +190,7 @@ function sync_directories($dirmode) {
|
||||
[
|
||||
'site_url' => DIRECTORY_FALLBACK_MASTER,
|
||||
'site_flags' => DIRECTORY_MODE_PRIMARY,
|
||||
'site_update' => NULL_DATE,
|
||||
'site_update' => NULL_DATE,
|
||||
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
|
||||
'site_realm' => DIRECTORY_REALM,
|
||||
'site_valid' => 1,
|
||||
@@ -335,11 +336,11 @@ function update_directory_entry($ud) {
|
||||
// modify the directory search to only return zot6 entries, and also modify this function
|
||||
// to *only* fetch the zot6 entries.
|
||||
// Otherwise we'll be showing duplicates or have a mostly empty directory for a good chunk of
|
||||
// the transition period. Directory server load will likely increase "moderately" during this transition.
|
||||
// The one month counter begins when the primary directory has upgraded to a release which uses this code.
|
||||
// the transition period. Directory server load will likely increase "moderately" during this transition.
|
||||
// The one month counter begins when the primary directory has upgraded to a release which uses this code.
|
||||
// Hubzilla channels running traditional zot which have not upgraded can or will be dropped from the directory or
|
||||
// "not found" at the end of the transition period as the directory will only serve zot6 entries at that time.
|
||||
|
||||
|
||||
$uri = Webfinger::zot_url($ud['ud_addr']);
|
||||
if($uri) {
|
||||
$record = Zotfinger::exec($uri);
|
||||
@@ -347,8 +348,8 @@ function update_directory_entry($ud) {
|
||||
// Check the HTTP signature
|
||||
|
||||
$hsig = $record['signature'];
|
||||
if($hsig && $hsig['signer'] === $url && $hsig['header_valid'] === true && $hsig['content_valid'] === true) {
|
||||
$x = \Zotlabs\Lib\Libzot::import_xchan($record['data'], 0, $ud);
|
||||
if($hsig && $hsig['signer'] === $uri && $hsig['header_valid'] === true && $hsig['content_valid'] === true) {
|
||||
$x = Libzot::import_xchan($record['data'], 0, $ud);
|
||||
if($x['success']) {
|
||||
$success = true;
|
||||
}
|
||||
@@ -394,7 +395,7 @@ function local_dir_update($uid, $force) {
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* @param array $params associative array which configures the feed
|
||||
* @return string with an atom feed
|
||||
*/
|
||||
|
||||
function get_public_feed($channel, $params) {
|
||||
|
||||
if(! $params)
|
||||
@@ -431,6 +432,7 @@ function get_atom_elements($feed, $item) {
|
||||
$res['plink'] = unxmlify($item->get_link(0));
|
||||
$res['item_rss'] = 1;
|
||||
|
||||
$res['uuid'] = uuid_from_url($res['plink']);
|
||||
|
||||
$summary = unxmlify($item->get_description(true));
|
||||
|
||||
@@ -1516,6 +1518,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ function load_context_help() {
|
||||
break;
|
||||
|
||||
array_pop($args);
|
||||
$path = implode($args,'/');
|
||||
$path = implode('/', $args);
|
||||
}
|
||||
|
||||
return $context_help;
|
||||
|
||||
@@ -40,7 +40,7 @@ function breaklines($line, $level, $wraplength = 75)
|
||||
$newlines[] = $line;
|
||||
|
||||
|
||||
return(implode($newlines, "\n"));
|
||||
return(implode("\n", $newlines));
|
||||
}
|
||||
|
||||
function quotelevel($message, $wraplength = 75)
|
||||
@@ -73,7 +73,7 @@ function quotelevel($message, $wraplength = 75)
|
||||
if (!$startquote or ($line != ''))
|
||||
$newlines[] = breaklines($line, $currlevel, $wraplength);
|
||||
}
|
||||
return(implode($newlines, "\n"));
|
||||
return(implode("\n", $newlines));
|
||||
}
|
||||
|
||||
function collecturls($message) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* @brief Hubloc related functions.
|
||||
*/
|
||||
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
/**
|
||||
* @brief Create an array for hubloc table and insert record.
|
||||
*
|
||||
@@ -163,7 +165,7 @@ function remove_obsolete_hublocs() {
|
||||
dbesc($rr['hubloc_hash'])
|
||||
);
|
||||
if($x) {
|
||||
Zotlabs\Daemon\Master::Summon(array('Notifier', 'location', $x[0]['channel_id']));
|
||||
Master::Summon(array('Notifier', 'refresh_all', $x[0]['channel_id']));
|
||||
if($interval)
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
|
||||
@@ -527,12 +527,12 @@ function sync_apps($channel, $apps) {
|
||||
|
||||
/**
|
||||
* @brief Import system apps.
|
||||
* System apps from the original server may not exist on this system
|
||||
* System apps from the original server may not exist on this system
|
||||
* (e.g. apps associated with addons that are not installed here).
|
||||
* Check the system apps that were provided in the import file to see if they
|
||||
* exist here and if so, install them locally. Preserve categories that
|
||||
* might have been added by this channel on the other server.
|
||||
* Do not use any paths from the original as they will point to a different server.
|
||||
* Do not use any paths from the original as they will point to a different server.
|
||||
* @param array $channel
|
||||
* @param array $apps
|
||||
*/
|
||||
@@ -1208,6 +1208,9 @@ function sync_files($channel, $files) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$term = $att['term'];
|
||||
unset($att['term']);
|
||||
|
||||
$attach_exists = false;
|
||||
$x = attach_by_hash($att['hash'],$channel['channel_hash']);
|
||||
logger('sync_files duplicate check: attach_exists=' . $attach_exists, LOGGER_DEBUG);
|
||||
@@ -1352,17 +1355,35 @@ function sync_files($channel, $files) {
|
||||
}
|
||||
$redirects = 0;
|
||||
|
||||
|
||||
$headers = [];
|
||||
$headers['Accept'] = 'application/x-zot+json' ;
|
||||
$headers['Sigtoken'] = random_string();
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], 'acct:' . channel_reddress($channel),true,'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), true, 'sha512');
|
||||
|
||||
$x = z_post_url($fetch_url,$parr,$redirects,[ 'filep' => $fp, 'headers' => $headers]);
|
||||
fclose($fp);
|
||||
|
||||
if($x['success']) {
|
||||
$attachment_stored = true;
|
||||
|
||||
$a = q("SELECT id FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($att['hash']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($a) {
|
||||
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
|
||||
intval($channel['channel_id']),
|
||||
intval($a[0]['id']),
|
||||
intval(TERM_OBJ_FILE)
|
||||
);
|
||||
if($term) {
|
||||
foreach($term as $t) {
|
||||
if(array_key_exists('type',$t))
|
||||
$t['ttype'] = $t['type'];
|
||||
store_item_tag($channel['channel_id'], $a[0]['id'], TERM_OBJ_FILE, $t['ttype'], escape_tags($t['term']), escape_tags($t['url']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1373,7 +1394,7 @@ function sync_files($channel, $files) {
|
||||
logger('attachment store failed',LOGGER_NORMAL,LOG_ERR);
|
||||
}
|
||||
if($f['photo']) {
|
||||
|
||||
|
||||
foreach($f['photo'] as $p) {
|
||||
unset($p['id']);
|
||||
$p['aid'] = $channel['channel_account_id'];
|
||||
@@ -1442,11 +1463,11 @@ function sync_files($channel, $files) {
|
||||
$headers = [];
|
||||
$headers['Accept'] = 'application/x-zot+json' ;
|
||||
$headers['Sigtoken'] = random_string();
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'],'acct:' . channel_reddress($channel),true,'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), true, 'sha512');
|
||||
|
||||
$x = z_post_url($fetch_url,$parr,$redirects,[ 'filep' => $fp, 'headers' => $headers]);
|
||||
fclose($fp);
|
||||
|
||||
|
||||
// Override remote hub thumbnails storage settings
|
||||
if(! boolval(get_config('system','filesystem_storage_thumbnails', 0))) {
|
||||
$p['os_storage'] = 0;
|
||||
@@ -1488,12 +1509,12 @@ function sync_files($channel, $files) {
|
||||
create_table_from_array('photo',$p, [ 'content' ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Set xchan photo date to prevent thumbnails fetch for clones on profile update packet recieve
|
||||
if(isset($update_xchan)) {
|
||||
|
||||
|
||||
$x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
|
||||
dbescdate($update_xchan),
|
||||
dbesc($channel['channel_hash'])
|
||||
@@ -1522,17 +1543,18 @@ function sync_addressbook($channel, $data) {
|
||||
|
||||
if(! \Zotlabs\Lib\Apps::system_app_installed($channel['channel_id'], 'CardDAV'))
|
||||
return;
|
||||
|
||||
|
||||
logger("debug: " . print_r($data,true), LOGGER_DEBUG);
|
||||
|
||||
require_once('include/cdav.php');
|
||||
|
||||
$principalUri = 'principals/' . $channel['channel_address'];
|
||||
|
||||
|
||||
if($data['action'] !== 'create') {
|
||||
$id = get_cdav_id($principalUri, $data['uri'], 'addressbooks');
|
||||
if(! $id)
|
||||
return;
|
||||
$id = $id['id'];
|
||||
}
|
||||
|
||||
$pdo = \DBA::$dba->db;
|
||||
@@ -1630,7 +1652,7 @@ function sync_calendar($channel, $data) {
|
||||
break;
|
||||
|
||||
case 'update_card':
|
||||
$caldavBackend->updateCalendarObject($id, $data['carduri'], $data['card']);
|
||||
$caldavBackend->updateCalendarObject($id, $data['carduri'], $data['card']);
|
||||
break;
|
||||
|
||||
case 'switch':
|
||||
|
||||
@@ -1551,7 +1551,7 @@ function get_mail_elements($x) {
|
||||
$arr['expires'] = datetime_convert('UTC','UTC',$x['expires']);
|
||||
|
||||
$arr['mail_flags'] = 0;
|
||||
|
||||
|
||||
if(array_key_exists('sig',$x))
|
||||
$arr['sig'] = $x['sig'];
|
||||
|
||||
@@ -2206,6 +2206,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
// override the unseen flag with the original
|
||||
|
||||
$arr['item_unseen'] = $orig[0]['item_unseen'];
|
||||
@@ -2502,7 +2503,7 @@ function item_update_parent_commented($item) {
|
||||
);
|
||||
|
||||
q("UPDATE item set commented = '%s', changed = '%s' WHERE id = %d",
|
||||
dbesc(($z) ? $z[0]['commented'] : datetime_convert()),
|
||||
dbesc(($z[0]['commented']) ? $z[0]['commented'] : datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
intval($item['parent'])
|
||||
);
|
||||
@@ -2672,6 +2673,11 @@ function tag_deliver($uid, $item_id) {
|
||||
}
|
||||
|
||||
if ($is_group && intval($item['item_private']) === 2 && intval($item['item_thread_top'])) {
|
||||
|
||||
// do not turn the groups own direkt messages into group items
|
||||
if($item['item_wall'] && $item['author_xchan'] === $u[0]['channel_hash'])
|
||||
return;
|
||||
|
||||
// group delivery via DM
|
||||
if(perm_is_allowed($uid,$item['owner_xchan'],'post_wall') || perm_is_allowed($uid,$item['owner_xchan'],'tag_deliver')) {
|
||||
logger('group DM delivery for ' . $u[0]['channel_address']);
|
||||
@@ -2682,6 +2688,12 @@ function tag_deliver($uid, $item_id) {
|
||||
|
||||
|
||||
if ($is_group && intval($item['item_thread_top']) && intval($item['item_wall']) && $item['author_xchan'] !== $item['owner_xchan']) {
|
||||
|
||||
if($item['resource_type'] === 'group_item') {
|
||||
logger('resource_type group_item: already shared');
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($item['body'],'[/share]')) {
|
||||
logger('W2W post already shared');
|
||||
return;
|
||||
@@ -2813,7 +2825,7 @@ function tag_deliver($uid, $item_id) {
|
||||
|
||||
|
||||
// standard forum tagging sequence !forumname
|
||||
|
||||
/*
|
||||
$forumpattern = '/\!\!?\[[uz]rl\=([^\]]*?)\]((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
|
||||
|
||||
$forumpattern2 = '/\[[uz]rl\=([^\]]*?)\]\!((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
|
||||
@@ -2847,6 +2859,8 @@ function tag_deliver($uid, $item_id) {
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if(! ($tagged || $plustagged)) {
|
||||
logger('Mention was in a reshare or exceeded max_tagged_forums - ignoring');
|
||||
continue;
|
||||
@@ -3022,7 +3036,7 @@ function tgroup_check($uid, $item) {
|
||||
}
|
||||
|
||||
// post to group via DM
|
||||
|
||||
|
||||
if ($is_group) {
|
||||
if (intval($item['item_private']) === 2 && $item['mid'] === $item['parent_mid']) {
|
||||
return true;
|
||||
@@ -3076,7 +3090,7 @@ function tgroup_check($uid, $item) {
|
||||
|
||||
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
|
||||
|
||||
|
||||
/*
|
||||
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
|
||||
|
||||
$forumpattern2 = '/\[zrl\=([^\]]*?)\]\!((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
|
||||
@@ -3116,6 +3130,7 @@ function tgroup_check($uid, $item) {
|
||||
logger('tgroup_check: mention was in a reshare or exceeded max_tagged_forums - ignoring');
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3179,8 +3194,18 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
if($rewrite_author) {
|
||||
$item['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
$r = q("update item set author_xchan = '%s' where id = %d",
|
||||
//if it's a toplevel rss item we will also rewrite the mid to something fetchable
|
||||
if($item['item_rss'] && $item['item_thread_top']) {
|
||||
$item['mid'] = z_root() . '/item/' . $item['uuid'];
|
||||
$item['parent_mid'] = $item['mid'];
|
||||
$item['thr_parent'] = $item['mid'];
|
||||
}
|
||||
|
||||
$r = q("UPDATE item SET author_xchan = '%s', mid = '%s', parent_mid = '%s', thr_parent = '%s' WHERE id = %d",
|
||||
dbesc($item['author_xchan']),
|
||||
dbesc($item['mid']),
|
||||
dbesc($item['parent_mid']),
|
||||
dbesc($item['thr_parent']),
|
||||
intval($item_id)
|
||||
);
|
||||
}
|
||||
@@ -3189,18 +3214,20 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
if ($group && (! $parent)) {
|
||||
|
||||
$arr = [];
|
||||
|
||||
|
||||
if ($edit) {
|
||||
|
||||
// process edit or delete action
|
||||
$r = q("select * from item where source_xchan = '%s' and body like '%s' and uid = %d limit 1",
|
||||
dbesc($item['owner_xchan']),
|
||||
dbesc("%message_id='" . $item['mid'] . "'%"),
|
||||
intval($channel['channel_id'])
|
||||
$r = q("select * from item where uid = %d and resource_id = '%s' and source_xchan = '%s' and resource_type = 'group_item' limit 1",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($item['mid']),
|
||||
dbesc($item['author_xchan'])
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
if (intval($item['item_deleted'])) {
|
||||
drop_item($r[0]['id'],false,DROPITEM_PHASE1);
|
||||
Master::Summon([ 'Notifier','drop',$r[0]['id'] ]);
|
||||
drop_item($r[0]['id'], false, DROPITEM_PHASE1);
|
||||
Master::Summon([ 'Notifier', 'drop', $r[0]['id'] ]);
|
||||
return;
|
||||
}
|
||||
$arr['id'] = intval($r[0]['id']);
|
||||
@@ -3221,30 +3248,32 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
$arr['mid'] = z_root() . '/activity/' . $arr['uuid'];
|
||||
$arr['parent_mid'] = $arr['mid'];
|
||||
}
|
||||
|
||||
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
|
||||
// WARNING: the presence of both source_xchan and non-zero item_uplink here will cause a delivery loop
|
||||
|
||||
|
||||
$arr['item_uplink'] = 0;
|
||||
$arr['source_xchan'] = $item['owner_xchan'];
|
||||
|
||||
$arr['resource_id'] = $item['mid'];
|
||||
$arr['resource_type'] = 'group_item';
|
||||
|
||||
$arr['item_private'] = (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
||||
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0);
|
||||
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = 1;
|
||||
|
||||
$arr['item_thread_top'] = 1;
|
||||
|
||||
|
||||
if (strpos($item['body'], "[/share]") !== false) {
|
||||
$pos = strpos($item['body'], "[share");
|
||||
$bb = substr($item['body'], $pos);
|
||||
} else {
|
||||
$bb = "[share author='" . urlencode($item['author']['xchan_name']).
|
||||
"' profile='" . $item['author']['xchan_url'] .
|
||||
"' portable_id='" . $item['author']['xchan_hash'] .
|
||||
"' portable_id='" . $item['author']['xchan_hash'] .
|
||||
"' avatar='" . $item['author']['xchan_photo_s'] .
|
||||
"' link='" . $item['plink'] .
|
||||
"' auth='" . ((in_array($item['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') .
|
||||
@@ -3252,12 +3281,13 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
"' message_id='" . $item['mid'] .
|
||||
"']";
|
||||
if($item['title'])
|
||||
$bb .= '[b]'.$item['title'].'[/b]'."\r\n";
|
||||
$bb .= '[h3][b]'.$item['title'].'[/b][/h3]'."\r\n";
|
||||
$bb .= $item['body'];
|
||||
$bb .= "[/share]";
|
||||
}
|
||||
|
||||
$arr['body'] = $bb;
|
||||
$arr['term'] = $item['term'];
|
||||
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
@@ -3299,7 +3329,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
$private = 1;
|
||||
|
||||
$item_wall = 1;
|
||||
$item_origin = 1;
|
||||
$item_origin = (($item['item_deleted']) ? 0 : 1); // item_origin for deleted items is set to 0 in delete_imported_item() to prevent looping. In this case we probably should not set it back to 1 here.
|
||||
$item_uplink = 0;
|
||||
$item_nocomment = 0;
|
||||
|
||||
@@ -3315,7 +3345,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
);
|
||||
}
|
||||
else {
|
||||
$item_uplink = 1;
|
||||
$item_uplink = (($item['item_rss']) ? 0 : 1); // Do not set item_uplink for rss items - we can not send anything to them.
|
||||
|
||||
// if this is an edit, item_store_update() will have already updated the item
|
||||
// with the correct value for source_xchan (by ignoring it). We cannot set to owner_xchan
|
||||
@@ -4063,11 +4093,6 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL) {
|
||||
if($stage == DROPITEM_PHASE1)
|
||||
return true;
|
||||
|
||||
$r = q("delete from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_POST),
|
||||
intval($item['id'])
|
||||
);
|
||||
|
||||
q("delete from iconfig where iid = %d",
|
||||
intval($item['id'])
|
||||
);
|
||||
@@ -4796,7 +4821,7 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow,
|
||||
elseif(strpos($access_tag,'gid:') === 0) {
|
||||
$str_group_allow .= '<' . substr($access_tag,4) . '>';
|
||||
$access_tag = '';
|
||||
$private = 2;
|
||||
$private = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,10 +47,10 @@ function js_strings() {
|
||||
'days' => tt('%d days', '%d days', '%d'),
|
||||
'months' => tt('%d months', '%d months', '%d'),
|
||||
'years' => tt('%d years', '%d years', '%d'),
|
||||
|
||||
|
||||
// get plural function code
|
||||
'plural_func' => tf(),
|
||||
|
||||
|
||||
'$t01' => ((t('timeago.prefixAgo') == 'timeago.prefixAgo') ? '' : ((t('timeago.prefixAgo') == 'NONE') ? '' : t('timeago.prefixAgo'))),
|
||||
'$t02' => ((t('timeago.prefixFromNow') == 'timeago.prefixFromNow') ? '' : ((t('timeago.prefixFromNow') == 'NONE') ? '' : t('timeago.prefixFromNow'))),
|
||||
'$t03' => ((t('timeago.suffixAgo') == 'timeago.suffixAgo') ? 'ago' : ((t('timeago.suffixAgo') == 'NONE') ? '' : t('timeago.suffixAgo'))),
|
||||
@@ -113,6 +113,9 @@ function js_strings() {
|
||||
'$month' => t('month','calendar'),
|
||||
'$week' => t('week','calendar'),
|
||||
'$day' => t('day','calendar'),
|
||||
'$allday' => t('All day','calendar')
|
||||
'$allday' => t('All day','calendar'),
|
||||
|
||||
// mod cloud
|
||||
'$download_info' => t('Please stand by while your download is being prepared.')
|
||||
));
|
||||
}
|
||||
|
||||
@@ -714,7 +714,7 @@ function sxml2array ( $xmlObject, $out = array () )
|
||||
* @brief xml2array() will convert the given XML text to an array in the XML structure.
|
||||
*
|
||||
* Link: http://www.bin-co.com/php/scripts/xml2array/
|
||||
* Portions significantly re-written by mike@macgirvin.com
|
||||
* Portions significantly re-written by mike@macgirvin.com
|
||||
* (namespaces, lowercase tags, get_attribute default changed, more...)
|
||||
*
|
||||
* Examples: $array = xml2array(file_get_contents('feed.xml'));
|
||||
@@ -1113,8 +1113,8 @@ function discover_by_webbie($webbie, $protocol = '') {
|
||||
// Check the HTTP signature
|
||||
|
||||
$hsig = $record['signature'];
|
||||
if($hsig && ($hsig['signer'] === $url || $hsig['signer'] === $link['href']) && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
|
||||
$hsig_valid = true;
|
||||
if($hsig && $hsig['signer'] === $link['href'] && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
|
||||
$hsig_valid = true;
|
||||
|
||||
if(! $hsig_valid) {
|
||||
logger('http signature not valid: ' . print_r($hsig,true));
|
||||
@@ -1431,7 +1431,7 @@ function scrape_feed($url) {
|
||||
function do_delivery($deliveries, $force = false) {
|
||||
|
||||
// $force is set if a site that wasn't responding suddenly returns to life.
|
||||
// Try and shove through everything going to that site while it's responding.
|
||||
// Try and shove through everything going to that site while it's responding.
|
||||
|
||||
if(! (is_array($deliveries) && count($deliveries)))
|
||||
return;
|
||||
@@ -2069,7 +2069,7 @@ function get_request_string($url) {
|
||||
* Takes the output of parse_url and builds a URL from it
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function unparse_url($parsed_url) {
|
||||
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
|
||||
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
|
||||
@@ -2081,4 +2081,4 @@ function unparse_url($parsed_url) {
|
||||
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
|
||||
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
|
||||
return "$scheme$user$pass$host$port$path$query$fragment";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ function photo_factory($data, $type = null) {
|
||||
$v = Imagick::getVersion();
|
||||
preg_match('/ImageMagick ([0-9]+\.[0-9]+\.[0-9]+)/', $v['versionString'], $m);
|
||||
if(version_compare($m[1], '6.6.7') >= 0) {
|
||||
$limits = get_config('system', 'imagick_limits', false);
|
||||
if ($limits)
|
||||
foreach ($limits as $k => $v)
|
||||
IMagick::setResourceLimit($k, $v);
|
||||
$ph = new PhotoImagick($data, $type);
|
||||
} else {
|
||||
// earlier imagick versions have issues with scaling png's
|
||||
|
||||
@@ -271,6 +271,7 @@ function suggestion_query($uid, $myxchan, $start = 0, $limit = 80) {
|
||||
and xchan_hidden = 0
|
||||
and xchan_deleted = 0
|
||||
and xlink_static = 0
|
||||
and xchan_network = 'zot6'
|
||||
group by xchan_hash order by total desc limit %d offset %d ",
|
||||
intval($uid),
|
||||
intval($uid),
|
||||
@@ -290,6 +291,7 @@ function suggestion_query($uid, $myxchan, $start = 0, $limit = 80) {
|
||||
and xchan_hidden = 0
|
||||
and xchan_deleted = 0
|
||||
and xlink_static = 0
|
||||
and xchan_network = 'zot6'
|
||||
group by xchan_hash order by total desc limit %d offset %d ",
|
||||
intval($uid),
|
||||
intval($uid),
|
||||
|
||||
@@ -1667,7 +1667,7 @@ function format_filer(&$item) {
|
||||
if(! trim($term))
|
||||
continue;
|
||||
$removelink = z_root() . '/filerm/' . $item['id'] . '?f=&term=' . urlencode($t['term']);
|
||||
$categories[] = array('term' => $term, 'removelink' => $removelink);
|
||||
$categories[] = array('term' => $term, 'removelink' => $removelink, 'id' => $item['id']);
|
||||
}
|
||||
|
||||
$s = replace_macros(get_markup_template('item_filer.tpl'),array(
|
||||
@@ -1801,7 +1801,7 @@ function prepare_body(&$item,$attach = false,$opts = false) {
|
||||
|
||||
$tags = format_hashtags($item);
|
||||
|
||||
if($item['resource_type'])
|
||||
if($item['resource_type'] == 'photo')
|
||||
$mentions = format_mentions($item);
|
||||
|
||||
$categories = format_categories($item,$writeable);
|
||||
@@ -2795,7 +2795,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
|
||||
|
||||
$termtype = ((strpos($tag,'#') === 0) ? TERM_HASHTAG : TERM_UNKNOWN);
|
||||
$termtype = ((strpos($tag,'@') === 0) ? TERM_MENTION : $termtype);
|
||||
$termtype = ((strpos($tag,'!') === 0) ? TERM_FORUM : $termtype);
|
||||
// $termtype = ((strpos($tag,'!') === 0) ? TERM_FORUM : $termtype);
|
||||
$termtype = ((strpos($tag,'#^[') === 0) ? TERM_BOOKMARK : $termtype);
|
||||
|
||||
// Is it a hashtag of some kind?
|
||||
@@ -2864,7 +2864,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
|
||||
|
||||
if ( in_array($termtype, [ TERM_MENTION, TERM_FORUM ] )) {
|
||||
|
||||
// The @! tag and !! tag will alter permissions
|
||||
// The @! tag will alter permissions
|
||||
|
||||
// $in_network is set to false to avoid false positives on posts originating
|
||||
// on a network which does not implement privacy tags or implements them differently.
|
||||
@@ -2966,12 +2966,13 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
|
||||
//create profile link
|
||||
$profile = str_replace(',','%2c',$profile);
|
||||
$url = $profile;
|
||||
/*
|
||||
if($termtype === TERM_FORUM) {
|
||||
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
else {
|
||||
// ( $termtype === TERM_MENTION )
|
||||
*/
|
||||
if ($termtype === TERM_MENTION) {
|
||||
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
@@ -2983,7 +2984,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
|
||||
$str_tags .= $newtag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$fn_results[] = [
|
||||
'replaced' => $replaced,
|
||||
@@ -3032,12 +3033,13 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
|
||||
//create profile link
|
||||
$profile = str_replace(',','%2c',$profile);
|
||||
$url = $profile;
|
||||
/*
|
||||
if($termtype === TERM_FORUM) {
|
||||
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
else {
|
||||
// ( $termtype === TERM_MENTION )
|
||||
*/
|
||||
if ($termtype === TERM_MENTION) {
|
||||
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
@@ -3060,7 +3062,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $fn_results;
|
||||
|
||||
}
|
||||
@@ -3098,7 +3100,7 @@ function linkify_tags(&$body, $uid, $in_network = true) {
|
||||
function getIconFromType($type) {
|
||||
$iconMap = array(
|
||||
//Folder
|
||||
t('Collection') => 'fa-folder-o',
|
||||
'Collection' => 'fa-folder-o',
|
||||
'multipart/mixed' => 'fa-folder-o', //dirs in attach use this mime type
|
||||
//Common file
|
||||
'application/octet-stream' => 'fa-file-o',
|
||||
@@ -3242,7 +3244,7 @@ function item_url_replace($channel,&$item,$old,$new,$oldnick = '') {
|
||||
if($oldnick)
|
||||
json_url_replace('/' . $oldnick . '/' ,'/' . $channel['channel_address'] . '/' ,$item['target']);
|
||||
}
|
||||
|
||||
|
||||
$item['body'] = preg_replace("/(\[zrl=".preg_quote($old,'/')."\/(photo|photos|gallery)\/".$channel['channel_address'].".+\]\[zmg=\d+x\d+\])".preg_quote($old,'/')."\/(.+\[\/zmg\])/", '${1}'.$new.'/${3}', $item['body']);
|
||||
$item['body'] = preg_replace("/".preg_quote($old,'/')."\/(search|\w+\/".$channel['channel_address'].")/", $new.'/${1}', $item['body']);
|
||||
|
||||
@@ -3575,7 +3577,7 @@ function cleanup_bbcode($body) {
|
||||
$body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body);
|
||||
$body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body);
|
||||
$body = preg_replace_callback('/\[\$b64svg(.*?)\[\/(svg)\]/ism','\red_unescape_codeblock',$body);
|
||||
|
||||
|
||||
// fix any img tags that should be zmg
|
||||
|
||||
$body = preg_replace_callback('/\[img(.*?)\](.*?)\[\/img\]/ism','\red_zrlify_img_callback',$body);
|
||||
@@ -3690,6 +3692,11 @@ function get_forum_channels($uid) {
|
||||
);
|
||||
|
||||
if($x1) {
|
||||
|
||||
$x2 = [];
|
||||
$x3 = [];
|
||||
$x4 = [];
|
||||
|
||||
$xc = ids_to_querystr($x1,'xchan',true);
|
||||
|
||||
$x2 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'tag_deliver' and v = '1' and xchan in (" . $xc . ") ",
|
||||
@@ -3706,6 +3713,15 @@ function get_forum_channels($uid) {
|
||||
if($x3) {
|
||||
$xf = ids_to_querystr(array_merge($x2,$x3),'xchan',true);
|
||||
}
|
||||
|
||||
// public forums with no permission to post
|
||||
$x4 = q("select xchan from abconfig left join xchan on xchan = xchan_hash where chan = %d and cat = 'their_perms' and k in ('post_wall', 'tag_deliver') and v = '0' and xchan in (" . $xc . ") and xchan_pubforum = 1 $sql_extra ",
|
||||
intval(local_channel())
|
||||
);
|
||||
if($x4) {
|
||||
$xf = ids_to_querystr(array_merge($x2,$x3,$x4),'xchan',true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$sql_extra_1 = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
|
||||
@@ -3722,6 +3738,15 @@ function get_forum_channels($uid) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($x4) {
|
||||
foreach($x4 as $xx) {
|
||||
if($r[$x]['xchan_hash'] == $xx['xchan']) {
|
||||
$r[$x]['no_post_perms'] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
App::$data['forum_channels'] = $r;
|
||||
@@ -3791,7 +3816,7 @@ function array_path_exists($str,$arr) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate a unique ID.
|
||||
* @brief Generate a random v4 UUID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -3807,6 +3832,22 @@ function new_uuid() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate a name-based v5 UUID in the URL namespace
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
function uuid_from_url($url) {
|
||||
|
||||
try {
|
||||
$hash = Uuid::uuid5(Uuid::NAMESPACE_URL, $url)->toString();
|
||||
} catch (UnsatisfiedDependencyException $e) {
|
||||
$hash = md5($url);
|
||||
}
|
||||
return $hash;
|
||||
}
|
||||
|
||||
function svg2bb($s) {
|
||||
|
||||
$s = preg_replace("/\<text (.*?)\>(.*?)\<(.*?)\<\/text\>/", '<text $1>$2<$3</text>', $s);
|
||||
|
||||
@@ -286,9 +286,7 @@ function owt_init($token) {
|
||||
}
|
||||
|
||||
$r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
|
||||
where hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s' order by hubloc_id desc",
|
||||
dbesc($ob_hash),
|
||||
dbesc($ob_hash),
|
||||
where hubloc_id_url = '%s' order by hubloc_id desc",
|
||||
dbesc($ob_hash)
|
||||
);
|
||||
|
||||
@@ -297,9 +295,7 @@ function owt_init($token) {
|
||||
$wf = discover_by_webbie($ob_hash);
|
||||
if($wf) {
|
||||
$r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
|
||||
where hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s' order by hubloc_id desc",
|
||||
dbesc($ob_hash),
|
||||
dbesc($ob_hash),
|
||||
where hubloc_id_url = '%s' order by hubloc_id desc",
|
||||
dbesc($ob_hash)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ class ASNValue
|
||||
function SetIntBuffer($Value)
|
||||
{
|
||||
if (strlen($Value) > 1) {
|
||||
$firstByte = ord($Value{0});
|
||||
$firstByte = ord($Value[0]);
|
||||
if ($firstByte & 0x80) { //first bit set
|
||||
$Value = chr(0x00) . $Value;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class ASNValue
|
||||
function GetIntBuffer()
|
||||
{
|
||||
$result = $this->Value;
|
||||
if (ord($result{0}) == 0x00) {
|
||||
if (ord($result[0]) == 0x00) {
|
||||
$result = substr($result, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.5/phpunit.xsd"
|
||||
bootstrap="../boot.php"
|
||||
forceCoversAnnotation="false"
|
||||
beStrictAboutCoversAnnotation="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
beStrictAboutTodoAnnotatedTests="true"
|
||||
verbose="true">
|
||||
<testsuites>
|
||||
<testsuite name="Hubzilla default Test Suite">
|
||||
<directory suffix="Test.php">./unit/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="API Test Suite">
|
||||
<directory suffix="Test.php" prefix="API">./unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>mysql</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<!--coverage reporting-->
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">../Zotlabs/</directory>
|
||||
<directory suffix=".php">../include/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="junit" target="./results/junit.xml"/>
|
||||
<!--<log type="coverage-clover" target="./results/coverage-clover.xml"/>-->
|
||||
<log type="coverage-html" target="./results/coverage-report/" lowUpperBound="35"
|
||||
highLowerBound="70"/>
|
||||
<!--<log type="testdox-text" target="./results/testdox.txt"/>-->
|
||||
<log type="testdox-html" target="./results/testdox.html"/>
|
||||
</logging>
|
||||
<php>
|
||||
<!-- Default test database config, only used if no environment variables
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="../boot.php" forceCoversAnnotation="false" beStrictAboutCoversAnnotation="true" beStrictAboutOutputDuringTests="true" beStrictAboutTodoAnnotatedTests="true" verbose="true">
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">../Zotlabs/</directory>
|
||||
<directory suffix=".php">../include/</directory>
|
||||
</include>
|
||||
<report>
|
||||
<html outputDirectory="./results/coverage-report/" lowUpperBound="35" highLowerBound="70"/>
|
||||
</report>
|
||||
</coverage>
|
||||
<testsuites>
|
||||
<testsuite name="Hubzilla default Test Suite">
|
||||
<directory suffix="Test.php">./unit/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="API Test Suite">
|
||||
<directory suffix="Test.php" prefix="API">./unit/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>mysql</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<!--coverage reporting-->
|
||||
<logging>
|
||||
<junit outputFile="./results/junit.xml"/>
|
||||
<!--<log type="coverage-clover" target="./results/coverage-clover.xml"/>-->
|
||||
<!--<log type="testdox-text" target="./results/testdox.txt"/>-->
|
||||
<testdoxHtml outputFile="./results/testdox.html"/>
|
||||
</logging>
|
||||
<php>
|
||||
<!-- Default test database config, only used if no environment variables
|
||||
with same names are set.
|
||||
!!! Never run against a real database, it will truncate all tables -->
|
||||
<env name="hz_db_server" value="postgres"/>
|
||||
<env name="hz_db_scheme" value="pgsql"/>
|
||||
<env name="hz_db_port" value="5432"/>
|
||||
<env name="hz_db_user" value="ci-user"/>
|
||||
<env name="hz_db_pass" value="ci-pass"/>
|
||||
<env name="hz_db_database" value="ci-db"/>
|
||||
</php>
|
||||
<env name="hz_db_server" value="postgres"/>
|
||||
<env name="hz_db_scheme" value="pgsql"/>
|
||||
<env name="hz_db_port" value="5432"/>
|
||||
<env name="hz_db_user" value="ci-user"/>
|
||||
<env name="hz_db_pass" value="ci-pass"/>
|
||||
<env name="hz_db_database" value="ci-db"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
@@ -1,42 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit bootstrap="../boot.php" colors="true">
|
||||
<php>
|
||||
<var name="db_dsn" value="mysql:dbname=gitlab_ci_hubzilla;host=mysql"/>
|
||||
<var name="db_username" value="root"/>
|
||||
<var name="db_password" value="mysql"/>
|
||||
|
||||
<env name="hz_db_server" value="mysql"/>
|
||||
<env name="hz_db_scheme" value="mysql"/>
|
||||
<env name="hz_db_port" value=""/>
|
||||
<env name="hz_db_user" value="root"/>
|
||||
<env name="hz_db_pass" value="mysql"/>
|
||||
<env name="hz_db_database" value="hello_world_test"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Hubzilla default Test Suite">
|
||||
<directory suffix="Test.php">./unit/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="API Test Suite">
|
||||
<directory suffix="Test.php" prefix="API">./unit/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Ex-/Import Test Suite">
|
||||
<!--<directory suffix="Test.php">./unit/eximport/</directory>-->
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>postgresql</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<!--cover reporting-->
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">../Zotlabs/</directory>
|
||||
<directory suffix=".php">../include/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="../boot.php" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
|
||||
<coverage processUncoveredFiles="false" includeUncoveredFiles="false">
|
||||
<include>
|
||||
<directory suffix=".php">../Zotlabs/</directory>
|
||||
<directory suffix=".php">../include/</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
<php>
|
||||
<var name="db_dsn" value="mysql:dbname=gitlab_ci_hubzilla;host=mysql"/>
|
||||
<var name="db_username" value="root"/>
|
||||
<var name="db_password" value="mysql"/>
|
||||
<env name="hz_db_server" value="mysql"/>
|
||||
<env name="hz_db_scheme" value="mysql"/>
|
||||
<env name="hz_db_port" value=""/>
|
||||
<env name="hz_db_user" value="root"/>
|
||||
<env name="hz_db_pass" value="mysql"/>
|
||||
<env name="hz_db_database" value="hello_world_test"/>
|
||||
</php>
|
||||
<testsuites>
|
||||
<testsuite name="Hubzilla default Test Suite">
|
||||
<directory suffix="Test.php">./unit/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="API Test Suite">
|
||||
<directory suffix="Test.php" prefix="API">./unit/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Ex-/Import Test Suite">
|
||||
<!--<directory suffix="Test.php">./Unit/eximport/</directory>-->
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>postgresql</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<!--cover reporting-->
|
||||
</phpunit>
|
||||
|
||||
|
||||
@@ -63,11 +63,12 @@ class AccessListTest extends UnitTestCase {
|
||||
/**
|
||||
* @expectedException PHPUnit\Framework\Error\Error
|
||||
*/
|
||||
/*
|
||||
public function testPHPErrorOnInvalidConstructor() {
|
||||
$accessList = new AccessList('invalid');
|
||||
// Causes: "Illegal string offset 'channel_allow_cid'"
|
||||
}
|
||||
|
||||
*/
|
||||
public function testDefaultGetExplicit() {
|
||||
$accessList = new AccessList([]);
|
||||
|
||||
@@ -112,12 +113,14 @@ class AccessListTest extends UnitTestCase {
|
||||
/**
|
||||
* @expectedException PHPUnit\Framework\Error\Error
|
||||
*/
|
||||
/*
|
||||
public function testPHPErrorOnInvalidSet() {
|
||||
$accessList = new AccessList([]);
|
||||
|
||||
$accessList->set('invalid');
|
||||
// Causes: "Illegal string offset 'allow_cid'"
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* set_from_array() calls some other functions, too which are not yet unit tested.
|
||||
@@ -188,4 +191,4 @@ class AccessListTest extends UnitTestCase {
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Zotlabs\Tests\Unit\Access;
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
use Zotlabs\Access\PermissionRoles;
|
||||
use phpmock\phpunit\PHPMock;
|
||||
use DMS\PHPUnitExtensions\ArraySubset\Assert;
|
||||
|
||||
/**
|
||||
* @brief Unit Test case for PermissionRoles class.
|
||||
@@ -68,7 +69,7 @@ class PermissionRolesTest extends UnitTestCase {
|
||||
'social_private' => 'Social - Private'
|
||||
];
|
||||
|
||||
$this->assertArraySubset(['Social Networking' => $socialNetworking], $roles);
|
||||
Assert::assertArraySubset(['Social Networking' => $socialNetworking], $roles);
|
||||
$this->assertEquals($socialNetworking, $roles['Social Networking']);
|
||||
|
||||
$this->assertCount(5, $roles, 'There should be 5 permission groups.');
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
/* Copyright (c) 2017 Hubzilla
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit;
|
||||
|
||||
use PHPUnit\DbUnit\TestCaseTrait;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @brief Base class for our Database Unit Tests.
|
||||
*
|
||||
* @warning Never run these tests against a production database, because all
|
||||
* tables will get truncated and there is no way to recover without a backup.
|
||||
*
|
||||
* @author Klaus Weidenbach
|
||||
*/
|
||||
abstract class DatabaseTestCase extends TestCase {
|
||||
|
||||
use TestCaseTrait;
|
||||
|
||||
/**
|
||||
* Only instantiate PDO once for test clean-up/fixture load.
|
||||
*
|
||||
* @var \PDO
|
||||
*/
|
||||
static private $pdo = null;
|
||||
|
||||
/**
|
||||
* Only instantiate \PHPUnit\DbUnit\Database\Connection once per test.
|
||||
*
|
||||
* @var \PHPUnit\DbUnit\Database\Connection
|
||||
*/
|
||||
private $conn = null;
|
||||
|
||||
|
||||
final public function getConnection() {
|
||||
if ($this->conn === null) {
|
||||
if (self::$pdo === null) {
|
||||
$dsn = \getenv('hz_db_scheme') . ':host=' . \getenv('hz_db_server')
|
||||
. ';port=' . \getenv('hz_db_port') . ';dbname=' . \getenv('hz_db_database');
|
||||
|
||||
self::$pdo = new \PDO($dsn, \getenv('hz_db_user'), \getenv('hz_db_pass'));
|
||||
}
|
||||
$this->conn = $this->createDefaultDBConnection(self::$pdo, \getenv('hz_db_database'));
|
||||
}
|
||||
|
||||
return $this->conn;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ use Zotlabs\Web\HTTPSig;
|
||||
*
|
||||
* @covers Zotlabs\Web\HTTPSig
|
||||
*/
|
||||
class PermissionDescriptionTest extends UnitTestCase {
|
||||
class HttpSigTest extends UnitTestCase {
|
||||
|
||||
use PHPMock;
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2017 Hubzilla
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit\includes;
|
||||
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
|
||||
// required because of process isolation and no autoloading
|
||||
require_once 'include/dba/dba_driver.php';
|
||||
|
||||
/**
|
||||
* @brief Unit Test case for include/dba/DBA.php file.
|
||||
*
|
||||
* This test needs process isolation because of static \DBA.
|
||||
* @runTestsInSeparateProcesses
|
||||
*/
|
||||
class DBATest extends UnitTestCase {
|
||||
|
||||
public function testDbaFactoryMysql() {
|
||||
$this->assertNull(\DBA::$dba);
|
||||
|
||||
$ret = \DBA::dba_factory('server', 'port', 'user', 'pass', 'db', '0');
|
||||
$this->assertInstanceOf('dba_pdo', $ret);
|
||||
$this->assertFalse($ret->connected);
|
||||
|
||||
$this->assertSame('mysql', \DBA::$scheme);
|
||||
$this->assertSame('schema_mysql.sql', \DBA::$install_script);
|
||||
$this->assertSame('0001-01-01 00:00:00', \DBA::$null_date);
|
||||
$this->assertSame('UTC_TIMESTAMP()', \DBA::$utc_now);
|
||||
$this->assertSame('`', \DBA::$tquot);
|
||||
}
|
||||
|
||||
public function testDbaFactoryPostgresql() {
|
||||
$this->assertNull(\DBA::$dba);
|
||||
|
||||
$ret = \DBA::dba_factory('server', 'port', 'user', 'pass', 'db', '1');
|
||||
$this->assertInstanceOf('dba_pdo', $ret);
|
||||
$this->assertFalse($ret->connected);
|
||||
|
||||
$this->assertSame('pgsql', \DBA::$scheme);
|
||||
$this->assertSame('schema_postgres.sql', \DBA::$install_script);
|
||||
$this->assertSame('0001-01-01 00:00:00', \DBA::$null_date);
|
||||
$this->assertSame("now() at time zone 'UTC'", \DBA::$utc_now);
|
||||
$this->assertSame('"', \DBA::$tquot);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2017 Hubzilla
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit\includes;
|
||||
|
||||
use Zotlabs\Tests\Unit\DatabaseTestCase;
|
||||
use PHPUnit\DbUnit\TestCaseTrait;
|
||||
use PHPUnit\DbUnit\DataSet\YamlDataSet;
|
||||
|
||||
require_once 'include/dba/dba_pdo.php';
|
||||
|
||||
/**
|
||||
* @brief Unit Test case for include/dba/dba_pdo.php file.
|
||||
*
|
||||
* Some very basic tests to see if our database layer can connect to a real
|
||||
* database.
|
||||
*/
|
||||
class dba_pdoTest extends DatabaseTestCase {
|
||||
|
||||
use TestCaseTrait;
|
||||
|
||||
/**
|
||||
* @var \dba_driver
|
||||
*/
|
||||
protected $dba;
|
||||
|
||||
|
||||
/**
|
||||
* Set initial state of the database before each test is executed.
|
||||
* Load database fixtures.
|
||||
*
|
||||
* @return \PHPUnit\DbUnit\DataSet\IDataSet
|
||||
*/
|
||||
public function getDataSet() {
|
||||
return new YamlDataSet(dirname(__FILE__) . '/_files/account.yml');
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
// Will invoke getDataSet() to load fixtures into DB
|
||||
parent::setUp();
|
||||
|
||||
$this->dba = new \dba_pdo(
|
||||
\getenv('hz_db_server'),
|
||||
\getenv('hz_db_scheme'),
|
||||
\getenv('hz_db_port'),
|
||||
\getenv('hz_db_user'),
|
||||
\getenv('hz_db_pass'),
|
||||
\getenv('hz_db_database')
|
||||
);
|
||||
}
|
||||
protected function assertPreConditions() {
|
||||
$this->assertSame('pdo', $this->dba->getdriver(), "Driver is expected to be 'pdo'.");
|
||||
$this->assertInstanceOf('dba_driver', $this->dba);
|
||||
$this->assertTrue($this->dba->connected, 'Pre condition failed, DB is not connected.');
|
||||
$this->assertInstanceOf('PDO', $this->dba->db);
|
||||
}
|
||||
protected function tearDown(): void {
|
||||
$this->dba = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @group mysql
|
||||
*/
|
||||
public function testQuoteintervalOnMysql() {
|
||||
$this->assertSame('value', $this->dba->quote_interval('value'));
|
||||
}
|
||||
/**
|
||||
* @group postgresql
|
||||
*/
|
||||
public function testQuoteintervalOnPostgresql() {
|
||||
$this->assertSame("'value'", $this->dba->quote_interval('value'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group mysql
|
||||
*/
|
||||
public function testGenerateMysqlConcatSql() {
|
||||
$this->assertSame('GROUP_CONCAT(DISTINCT field SEPARATOR \';\')', $this->dba->concat('field', ';'));
|
||||
$this->assertSame('GROUP_CONCAT(DISTINCT field2 SEPARATOR \' \')', $this->dba->concat('field2', ' '));
|
||||
}
|
||||
/**
|
||||
* @group postgresql
|
||||
*/
|
||||
public function testGeneratePostgresqlConcatSql() {
|
||||
$this->assertSame('string_agg(field,\';\')', $this->dba->concat('field', ';'));
|
||||
$this->assertSame('string_agg(field2,\' \')', $this->dba->concat('field2', ' '));
|
||||
}
|
||||
|
||||
|
||||
public function testConnectToSqlServer() {
|
||||
// connect() is done in dba_pdo constructor which is called in setUp()
|
||||
$this->assertTrue($this->dba->connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testConnectToSqlServer
|
||||
*/
|
||||
public function testCloseSqlServerConnection() {
|
||||
$this->dba->close();
|
||||
|
||||
$this->assertNull($this->dba->db);
|
||||
$this->assertFalse($this->dba->connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testConnectToSqlServer
|
||||
*/
|
||||
public function testSelectQueryShouldReturnArray() {
|
||||
$ret = $this->dba->q('SELECT * FROM account');
|
||||
|
||||
$this->assertTrue(is_array($ret));
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testConnectToSqlServer
|
||||
*/
|
||||
public function testInsertQueryShouldReturnPdostatement() {
|
||||
// Fixture account.yml adds two entries to account table
|
||||
$this->assertEquals(2, $this->getConnection()->getRowCount('account'), 'Pre-Condition');
|
||||
|
||||
$ret = $this->dba->q('INSERT INTO account
|
||||
(account_id, account_email, account_language)
|
||||
VALUES (100, \'insert@example.com\', \'de\')
|
||||
');
|
||||
$this->assertInstanceOf('PDOStatement', $ret);
|
||||
|
||||
$this->assertEquals(3, $this->getConnection()->getRowCount('account'), 'Inserting failed');
|
||||
}
|
||||
|
||||
|
||||
public function testConnectToWrongSqlServer() {
|
||||
$nodba = new \dba_pdo('wrongserver',
|
||||
\getenv('hz_db_scheme'), \getenv('hz_db_port'),
|
||||
\getenv('hz_db_user'), \getenv('hz_db_pass'),
|
||||
\getenv('hz_db_database')
|
||||
);
|
||||
|
||||
$this->assertSame('pdo', $nodba->getdriver());
|
||||
$this->assertInstanceOf('dba_pdo', $nodba);
|
||||
$this->assertFalse($nodba->connected);
|
||||
$this->assertNull($nodba->db);
|
||||
|
||||
$this->assertFalse($nodba->q('SELECT * FROM account'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testConnectToSqlServer
|
||||
*/
|
||||
public function testSelectQueryToNonExistentTableShouldReturnFalse() {
|
||||
$ret = $this->dba->q('SELECT * FROM non_existent_table');
|
||||
|
||||
$this->assertFalse($ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testConnectToSqlServer
|
||||
*/
|
||||
public function testInsertQueryToNonExistentTableShouldReturnEmptyArray() {
|
||||
$ret = $this->dba->q('INSERT INTO non_existent_table
|
||||
(account_email, account_language)
|
||||
VALUES (\'email@example.com\', \'en\')
|
||||
');
|
||||
|
||||
$this->assertNotInstanceOf('PDOStatement', $ret);
|
||||
$this->isEmpty($ret);
|
||||
}
|
||||
|
||||
}
|
||||
1773
util/hmessages.po
1773
util/hmessages.po
File diff suppressed because it is too large
Load Diff
20
vendor/brick/math/LICENSE
vendored
Normal file
20
vendor/brick/math/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-present Benjamin Morel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
16
vendor/brick/math/SECURITY.md
vendored
Normal file
16
vendor/brick/math/SECURITY.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the latest release stream is supported.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.8.x | :white_check_mark: |
|
||||
| < 0.8 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report a security vulnerability, please use the
|
||||
[Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
35
vendor/brick/math/composer.json
vendored
Normal file
35
vendor/brick/math/composer.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "brick/math",
|
||||
"description": "Arbitrary-precision arithmetic library",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"Brick",
|
||||
"Math",
|
||||
"Arbitrary-precision",
|
||||
"Arithmetic",
|
||||
"BigInteger",
|
||||
"BigDecimal",
|
||||
"BigRational",
|
||||
"Bignum"
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.1|^8.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5.15|^8.5",
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"vimeo/psalm": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\Tests\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/brick/math/psalm-baseline.xml
vendored
Normal file
40
vendor/brick/math/psalm-baseline.xml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="3.8.5@e6ec5fa22a7b9e61670a24d07b3119aff80dcd89">
|
||||
<file src="src/Internal/Calculator/BcMathCalculator.php">
|
||||
<InvalidNullableReturnType occurrences="3">
|
||||
<code>string</code>
|
||||
<code>string</code>
|
||||
<code>string</code>
|
||||
</InvalidNullableReturnType>
|
||||
<InvalidReturnStatement occurrences="1">
|
||||
<code>[$q, $r]</code>
|
||||
</InvalidReturnStatement>
|
||||
<InvalidReturnType occurrences="1">
|
||||
<code>array</code>
|
||||
</InvalidReturnType>
|
||||
<NullableReturnStatement occurrences="3">
|
||||
<code>\bcdiv($a, $b, 0)</code>
|
||||
<code>\bcmod($a, $b)</code>
|
||||
<code>\bcpowmod($base, $exp, $mod, 0)</code>
|
||||
</NullableReturnStatement>
|
||||
</file>
|
||||
<file src="src/Internal/Calculator/NativeCalculator.php">
|
||||
<InvalidOperand occurrences="6">
|
||||
<code>$a</code>
|
||||
<code>$a</code>
|
||||
<code>$a</code>
|
||||
<code>$b</code>
|
||||
<code>$blockA</code>
|
||||
<code>$blockA</code>
|
||||
</InvalidOperand>
|
||||
<LoopInvalidation occurrences="4">
|
||||
<code>$i</code>
|
||||
<code>$i</code>
|
||||
<code>$i</code>
|
||||
<code>$j</code>
|
||||
</LoopInvalidation>
|
||||
<PossiblyInvalidArgument occurrences="1">
|
||||
<code>$e / 2</code>
|
||||
</PossiblyInvalidArgument>
|
||||
</file>
|
||||
</files>
|
||||
56
vendor/brick/math/psalm.xml
vendored
Normal file
56
vendor/brick/math/psalm.xml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
totallyTyped="false"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
errorBaseline="psalm-baseline.xml"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<LessSpecificReturnType errorLevel="info" />
|
||||
|
||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
||||
|
||||
<DeprecatedMethod errorLevel="info" />
|
||||
<DeprecatedProperty errorLevel="info" />
|
||||
<DeprecatedClass errorLevel="info" />
|
||||
<DeprecatedConstant errorLevel="info" />
|
||||
<DeprecatedFunction errorLevel="info" />
|
||||
<DeprecatedInterface errorLevel="info" />
|
||||
<DeprecatedTrait errorLevel="info" />
|
||||
|
||||
<InternalMethod errorLevel="info" />
|
||||
<InternalProperty errorLevel="info" />
|
||||
<InternalClass errorLevel="info" />
|
||||
|
||||
<MissingClosureReturnType errorLevel="info" />
|
||||
<MissingReturnType errorLevel="info" />
|
||||
<MissingPropertyType errorLevel="info" />
|
||||
<InvalidDocblock errorLevel="info" />
|
||||
<MisplacedRequiredParam errorLevel="info" />
|
||||
|
||||
<PropertyNotSetInConstructor errorLevel="info" />
|
||||
<MissingConstructor errorLevel="info" />
|
||||
<MissingClosureParamType errorLevel="info" />
|
||||
<MissingParamType errorLevel="info" />
|
||||
|
||||
<RedundantCondition errorLevel="info" />
|
||||
|
||||
<DocblockTypeContradiction errorLevel="info" />
|
||||
<RedundantConditionGivenDocblockType errorLevel="info" />
|
||||
|
||||
<UnresolvableInclude errorLevel="info" />
|
||||
|
||||
<RawObjectIteration errorLevel="info" />
|
||||
|
||||
<InvalidStringClass errorLevel="info" />
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user