mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 09:01:15 -04:00
Compare commits
334 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0784cd593a | ||
|
|
9c5d2ee563 | ||
|
|
be5f7c2e67 | ||
|
|
0d0f73fb67 | ||
|
|
680be6cfec | ||
|
|
2ab3d072b0 | ||
|
|
943ecff623 | ||
|
|
03973f5d1d | ||
|
|
c42a0fa9b6 | ||
|
|
61522ed31d | ||
|
|
29a527426a | ||
|
|
62ac0ff21e | ||
|
|
a41c7caa18 | ||
|
|
b3ca31bce7 | ||
|
|
b02f6a1dae | ||
|
|
d35609f33a | ||
|
|
8c19ab8f9f | ||
|
|
30ae198b89 | ||
|
|
bddeab3ac1 | ||
|
|
591349ee74 | ||
|
|
9081a25e64 | ||
|
|
1beadfc6e7 | ||
|
|
f4af532c5a | ||
|
|
76eb1a9d78 | ||
|
|
14a2790dcb | ||
|
|
46f54db197 | ||
|
|
4ffd7587a9 | ||
|
|
c48c62c7a8 | ||
|
|
9e7fd20ade | ||
|
|
efa1d381ba | ||
|
|
740fa058aa | ||
|
|
37f56e1efd | ||
|
|
6294be371a | ||
|
|
bee7549a1e | ||
|
|
db14dbacc9 | ||
|
|
27058e6297 | ||
|
|
b41175e0e2 | ||
|
|
eeea3251ad | ||
|
|
34ffff3947 | ||
|
|
65ed3818ec | ||
|
|
c8417df6f1 | ||
|
|
dc3be7ecf7 | ||
|
|
cf3c0b593b | ||
|
|
34f64148e8 | ||
|
|
fc5dad1983 | ||
|
|
c3c40548b9 | ||
|
|
0e2e932102 | ||
|
|
6930c4e23b | ||
|
|
01b9f2dfcf | ||
|
|
0cc6f66a26 | ||
|
|
d384f55dd1 | ||
|
|
1893368aa5 | ||
|
|
a520063265 | ||
|
|
1e171a72a0 | ||
|
|
5b1a0d93b9 | ||
|
|
7e04662a9c | ||
|
|
a804549781 | ||
|
|
2a60f1cc6e | ||
|
|
2ddff785e5 | ||
|
|
38882efb5c | ||
|
|
6f7786b068 | ||
|
|
0819141f03 | ||
|
|
329ef5049f | ||
|
|
34bb8c65d6 | ||
|
|
575ccae6f9 | ||
|
|
486be87e33 | ||
|
|
c0350861ef | ||
|
|
a7ec1805e3 | ||
|
|
4b06bc552f | ||
|
|
76ee7b7eea | ||
|
|
04b1e7e34f | ||
|
|
17dbb156e1 | ||
|
|
135117c637 | ||
|
|
d3348f7855 | ||
|
|
39bbcb66c8 | ||
|
|
d45e8e4d20 | ||
|
|
d65052c1ac | ||
|
|
2fbc42753f | ||
|
|
4195865965 | ||
|
|
de3f6fbeba | ||
|
|
6a377120bd | ||
|
|
502226b0a6 | ||
|
|
78206b48f4 | ||
|
|
dc3cec06ca | ||
|
|
5a7688e099 | ||
|
|
c721f01c76 | ||
|
|
463806822c | ||
|
|
b74c2f001d | ||
|
|
9fc7a8b626 | ||
|
|
3ffd92a6c3 | ||
|
|
29b02e5329 | ||
|
|
97584e046f | ||
|
|
09d2fce85d | ||
|
|
fc3060cb29 | ||
|
|
9804a67165 | ||
|
|
21eddefa41 | ||
|
|
9b62e7eedb | ||
|
|
bf30cfd8a4 | ||
|
|
139ffae367 | ||
|
|
51a48cc264 | ||
|
|
abbca12565 | ||
|
|
9e9d96a2ec | ||
|
|
615c9f1cbe | ||
|
|
7d75d0cfbd | ||
|
|
5468de2c6a | ||
|
|
6d8aabab23 | ||
|
|
e74359fcfe | ||
|
|
53c842c614 | ||
|
|
23ececeb34 | ||
|
|
521c9eb566 | ||
|
|
35877b1382 | ||
|
|
c531287170 | ||
|
|
8e79a81b88 | ||
|
|
b95ceb301f | ||
|
|
76a94495c4 | ||
|
|
b6b2299b4e | ||
|
|
34ddea87d3 | ||
|
|
3d318542cb | ||
|
|
4a8c3cdc61 | ||
|
|
c0b6f2d95f | ||
|
|
9ca7fccab8 | ||
|
|
d91fcfc866 | ||
|
|
29b53f3b9d | ||
|
|
30987095c7 | ||
|
|
43b93de570 | ||
|
|
5b310cf315 | ||
|
|
a1c2a57ea6 | ||
|
|
34bf8f1133 | ||
|
|
c708ec577e | ||
|
|
c185685f2d | ||
|
|
daee5b3477 | ||
|
|
5d0346ee30 | ||
|
|
85ad5355cf | ||
|
|
4c8b84633a | ||
|
|
c0dd4d748d | ||
|
|
c94f25570b | ||
|
|
ffa5e08832 | ||
|
|
63243c8e04 | ||
|
|
21c4ec2de0 | ||
|
|
a8d87af418 | ||
|
|
7b084a065e | ||
|
|
47f6b202e5 | ||
|
|
f588d8379b | ||
|
|
58827e130b | ||
|
|
d702334604 | ||
|
|
b04aa799e3 | ||
|
|
e113f6cb9d | ||
|
|
bc13b7eb72 | ||
|
|
f50b395da6 | ||
|
|
a0e8e40f1c | ||
|
|
cb6055c1b8 | ||
|
|
25424c16e4 | ||
|
|
99dcdee67a | ||
|
|
99928f1aea | ||
|
|
1740ae2104 | ||
|
|
d8372f8433 | ||
|
|
2a15d2c421 | ||
|
|
bacf19688f | ||
|
|
31fbdcf6c5 | ||
|
|
c8818cb7b3 | ||
|
|
eb20789821 | ||
|
|
c90862217e | ||
|
|
df87d6feeb | ||
|
|
6c808abcfc | ||
|
|
f1822bdfab | ||
|
|
c3428acd80 | ||
|
|
d619192b22 | ||
|
|
5bdc713afe | ||
|
|
46eff1c937 | ||
|
|
76e1ea1c02 | ||
|
|
755076a8e5 | ||
|
|
b49f7b8b34 | ||
|
|
c4dd8885e4 | ||
|
|
4c82952b58 | ||
|
|
0da69cb9c7 | ||
|
|
36e244060c | ||
|
|
b13a9f57af | ||
|
|
0aa67ad7f9 | ||
|
|
195a3a6827 | ||
|
|
38ecff1220 | ||
|
|
67e64287af | ||
|
|
b022703b0b | ||
|
|
e8069c0d93 | ||
|
|
7a1c6b64c2 | ||
|
|
8250cb1e8d | ||
|
|
ffe2c4d42b | ||
|
|
f06c970628 | ||
|
|
99bce46b32 | ||
|
|
f711913778 | ||
|
|
a8ac231667 | ||
|
|
f7c8791a6d | ||
|
|
7acc775c91 | ||
|
|
c2e21e837f | ||
|
|
755d0f54f7 | ||
|
|
f62d66ff25 | ||
|
|
406d19f930 | ||
|
|
42b13614eb | ||
|
|
c942bd67fe | ||
|
|
b8dc3d74b6 | ||
|
|
38fb263737 | ||
|
|
b55beed2f9 | ||
|
|
e9278c03c1 | ||
|
|
ae1fe83784 | ||
|
|
717a547c40 | ||
|
|
ec491e87ab | ||
|
|
42e30d0835 | ||
|
|
5b19418e48 | ||
|
|
1bc9a7373f | ||
|
|
23e59b5dcc | ||
|
|
c6b459cf96 | ||
|
|
33254b4cac | ||
|
|
44da40d18d | ||
|
|
c742f25801 | ||
|
|
b153687bf1 | ||
|
|
3318f093da | ||
|
|
d98d56c3b5 | ||
|
|
c3f5f6c7ad | ||
|
|
5f21edcc53 | ||
|
|
cd0731cbb0 | ||
|
|
f392ddec2f | ||
|
|
df71168ab7 | ||
|
|
e93b26bf54 | ||
|
|
a73d4a8cbd | ||
|
|
20ee57801c | ||
|
|
6a270d7f02 | ||
|
|
68639637c9 | ||
|
|
0d1eabbc33 | ||
|
|
dce249f7a9 | ||
|
|
1723d4fbd8 | ||
|
|
c4b09f1a4f | ||
|
|
788c973c13 | ||
|
|
465c5c8cfb | ||
|
|
ee28ba5be1 | ||
|
|
9a22e9cf39 | ||
|
|
2513f605b6 | ||
|
|
3b1ffb2028 | ||
|
|
47c6624e12 | ||
|
|
b6f1b064d3 | ||
|
|
17d89467df | ||
|
|
1282214d48 | ||
|
|
f4bc6ee615 | ||
|
|
f8b8d8c540 | ||
|
|
57ff667438 | ||
|
|
abe3039926 | ||
|
|
82a1117e91 | ||
|
|
b6ff3a4d99 | ||
|
|
f4046efcb2 | ||
|
|
fc1d3831cf | ||
|
|
867deda247 | ||
|
|
f8149face5 | ||
|
|
7e2aecd8bb | ||
|
|
105d121199 | ||
|
|
37d662f2f5 | ||
|
|
5b50454b4d | ||
|
|
b5e4c08fc5 | ||
|
|
db39cd8b7c | ||
|
|
a35f741a35 | ||
|
|
fc02e018cb | ||
|
|
b14a530efb | ||
|
|
f70bc571bd | ||
|
|
8cc64176b4 | ||
|
|
7450ac1a31 | ||
|
|
c72e5e3b66 | ||
|
|
5e811819e2 | ||
|
|
f1c0034a18 | ||
|
|
7342cb81a3 | ||
|
|
b40e858556 | ||
|
|
95a4ed7d6a | ||
|
|
2c2d4b6b95 | ||
|
|
4490eae4fe | ||
|
|
9d59cb0135 | ||
|
|
7d348fe69f | ||
|
|
fa8fb9e73f | ||
|
|
f6093872ec | ||
|
|
e8030e29d9 | ||
|
|
df8bb0596a | ||
|
|
0003e0b8a5 | ||
|
|
e42703d557 | ||
|
|
4636e56395 | ||
|
|
27ebeffad4 | ||
|
|
07110cee17 | ||
|
|
afa1f1416b | ||
|
|
f8dfcab0ca | ||
|
|
e14fd920d6 | ||
|
|
8c10fdae5b | ||
|
|
eee027d9ff | ||
|
|
1b1fb5d26a | ||
|
|
c36e0805d8 | ||
|
|
5c56041185 | ||
|
|
5aefe0b74f | ||
|
|
20e0359efd | ||
|
|
9c790e5a90 | ||
|
|
9c79b5be77 | ||
|
|
2d9a4f4e42 | ||
|
|
565602538c | ||
|
|
78972725ae | ||
|
|
5ab90f7791 | ||
|
|
b90d98fc2b | ||
|
|
eca3ae393b | ||
|
|
2bd69495d2 | ||
|
|
bfd3da43ac | ||
|
|
32a9eaf3b6 | ||
|
|
91cea1f28a | ||
|
|
220ed35f58 | ||
|
|
b1cf5d4e44 | ||
|
|
fe330ec1bb | ||
|
|
2968bf8241 | ||
|
|
a40babbf0d | ||
|
|
7822257e1c | ||
|
|
b37165c62b | ||
|
|
5e9d267959 | ||
|
|
1a1e6b6810 | ||
|
|
88140002e7 | ||
|
|
efc203d958 | ||
|
|
42d4cdcc39 | ||
|
|
fd433b3eb6 | ||
|
|
7483adb8ad | ||
|
|
45fd462f80 | ||
|
|
807003adf7 | ||
|
|
1b0a17c7db | ||
|
|
60b145833c | ||
|
|
39458b2ba8 | ||
|
|
5de38b3632 | ||
|
|
6ced3426cf | ||
|
|
43460c9d19 | ||
|
|
ca17fb01bc | ||
|
|
a6f65aa9c5 | ||
|
|
ae9a7727d6 | ||
|
|
3ac5d5257b | ||
|
|
668d7c73ed | ||
|
|
c95f708c91 | ||
|
|
06e214e567 | ||
|
|
18f8cafee0 | ||
|
|
6bd6afac05 |
101
.gitlab-ci.yml
101
.gitlab-ci.yml
@@ -1,7 +1,9 @@
|
||||
# Select image from https://hub.docker.com/_/php/
|
||||
#image: php:7.3
|
||||
# Use a prepared Hubzilla image to optimise pipeline duration
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
|
||||
image: php:8.0
|
||||
|
||||
stages:
|
||||
- test
|
||||
@@ -35,7 +37,12 @@ before_script:
|
||||
- if [ -f /usr/local/etc/php/conf.d/z_prod.ini ]; then mv /usr/local/etc/php/conf.d/z_prod.ini /usr/local/etc/php/conf.d/z_prod.ini.off; fi
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- pecl install xdebug
|
||||
- apt-get update
|
||||
- apt-get install zip unzip libjpeg-dev libpng-dev -yqq
|
||||
- docker-php-ext-enable xdebug
|
||||
- docker-php-ext-install gd
|
||||
|
||||
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
@@ -43,31 +50,38 @@ before_script:
|
||||
# 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
|
||||
# hidden job definition with template for PHP
|
||||
.job_template_php: &job_definition_php
|
||||
stage: test
|
||||
script:
|
||||
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
#.job_template_mysql: &job_definition_mysql
|
||||
# stage: test
|
||||
# script:
|
||||
# - echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
# - echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
# - echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||
# - vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
|
||||
# hidden job definition with template for PostgreSQL
|
||||
.job_template_postgres: &job_definition_postgres
|
||||
stage: test
|
||||
services:
|
||||
- postgres:latest
|
||||
script:
|
||||
- export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
- psql --version
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
#.job_template_postgres: &job_definition_postgres
|
||||
# stage: test
|
||||
# services:
|
||||
# - postgres:latest
|
||||
# script:
|
||||
# - export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
# - psql --version
|
||||
# - psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
# Import hubzilla's DB schema
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# - psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
- vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
|
||||
# - vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
|
||||
|
||||
# hidden job definition with artifacts config template
|
||||
.artifacts_template:
|
||||
@@ -82,36 +96,41 @@ before_script:
|
||||
- tests/results/
|
||||
|
||||
|
||||
# PHP7.3 with MySQL 5.7
|
||||
php7.3_mysql5.7:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- mysql:5.7
|
||||
# PHP8.0
|
||||
php8.0:
|
||||
<<: *job_definition_php
|
||||
|
||||
# PHP8.0 with MySQL 5.7
|
||||
#php8.0_mysql5.7:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - mysql:5.7
|
||||
|
||||
|
||||
# PHP7.3 with MySQL 8 (latest)
|
||||
php7.3_mysql8:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- name: mysql:8
|
||||
command: ["--default-authentication-plugin=mysql_native_password"]
|
||||
# PHP8.0 with MySQL 8 (latest)
|
||||
#php8.0_mysql8:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - name: mysql:8
|
||||
# command: ["--default-authentication-plugin=mysql_native_password"]
|
||||
|
||||
|
||||
# PHP7.3 with MariaDB 10.2
|
||||
php7.3_mariadb10.2:
|
||||
<<: *job_definition_mysql
|
||||
services:
|
||||
- name: mariadb:10.2
|
||||
alias: mysql
|
||||
# PHP8.0 with MariaDB 10.2
|
||||
#php8.0_mariadb10.2:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - name: mariadb:10.2
|
||||
# alias: mysql
|
||||
|
||||
|
||||
# PHP7.3 with MariaDB 10.3 (latest)
|
||||
php7.3_mariadb10.3:
|
||||
<<: *job_definition_mysql
|
||||
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
services:
|
||||
- name: mariadb:10.3
|
||||
alias: mysql
|
||||
# PHP8.0 with MariaDB 10.3 (latest)
|
||||
#php8.0_mariadb10.3:
|
||||
# <<: *job_definition_mysql
|
||||
# image: php:8.0
|
||||
#image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
# services:
|
||||
# - name: mariadb:10.3
|
||||
# alias: mysql
|
||||
|
||||
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
@@ -131,7 +150,7 @@ php7.3_mariadb10.3:
|
||||
pages:
|
||||
stage: deploy
|
||||
cache: {}
|
||||
image: php:7-cli-alpine
|
||||
image: php:8-cli-alpine
|
||||
before_script:
|
||||
- apk update
|
||||
- apk add doxygen ttf-freefont graphviz
|
||||
|
||||
134
CHANGELOG
134
CHANGELOG
@@ -1,3 +1,137 @@
|
||||
Hubzilla 7.2 (2022-03-29)
|
||||
- Streamline comment policy with downstream project
|
||||
- Add new function is_local_url()
|
||||
- Add helper function to escape URLs
|
||||
- Add signing algorithm to zotinfo()
|
||||
- Store signing algorithm in import_xchan()
|
||||
- Use bootstrap-nightfall for redbasic:dark schema
|
||||
- Add support for hs2019
|
||||
- Remove unused function script_path()
|
||||
- Move login and register button into the hamburger menu for small screens
|
||||
- Collect accept headers in an array instead of a concatenated string
|
||||
- Update composer libs
|
||||
- Enhanced content filters
|
||||
- Improve mod gprobe to also deal with URLs
|
||||
- Adapt unseen forum posts query in mod network to new forum post style
|
||||
- Remove deprecated widgets
|
||||
- Add inbound support for quoteUrl to Lib/Activity
|
||||
- Add widget descriptions
|
||||
- Add a GUI for the PDL editor
|
||||
|
||||
Addons
|
||||
- Pubcrawl: deprecate as.php in favor of core libs
|
||||
- Pubcrawl: rewrite/modernize mod inbox
|
||||
- Pubcrawl: reflect core enhanced content filter changes
|
||||
- Diaspora: reflect core enhanced content filter changes
|
||||
- Fediwordle: new addon - a distributed word game inspired by wordle
|
||||
- Pubcrawl: streamline post_local hook with diaspora
|
||||
|
||||
Bugfixes
|
||||
- Fix comments_closed date on posts where comments are disabled
|
||||
- Fix open redirect via rpath query param (CVE-2022-27256)
|
||||
- Fix cross-site scripting via rpath query param (CVE-2022-27258)
|
||||
- Fix local file inclusion in redbasic theme (CVE-2022-27257)
|
||||
- Fix baseurl for css and js
|
||||
- Fix duplicate IDs in login form
|
||||
- Fix unknown author not fetched if w2w comment arrives
|
||||
- Fix thr_parent lost across edits
|
||||
|
||||
|
||||
Hubzilla 7.0.3 (2022-02-10)
|
||||
- Allow to override the charset for the PDO connection string via $db_charset in .htconfig.php
|
||||
|
||||
|
||||
Hubzilla 7.0.2 (2022-02-09)
|
||||
- Update french templates
|
||||
- Add charset to the PDO connection strings
|
||||
- Introduce delete keytype for get_activitystreams_key()
|
||||
- Fix PHP error in Daemon/Externals
|
||||
- Improved actor cache handling
|
||||
- Implement manual fetch of packed local links
|
||||
- Add JSalmon data to the meta field instead of data in Lib/ActivityStreams
|
||||
- Fix some PHP8.1 deprecation warnings
|
||||
- Fix delivery report for likes not found in some cases
|
||||
- Allow zotfinger to recurse through all known hublocs if the one we got does not exist (404) or got removed (410)
|
||||
- Diaspora: improve relaying of comments
|
||||
- Fix regression in mod hcard
|
||||
- Add the LD signature in Daemon/Notifier in case where there is no signed data available
|
||||
- Prevent zot6 packet being saved as AP raw message
|
||||
- Attach iconfig to the activity instead of the activity object
|
||||
|
||||
Addons
|
||||
- Pubcrawl: make sure the sys channel falls through the app installed check
|
||||
- Pubcrawl: improve local delivery of shared inbox items
|
||||
|
||||
|
||||
Hubzilla 7.0.1 (2022-01-28)
|
||||
- Fix removing contacts from privacy groups in the contact edit modal
|
||||
- Fix escape_tags() messing with URLs in actor_store()
|
||||
- Fix pagination in the cards module if a category is selected
|
||||
- Remove unused entries in webfinger
|
||||
- Remove deprecated mail app from apps
|
||||
- Set item_hidden for forum comment announces
|
||||
- Fix relaying of signed messages for activitypub
|
||||
- Fix contact role permissions not re-assigned if the role permission has changed
|
||||
- Fix default channel role not set in rare cases
|
||||
|
||||
Addons
|
||||
- Pubcrawl: fix webfinger not returning the fetched URL
|
||||
- Pubcrawl: improved queue handling for rejected deliveries
|
||||
|
||||
|
||||
Hubzilla 7.0 (2022-01-21)
|
||||
- Provide theme_color and background_color in App::$theme_info for usage in page meta and manifest
|
||||
- PWA improvements according to lighthouse
|
||||
- Refactor mod profile_photo
|
||||
- Remove core legacy mail code
|
||||
- Set session samesite cookie flag
|
||||
- Improve toc bbcode for more flexible usecases
|
||||
- Deprecate include/group in favor of Lib/AccessList
|
||||
- Deprecate AccessList::widget()
|
||||
- Mark forum channel profile images with a small icon in the timelines
|
||||
- Improve privacy groups UI/UX
|
||||
- Do not show connections widget if there are no connections
|
||||
- Remove suggestions widget from various modules
|
||||
- Provide guest access links for private resources in lockview
|
||||
- Improve pconfig syncing
|
||||
- deprecate include/group in favor of Lib/AccessList
|
||||
- Implement background deleting of items in contact_remove()
|
||||
- Refactor guest access tokens for better usability and provide quick access
|
||||
- Refactor permissions handling
|
||||
- Improved poll rendering
|
||||
|
||||
Bugfixes
|
||||
- Fix items not deleted on remote channel purge
|
||||
- Fix plink in post_activity_item()
|
||||
- Fix multiple update_poll() calls dismissed in queueworker
|
||||
- Fix blocked or ignored contacts displayed in connections
|
||||
- Fix polls for forum channels
|
||||
|
||||
Addons:
|
||||
- Legacy mail: remove
|
||||
- Deprecate include/group in favor of Lib/AccessList
|
||||
- Pubcrawl: support pleroma end time for polls
|
||||
- Pubcrawl: slightly adjust the way we check mastodon direct messages
|
||||
- Socialauth: scope support and improvements
|
||||
|
||||
|
||||
Hubzilla 6.4.2 (2021-12-14)
|
||||
- Fix issue in mod sse_bs where returning message id's were assumed to be base64 encoded
|
||||
- Fix announce activity type not registered as response activity
|
||||
|
||||
|
||||
Hubzilla 6.4.1 (2021-12-03)
|
||||
- Fix hubloc_site_id in fix_system_urls() on detected site rename events
|
||||
- Fix duplicate deliveries if duplicate hublocs available
|
||||
- Redesign profile vcard for improved responsive handling
|
||||
- Fix profile photos not stored in profile photo folder
|
||||
- Maximum width of content region is now calculated in rem for improved responsive handling
|
||||
- Fix likes notices emited allthough they are disabled
|
||||
- Fix page not reloaded after comment/like in mod photos - issue #1651
|
||||
- Port improved Lib/HttpMeta from zap
|
||||
- Improved responsive aside
|
||||
|
||||
|
||||
Hubzilla 6.4 (2021-11-09)
|
||||
- Automatically connect the invitee with the inviting channel
|
||||
- Use the composer version of urlify
|
||||
|
||||
@@ -89,4 +89,4 @@ class PermissionLimits {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class PermissionRoles {
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
static function role_perms($role) {
|
||||
@@ -27,6 +27,54 @@ class PermissionRoles {
|
||||
$ret['role'] = $role;
|
||||
|
||||
switch($role) {
|
||||
|
||||
case 'public':
|
||||
$ret['default_collection'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
|
||||
'send_stream', 'post_comments', 'post_mail', 'post_wall', 'chat', 'post_like', 'republish'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['post_comments'] = PERMS_AUTHED;
|
||||
$ret['limits']['post_mail'] = PERMS_AUTHED;
|
||||
$ret['limits']['post_like'] = PERMS_AUTHED;
|
||||
$ret['limits']['chat'] = PERMS_AUTHED;
|
||||
break;
|
||||
|
||||
// Hubzilla default role
|
||||
case 'personal':
|
||||
$ret['default_collection'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
|
||||
'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
break;
|
||||
|
||||
case 'group':
|
||||
$ret['default_collection'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'view_wiki', 'post_wall', 'post_comments',
|
||||
'post_mail', 'post_like', 'chat'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
break;
|
||||
|
||||
// Provide some defaults for the custom role so that we do not start
|
||||
// with no permissions at all if we create a new channel with this role
|
||||
case 'custom':
|
||||
$ret['default_collection'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'view_pages', 'view_wiki',
|
||||
'send_stream', 'post_comments', 'post_mail', 'chat', 'post_like'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
break;
|
||||
|
||||
/*
|
||||
case 'social':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = false;
|
||||
@@ -193,13 +241,14 @@ class PermissionRoles {
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
*/
|
||||
|
||||
case 'custom':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$x = get_config('system','role_perms');
|
||||
|
||||
// let system settings over-ride any or all
|
||||
if($x && is_array($x) && array_key_exists($role,$x))
|
||||
$ret = array_merge($ret,$x[$role]);
|
||||
@@ -284,6 +333,7 @@ class PermissionRoles {
|
||||
*/
|
||||
static public function roles() {
|
||||
$roles = [
|
||||
|
||||
t('Social Networking') => [
|
||||
'social_federation' => t('Social - Federation'),
|
||||
'social' => t('Social - Mostly Public'),
|
||||
@@ -317,4 +367,29 @@ class PermissionRoles {
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Array with translated role names and grouping.
|
||||
*
|
||||
* Return an associative array with role names that can be used
|
||||
* to create select groups like in \e field_select_grouped.tpl.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function channel_roles() {
|
||||
$channel_roles = [
|
||||
//'public' => [t('Public'), t('A very permissive role suited for participation in the fediverse')],
|
||||
//'personal' => [t('Personal'), t('The $Projectname default role suited for a personal channel')],
|
||||
//'forum' => [t('Community forum'), t('This role configures your channel to act as an community forum')],
|
||||
//'custom' => [t('Custom'), t('This role comes with the presets of the personal role but allows you to configure it to your needs')]
|
||||
'public' => t('Public'),
|
||||
'personal' => t('Personal'),
|
||||
'group' => t('Community forum'),
|
||||
'custom' => t('Custom')
|
||||
];
|
||||
|
||||
call_hooks('list_channel_roles', $channel_roles);
|
||||
|
||||
return $channel_roles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class Permissions {
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,9 +67,9 @@ class Permissions {
|
||||
'post_comments' => t('Can comment on or like my posts'),
|
||||
'post_mail' => t('Can send me direct messages'),
|
||||
'post_like' => t('Can like/dislike profiles and profile things'),
|
||||
'tag_deliver' => t('Can forward direct messages to all my channel connections (forum)'),
|
||||
'chat' => t('Can chat with me'),
|
||||
'republish' => t('Can source my public posts in derived channels'),
|
||||
'republish' => t('Can source/mirror my public posts in derived channels'),
|
||||
//'tag_deliver' => t('Can forward to my contacts via direct messages (forum)'),
|
||||
'delegate' => t('Can administer my channel')
|
||||
];
|
||||
|
||||
@@ -217,25 +217,23 @@ class Permissions {
|
||||
|
||||
$my_perms = [];
|
||||
$permcat = null;
|
||||
$automatic = 0;
|
||||
$automatic = get_pconfig($channel_id, 'system', 'autoperms');
|
||||
|
||||
// If a default permcat exists, use that
|
||||
|
||||
$pc = ((feature_enabled($channel_id, 'permcats')) ? get_pconfig($channel_id, 'system', 'default_permcat') : 'default');
|
||||
if (!in_array($pc, ['', 'default'])) {
|
||||
$pcp = new Zlib\Permcat($channel_id);
|
||||
$permcat = $pcp->fetch($pc);
|
||||
if ($permcat && $permcat['perms']) {
|
||||
foreach ($permcat['perms'] as $p) {
|
||||
$my_perms[$p['name']] = $p['value'];
|
||||
}
|
||||
$pc = get_pconfig($channel_id, 'system', 'default_permcat', 'default');
|
||||
$pcp = new Zlib\Permcat($channel_id);
|
||||
$permcat = $pcp->fetch($pc);
|
||||
if ($permcat && $permcat['perms']) {
|
||||
foreach ($permcat['perms'] as $p) {
|
||||
$my_perms[$p['name']] = $p['value'];
|
||||
}
|
||||
}
|
||||
|
||||
// look up the permission role to see if it specified auto-connect
|
||||
// and if there was no permcat or a default permcat, set the perms
|
||||
// from the role
|
||||
|
||||
/*
|
||||
$role = get_pconfig($channel_id, 'system', 'permissions_role');
|
||||
if ($role) {
|
||||
$xx = PermissionRoles::role_perms($role);
|
||||
@@ -247,11 +245,12 @@ class Permissions {
|
||||
$my_perms = Permissions::FilledPerms($default_perms);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// If we reached this point without having any permission information,
|
||||
// it is likely a custom permissions role. First see if there are any
|
||||
// automatic permissions.
|
||||
|
||||
/*
|
||||
if (!$my_perms) {
|
||||
$m = Permissions::FilledAutoperms($channel_id);
|
||||
if ($m) {
|
||||
@@ -259,11 +258,12 @@ class Permissions {
|
||||
$my_perms = $m;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// If we reached this point with no permissions, the channel is using
|
||||
// custom perms but they are not automatic. They will be stored in abconfig with
|
||||
// the channel's channel_hash (the 'self' connection).
|
||||
|
||||
/*
|
||||
if (!$my_perms) {
|
||||
$r = q("select channel_hash from channel where channel_id = %d",
|
||||
intval($channel_id)
|
||||
@@ -280,10 +280,10 @@ class Permissions {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (['perms' => $my_perms, 'automatic' => $automatic]);
|
||||
*/
|
||||
return (['perms' => $my_perms, 'automatic' => $automatic, 'role' => $pc]);
|
||||
}
|
||||
|
||||
/*
|
||||
static public function serialise($p) {
|
||||
$n = [];
|
||||
if ($p) {
|
||||
@@ -295,4 +295,5 @@ class Permissions {
|
||||
}
|
||||
return implode(',', $n);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
25
Zotlabs/Daemon/Delxitems.php
Normal file
25
Zotlabs/Daemon/Delxitems.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/connections.php');
|
||||
|
||||
/*
|
||||
* Daemon to remove 'item' resources in the background from a removed connection
|
||||
*/
|
||||
|
||||
class Delxitems {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
cli_startup();
|
||||
|
||||
if($argc != 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove_abook_items($argv[1], $argv[2]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,9 @@ class Externals {
|
||||
continue;
|
||||
}
|
||||
|
||||
Libzot::fetch_conversation($importer, $message['object']['id']);
|
||||
$obj_id = isset($message['object']['id']) ?? $message['object'];
|
||||
|
||||
Libzot::fetch_conversation($importer, $obj_id);
|
||||
$total++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -15,19 +15,31 @@ class Gprobe {
|
||||
return;
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
$is_webbie = false;
|
||||
$r = null;
|
||||
|
||||
if (!strpos($url, '@'))
|
||||
return;
|
||||
if (filter_var($url, FILTER_VALIDATE_EMAIL)) {
|
||||
$is_webbie = true;
|
||||
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
}
|
||||
elseif (filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
$r = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
}
|
||||
|
||||
if (!$r) {
|
||||
$href = Webfinger::zot_url(punify($url));
|
||||
if ($href) {
|
||||
$zf = Zotfinger::exec($href, null);
|
||||
if ($is_webbie) {
|
||||
$url = Webfinger::zot_url(punify($url));
|
||||
}
|
||||
|
||||
if ($url) {
|
||||
$zf = Zotfinger::exec($url, null);
|
||||
}
|
||||
|
||||
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
Libzot::import_xchan($zf['data']);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Zotlabs\Daemon;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Queue;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
require_once('include/conversation.php');
|
||||
@@ -78,6 +79,10 @@ class Notifier {
|
||||
static public $encoded_item = null;
|
||||
static public $channel = null;
|
||||
static public $private = false;
|
||||
// $fragment can contain additional info to omit de-duplication in the queueworker.
|
||||
// E.g. if an item is updated many times in a row from different sources (multiple vote updates) the
|
||||
// update source mid or a timestamp or random string can be added.
|
||||
static public $fragment = null;
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
@@ -88,7 +93,6 @@ class Notifier {
|
||||
logger('notifier: invoked: ' . print_r($argv, true), LOGGER_DEBUG);
|
||||
|
||||
$cmd = $argv[1];
|
||||
|
||||
$item_id = $argv[2];
|
||||
|
||||
if (!$item_id) {
|
||||
@@ -103,6 +107,7 @@ class Notifier {
|
||||
self::$encoded_item = null;
|
||||
self::$channel = null;
|
||||
self::$private = false;
|
||||
self::$fragment = null;
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$normal_mode = true;
|
||||
@@ -222,6 +227,8 @@ class Notifier {
|
||||
|
||||
// Fetch the target item
|
||||
|
||||
self::$fragment = $argv[3] ?? '';
|
||||
|
||||
$r = q("SELECT * FROM item WHERE id = %d AND parent != 0",
|
||||
intval($item_id)
|
||||
);
|
||||
@@ -234,7 +241,7 @@ class Notifier {
|
||||
|
||||
$target_item = $r[0];
|
||||
|
||||
if (in_array($target_item['author']['xchan_network'], ['rss', 'anon'])) {
|
||||
if (in_array($target_item['author']['xchan_network'], ['rss', 'anon', 'token'])) {
|
||||
logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
@@ -330,12 +337,14 @@ class Notifier {
|
||||
self::$encoded_item = json_decode($m, true);
|
||||
}
|
||||
else {
|
||||
|
||||
self::$encoded_item = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], Activity::encode_activity($target_item)
|
||||
);
|
||||
self::$encoded_item['signature'] = LDSignatures::sign(self::$encoded_item, self::$channel);
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
|
||||
@@ -488,7 +497,7 @@ class Notifier {
|
||||
// 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_dead from hubloc left join site on site_url = hubloc_url
|
||||
$hubs = dbq("select hubloc.*, site.site_crypto, site.site_flags, site.site_dead from hubloc left join site on site_url = hubloc_url
|
||||
where hubloc_hash in (" . protect_sprintf(implode(',', self::$recipients)) . ")
|
||||
and hubloc_error = 0 and hubloc_deleted = 0"
|
||||
);
|
||||
@@ -550,7 +559,9 @@ class Notifier {
|
||||
if (!array_key_exists($hub['hubloc_site_id'], $hub_env)) {
|
||||
$hub_env[$hub['hubloc_site_id']] = [];
|
||||
}
|
||||
$hub_env[$hub['hubloc_site_id']][] = $er;
|
||||
if (!in_array($er, $hub_env[$hub['hubloc_site_id']])) {
|
||||
$hub_env[$hub['hubloc_site_id']][] = $er;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,6 +639,18 @@ class Notifier {
|
||||
|
||||
// default: zot protocol
|
||||
|
||||
// Prevent zot6 delivery of group comment boosts, which are not required for conversational platforms.
|
||||
// ActivityPub conversational platforms may wish to filter these if they don't want or require them.
|
||||
// We will assume here that if $target_item exists and has a verb that it is an actual item structure
|
||||
// so we won't need to check the existence of the other item fields prior to evaluation.
|
||||
|
||||
// This shouldn't produce false positives on comment boosts that were generated on other platforms
|
||||
// because we won't be delivering them.
|
||||
|
||||
if (isset($target_item) && isset($target_item['verb']) && $target_item['verb'] === 'Announce' && $target_item['author_xchan'] === $target_item['owner_xchan'] && ! intval($target_item['item_thread_top'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
|
||||
@@ -671,7 +694,7 @@ class Notifier {
|
||||
// This wastes a process if there are no delivery hooks configured, so check this before launching the new process
|
||||
$x = q("select * from hook where hook = 'notifier_normal'");
|
||||
if ($x) {
|
||||
Master::Summon(['Deliver_hooks', $target_item['id']]);
|
||||
Master::Summon(['Deliver_hooks', $target_item['id'], self::$fragment]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
<?php
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
|
||||
class AccessList {
|
||||
|
||||
static function add($uid,$name,$public = 0) {
|
||||
|
||||
$ret = false;
|
||||
static function add($uid, $name, $public = 0) {
|
||||
|
||||
$ret = false;
|
||||
$hash = '';
|
||||
if ($uid && $name) {
|
||||
$r = self::byname($uid,$name); // check for dups
|
||||
$r = self::by_name($uid, $name); // check for dups
|
||||
if ($r !== false) {
|
||||
|
||||
// This could be a problem.
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a list which we once deleted
|
||||
// all the old members are gone, but the list remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead list, but old content which
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
|
||||
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
if (($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice( t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
|
||||
notice(t('A deleted privacy group with this name was revived. Existing item permissions <strong>may</strong> apply to this privacy group and any future members. If this is not what you intended, please create another privacy group with a different name.') . EOL);
|
||||
}
|
||||
return true;
|
||||
$hash = self::by_id($uid, $r);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
VALUES( '%s', %d, %d, '%s' ) ",
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
@@ -42,12 +41,12 @@ class AccessList {
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $ret;
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return (($ret) ? $hash : $ret);
|
||||
}
|
||||
|
||||
|
||||
static function remove($uid,$name) {
|
||||
static function remove($uid, $name) {
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
@@ -55,36 +54,36 @@ class AccessList {
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// remove group from default posting lists
|
||||
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$user_info = array_shift($r);
|
||||
$change = false;
|
||||
$change = false;
|
||||
|
||||
if ($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
$change = true;
|
||||
}
|
||||
|
||||
if ($change) {
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
WHERE channel_id = %d",
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
@@ -110,16 +109,16 @@ class AccessList {
|
||||
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// returns the integer id of an access group owned by $uid and named $name
|
||||
// or false.
|
||||
|
||||
static function byname($uid,$name) {
|
||||
if (! ($uid && $name)) {
|
||||
|
||||
static function by_name($uid, $name) {
|
||||
if (!($uid && $name)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
@@ -132,11 +131,11 @@ class AccessList {
|
||||
return false;
|
||||
}
|
||||
|
||||
static function by_id($uid,$id) {
|
||||
if (! ($uid && $id)) {
|
||||
static function by_id($uid, $id) {
|
||||
if (!($uid && $id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
|
||||
intval($uid),
|
||||
intval($id)
|
||||
@@ -147,10 +146,8 @@ class AccessList {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function rec_byhash($uid,$hash) {
|
||||
if (! ( $uid && $hash)) {
|
||||
static function by_hash($uid, $hash) {
|
||||
if (!($uid && $hash)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
@@ -163,46 +160,46 @@ class AccessList {
|
||||
return false;
|
||||
}
|
||||
|
||||
static function member_remove($uid, $name, $member, $gid = 0) {
|
||||
if (!$gid) {
|
||||
$gid = self::by_name($uid, $name);
|
||||
}
|
||||
|
||||
static function member_remove($uid,$name,$member) {
|
||||
$gid = self::byname($uid,$name);
|
||||
if (! $gid) {
|
||||
return false;
|
||||
}
|
||||
if (! ($uid && $gid && $member)) {
|
||||
if (!($uid && $gid && $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function member_add($uid,$name,$member,$gid = 0) {
|
||||
if (! $gid) {
|
||||
$gid = self::byname($uid,$name);
|
||||
static function member_add($uid, $name, $member, $gid = 0) {
|
||||
if (!$gid) {
|
||||
$gid = self::by_name($uid, $name);
|
||||
}
|
||||
if (! ($gid && $uid && $member)) {
|
||||
if (!($gid && $uid && $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if ($r) {
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
return true;
|
||||
// You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
}
|
||||
else {
|
||||
else {
|
||||
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
@@ -210,15 +207,14 @@ class AccessList {
|
||||
dbesc($member)
|
||||
);
|
||||
}
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function members($uid, $gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
intval($gid),
|
||||
@@ -232,7 +228,7 @@ class AccessList {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_xchan($uid,$gid) {
|
||||
static function members_xchan($uid, $gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
@@ -248,99 +244,75 @@ class AccessList {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_profile_xchan($uid,$gid) {
|
||||
static function profile_members_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
foreach($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function select($uid, $options) {
|
||||
|
||||
$selected = $options['selected'] ?? '';
|
||||
$form_id = $options['form_id'] ?? 'accesslist_select';
|
||||
$label = $options['label'] ?? t('Select a privacy group');
|
||||
$before = $options['before'] ?? [];
|
||||
$after = $options['after'] ?? [];
|
||||
|
||||
|
||||
static function select($uid,$group = '') {
|
||||
|
||||
$grps = [];
|
||||
$o = '';
|
||||
|
||||
$grps[] = [
|
||||
'name' => '',
|
||||
'id' => '0',
|
||||
'selected' => false
|
||||
];
|
||||
|
||||
if ($before) {
|
||||
$grps[] = $before;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = [ 'name' => '', 'hash' => '0', 'selected' => '' ];
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$grps[] = [ 'name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '') ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_selection.tpl'), [
|
||||
'$label' => t('Add new connections to this access list'),
|
||||
'$groups' => $grps
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||
|
||||
$o = '';
|
||||
|
||||
$groups = [];
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = [];
|
||||
if ($cid) {
|
||||
$member_of = self::containing(local_channel(),$cid);
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
if ($edit) {
|
||||
$groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
|
||||
}
|
||||
else {
|
||||
$groupedit = null;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'],$member_of),
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$grps[] = [
|
||||
'name' => $rr['gname'],
|
||||
'id' => $rr['hash'],
|
||||
'selected' => ($selected == $rr['hash'])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_side.tpl'), [
|
||||
'$title' => t('Lists'),
|
||||
'$edittext' => t('Edit list'),
|
||||
'$createtext' => t('Create new list'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
]);
|
||||
|
||||
if ($after) {
|
||||
$grps[] = $after;
|
||||
}
|
||||
|
||||
logger('select: ' . print_r($grps,true), LOGGER_DATA);
|
||||
|
||||
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
|
||||
'$label' => $label,
|
||||
'$form_id' => $form_id,
|
||||
'$groups' => $grps
|
||||
));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
static function expand($g) {
|
||||
if (! (is_array($g) && count($g))) {
|
||||
if (!(is_array($g) && count($g))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -350,8 +322,8 @@ class AccessList {
|
||||
// private profile linked virtual groups
|
||||
|
||||
foreach ($g as $gv) {
|
||||
if (substr($gv,0,3) === 'vp.') {
|
||||
$profile_hash = substr($gv,3);
|
||||
if (substr($gv, 0, 3) === 'vp.') {
|
||||
$profile_hash = substr($gv, 3);
|
||||
if ($profile_hash) {
|
||||
$r = q("select abook_xchan from abook where abook_profile = '%s'",
|
||||
dbesc($profile_hash)
|
||||
@@ -366,10 +338,10 @@ class AccessList {
|
||||
else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
stringify_array_elms($x,true);
|
||||
stringify_array_elms($x, true);
|
||||
$groups = implode(',', $x);
|
||||
if ($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
@@ -383,9 +355,8 @@ class AccessList {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function member_of($c) {
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||
dbesc($c)
|
||||
);
|
||||
@@ -393,7 +364,7 @@ class AccessList {
|
||||
return $r;
|
||||
}
|
||||
|
||||
static function containing($uid,$c) {
|
||||
static function containing($uid, $c) {
|
||||
|
||||
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
@@ -405,7 +376,8 @@ class AccessList {
|
||||
foreach ($r as $rv)
|
||||
$ret[] = $rv['gid'];
|
||||
}
|
||||
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -116,6 +116,11 @@ class Activity {
|
||||
|
||||
$y = json_decode($x['body'], true);
|
||||
logger('returned: ' . json_encode($y, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOGGER_DEBUG);
|
||||
|
||||
if (ActivityStreams::is_an_actor($y['type'])) {
|
||||
XConfig::Set($y['id'], 'system', 'actor_record', $y);
|
||||
}
|
||||
|
||||
return json_decode($x['body'], true);
|
||||
}
|
||||
else {
|
||||
@@ -496,7 +501,7 @@ class Activity {
|
||||
|
||||
$ret['attributedTo'] = $i['author']['xchan_url'];
|
||||
|
||||
if ($i['id'] != $i['parent']) {
|
||||
if ($i['mid'] !== $i['parent_mid']) {
|
||||
$ret['inReplyTo'] = ((strpos($i['thr_parent'], 'http') === 0) ? $i['thr_parent'] : z_root() . '/item/' . urlencode($i['thr_parent']));
|
||||
}
|
||||
|
||||
@@ -529,6 +534,7 @@ class Activity {
|
||||
$top_level = (($i['mid'] === $i['parent_mid']) ? true : false);
|
||||
|
||||
if ($public) {
|
||||
|
||||
$ret['to'] = [ACTIVITY_PUBLIC_INBOX];
|
||||
$ret['cc'] = [z_root() . '/followers/' . substr($i['author']['xchan_addr'], 0, strpos($i['author']['xchan_addr'], '@'))];
|
||||
}
|
||||
@@ -602,10 +608,10 @@ class Activity {
|
||||
$ptr = [$ptr];
|
||||
}
|
||||
foreach ($ptr as $t) {
|
||||
if (!array_key_exists('type', $t))
|
||||
if (is_array($t) && !array_key_exists('type', $t))
|
||||
$t['type'] = 'Hashtag';
|
||||
|
||||
if (array_key_exists('href', $t) && array_key_exists('name', $t)) {
|
||||
if (is_array($t) && array_key_exists('href', $t) && array_key_exists('name', $t)) {
|
||||
switch ($t['type']) {
|
||||
case 'Hashtag':
|
||||
$ret[] = ['ttype' => TERM_HASHTAG, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'], 0, 1) === '#') ? substr($t['name'], 1) : $t['name'])];
|
||||
@@ -660,11 +666,11 @@ class Activity {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function encode_attachment($item) {
|
||||
static function encode_attachment($item, $iconfig = false) {
|
||||
|
||||
$ret = [];
|
||||
|
||||
if (array_key_exists('attach', $item)) {
|
||||
if (!$iconfig && array_key_exists('attach', $item)) {
|
||||
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
|
||||
if ($atts) {
|
||||
foreach ($atts as $att) {
|
||||
@@ -677,7 +683,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (array_key_exists('iconfig', $item) && is_array($item['iconfig'])) {
|
||||
if ($iconfig && array_key_exists('iconfig', $item) && is_array($item['iconfig'])) {
|
||||
foreach ($item['iconfig'] as $att) {
|
||||
if ($att['sharing']) {
|
||||
$value = ((is_string($att['v']) && preg_match('|^a:[0-9]+:{.*}$|s', $att['v'])) ? unserialize($att['v']) : $att['v']);
|
||||
@@ -869,7 +875,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if ($i['id'] != $i['parent']) {
|
||||
if ($i['mid'] !== $i['parent_mid']) {
|
||||
$reply = true;
|
||||
|
||||
// inReplyTo needs to be set in the activity for followup actions (Like, Dislike, Announce, etc.),
|
||||
@@ -886,10 +892,6 @@ class Activity {
|
||||
else
|
||||
return [];
|
||||
|
||||
if (strpos($i['body'], '[/share]') !== false) {
|
||||
$i['obj'] = null;
|
||||
}
|
||||
|
||||
if ($i['obj']) {
|
||||
if (!is_array($i['obj'])) {
|
||||
$i['obj'] = json_decode($i['obj'], true);
|
||||
@@ -899,8 +901,10 @@ class Activity {
|
||||
}
|
||||
|
||||
$obj = self::encode_object($i['obj']);
|
||||
if ($obj)
|
||||
|
||||
if ($obj) {
|
||||
$ret['object'] = $obj;
|
||||
}
|
||||
else
|
||||
return [];
|
||||
}
|
||||
@@ -932,6 +936,11 @@ class Activity {
|
||||
$ret['tag'] = $t;
|
||||
}
|
||||
|
||||
$a = self::encode_attachment($i, true);
|
||||
if ($a) {
|
||||
$ret['attachment'] = $a;
|
||||
}
|
||||
|
||||
// addressing madness
|
||||
|
||||
$public = (($i['item_private']) ? false : true);
|
||||
@@ -1042,7 +1051,7 @@ class Activity {
|
||||
$tmp = expand_acl($i['allow_cid']);
|
||||
$list = stringify_array($tmp, true);
|
||||
if ($list) {
|
||||
$details = q("select hubloc_id_url from hubloc where hubloc_hash in (" . $list . ") and hubloc_id_url != ''");
|
||||
$details = q("select hubloc_id_url from hubloc where hubloc_hash in (" . $list . ") and hubloc_id_url != '' and hubloc_deleted = 0");
|
||||
if ($details) {
|
||||
foreach ($details as $d) {
|
||||
$ret[] = $d['hubloc_id_url'];
|
||||
@@ -1089,10 +1098,11 @@ class Activity {
|
||||
$ret['type'] = 'Person';
|
||||
|
||||
if ($c) {
|
||||
$role = get_pconfig($c['channel_id'], 'system', 'permissions_role');
|
||||
if (strpos($role, 'forum') !== false) {
|
||||
if (get_pconfig($c['channel_id'], 'system', 'group_actor')) {
|
||||
$ret['type'] = 'Group';
|
||||
}
|
||||
|
||||
$ret['manuallyApprovesFollowers'] = ((get_pconfig($c['channel_id'], 'system', 'autoperms')) ? false : true);
|
||||
}
|
||||
|
||||
if ($c) {
|
||||
@@ -1144,9 +1154,10 @@ class Activity {
|
||||
$ret['url'] = $p['xchan_url'];
|
||||
|
||||
$ret['publicKey'] = [
|
||||
'id' => $p['xchan_url'],
|
||||
'owner' => $p['xchan_url'],
|
||||
'publicKeyPem' => $p['xchan_pubkey']
|
||||
'id' => $p['xchan_url'],
|
||||
'owner' => $p['xchan_url'],
|
||||
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
|
||||
'publicKeyPem' => $p['xchan_pubkey']
|
||||
];
|
||||
|
||||
if ($c) {
|
||||
@@ -1403,7 +1414,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
$x = PermissionRoles::role_perms('social');
|
||||
$x = PermissionRoles::role_perms('personal');
|
||||
$their_perms = Permissions::FilledPerms($x['perms_connect']);
|
||||
|
||||
if ($contact && $contact['abook_id']) {
|
||||
@@ -1520,7 +1531,7 @@ class Activity {
|
||||
'type' => NOTIFY_INTRO,
|
||||
'from_xchan' => $ret['xchan_hash'],
|
||||
'to_xchan' => $channel['channel_hash'],
|
||||
'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
|
||||
'link' => z_root() . '/connections#' . $new_connection[0]['abook_id'],
|
||||
]
|
||||
);
|
||||
|
||||
@@ -1554,9 +1565,9 @@ class Activity {
|
||||
/* If there is a default group for this channel and permissions are automatic, add this member to it */
|
||||
|
||||
if ($channel['channel_default_group'] && $automatic) {
|
||||
$g = Group::rec_byhash($channel['channel_id'], $channel['channel_default_group']);
|
||||
$g = AccessList::by_hash($channel['channel_id'], $channel['channel_default_group']);
|
||||
if ($g)
|
||||
Group::member_add($channel['channel_id'], '', $ret['xchan_hash'], $g['id']);
|
||||
AccessList::member_add($channel['channel_id'], '', $ret['xchan_hash'], $g['id']);
|
||||
}
|
||||
|
||||
|
||||
@@ -1589,6 +1600,25 @@ class Activity {
|
||||
return;
|
||||
}
|
||||
|
||||
public static function drop($channel, $observer, $act) {
|
||||
$r = q(
|
||||
"select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc((is_array($act->obj)) ? $act->obj['id'] : $act->obj),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($observer, [$r[0]['author_xchan'], $r[0]['owner_xchan']])) {
|
||||
drop_item($r[0]['id'], false);
|
||||
} elseif (in_array($act->actor['id'], [$r[0]['author_xchan'], $r[0]['owner_xchan']])) {
|
||||
drop_item($r[0]['id'], false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function actor_store($url, $person_obj, $force = false) {
|
||||
|
||||
if (!is_array($person_obj)) {
|
||||
@@ -1608,6 +1638,7 @@ class Activity {
|
||||
$ap_hubloc = null;
|
||||
|
||||
$hublocs = self::get_actor_hublocs($url);
|
||||
$has_zot_hubloc = false;
|
||||
|
||||
if ($hublocs) {
|
||||
foreach ($hublocs as $hub) {
|
||||
@@ -1615,6 +1646,7 @@ class Activity {
|
||||
$ap_hubloc = $hub;
|
||||
}
|
||||
if ($hub['hubloc_network'] === 'zot6') {
|
||||
$has_zot_hubloc = true;
|
||||
Libzot::update_cached_hubloc($hub);
|
||||
}
|
||||
}
|
||||
@@ -1638,16 +1670,18 @@ class Activity {
|
||||
return;
|
||||
}
|
||||
|
||||
$inbox = $person_obj['inbox'];
|
||||
$inbox = $person_obj['inbox'] ?? null;
|
||||
|
||||
// invalid identity
|
||||
// invalid AP identity
|
||||
|
||||
if (!$inbox || strpos($inbox, z_root()) !== false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// store the actor record in XConfig
|
||||
XConfig::Set($url, 'system', 'actor_record', $person_obj);
|
||||
|
||||
// we already store this in Activity::fetch()
|
||||
// XConfig::Set($url, 'system', 'actor_record', $person_obj);
|
||||
|
||||
$name = $person_obj['name'];
|
||||
if (!$name) {
|
||||
@@ -1704,7 +1738,7 @@ class Activity {
|
||||
|
||||
if ($links) {
|
||||
foreach ($links as $link) {
|
||||
if (array_key_exists('mediaType', $link) && $link['mediaType'] === 'text/html') {
|
||||
if (is_array($link) && array_key_exists('mediaType', $link) && $link['mediaType'] === 'text/html') {
|
||||
$profile = $link['href'];
|
||||
}
|
||||
}
|
||||
@@ -1749,7 +1783,7 @@ class Activity {
|
||||
// update existing xchan record
|
||||
q("update xchan set xchan_name = '%s', xchan_guid = '%s', xchan_pubkey = '%s', xchan_addr = '%s', xchan_network = 'activitypub', xchan_name_date = '%s' where xchan_hash = '%s'",
|
||||
dbesc(escape_tags($name)),
|
||||
dbesc(escape_tags($url)),
|
||||
dbesc($url),
|
||||
dbesc(escape_tags($pubkey)),
|
||||
dbesc(escape_tags($webfinger_addr)),
|
||||
dbescdate(datetime_convert()),
|
||||
@@ -1758,13 +1792,13 @@ class Activity {
|
||||
|
||||
// update existing hubloc record
|
||||
q("update hubloc set hubloc_guid = '%s', hubloc_addr = '%s', hubloc_network = 'activitypub', hubloc_url = '%s', hubloc_host = '%s', hubloc_callback = '%s', hubloc_updated = '%s', hubloc_id_url = '%s' where hubloc_hash = '%s'",
|
||||
dbesc(escape_tags($url)),
|
||||
dbesc($url),
|
||||
dbesc(escape_tags($webfinger_addr)),
|
||||
dbesc(escape_tags($baseurl)),
|
||||
dbesc(escape_tags($hostname)),
|
||||
dbesc(escape_tags($inbox)),
|
||||
dbesc($baseurl),
|
||||
dbesc($hostname),
|
||||
dbesc($inbox),
|
||||
dbescdate(datetime_convert()),
|
||||
dbesc(escape_tags($profile)),
|
||||
dbesc($profile),
|
||||
dbesc($url)
|
||||
);
|
||||
}
|
||||
@@ -1773,8 +1807,8 @@ class Activity {
|
||||
|
||||
xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => escape_tags($url),
|
||||
'xchan_guid' => escape_tags($url),
|
||||
'xchan_hash' => $url,
|
||||
'xchan_guid' => $url,
|
||||
'xchan_pubkey' => escape_tags($pubkey),
|
||||
'xchan_addr' => $webfinger_addr,
|
||||
'xchan_url' => escape_tags($profile),
|
||||
@@ -1786,16 +1820,16 @@ class Activity {
|
||||
|
||||
hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => escape_tags($url),
|
||||
'hubloc_hash' => escape_tags($url),
|
||||
'hubloc_guid' => $url,
|
||||
'hubloc_hash' => $url,
|
||||
'hubloc_addr' => $webfinger_addr,
|
||||
'hubloc_network' => 'activitypub',
|
||||
'hubloc_url' => escape_tags($baseurl),
|
||||
'hubloc_host' => escape_tags($hostname),
|
||||
'hubloc_callback' => escape_tags($inbox),
|
||||
'hubloc_url' => $baseurl,
|
||||
'hubloc_host' => $hostname,
|
||||
'hubloc_callback' => $inbox,
|
||||
'hubloc_updated' => datetime_convert(),
|
||||
'hubloc_primary' => 1,
|
||||
'hubloc_id_url' => escape_tags($profile)
|
||||
'hubloc_id_url' => $profile
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -1804,12 +1838,12 @@ class Activity {
|
||||
// Adding zot discovery urls to the actor record will cause federation to fail with the 20-30 projects which don't accept arrays in the url field.
|
||||
|
||||
$actor_protocols = self::get_actor_protocols($person_obj);
|
||||
if (in_array('zot6', $actor_protocols)) {
|
||||
if (!$has_zot_hubloc && in_array('zot6', $actor_protocols)) {
|
||||
$zx = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6'",
|
||||
dbesc($url)
|
||||
);
|
||||
if (!$zx && $webfinger_addr) {
|
||||
Master::Summon(['Gprobe', bin2hex($webfinger_addr)]);
|
||||
if (!$zx) {
|
||||
Master::Summon(['Gprobe', bin2hex($url)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1912,11 +1946,6 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
$abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($observer_hash),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
$content = self::get_content($act->obj);
|
||||
|
||||
if (!$content) {
|
||||
@@ -1994,15 +2023,23 @@ class Activity {
|
||||
}
|
||||
|
||||
if ($channel['channel_system']) {
|
||||
if (!MessageFilter::evaluate($s, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) {
|
||||
$incl = get_config('system','pubstream_incl');
|
||||
$excl = get_config('system','pubstream_excl');
|
||||
|
||||
if(($incl || $excl) && !MessageFilter::evaluate($s, $incl, $excl)) {
|
||||
logger('post is filtered');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$abook = q("select * from abook where (abook_xchan = '%s' OR abook_xchan = '%s') and abook_channel = %d ",
|
||||
dbesc($s['author_xchan']),
|
||||
dbesc($s['owner_xchan']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if ($abook) {
|
||||
if (!post_is_importable($s, $abook[0])) {
|
||||
if (!post_is_importable($channel['channel_id'], $s, $abook)) {
|
||||
logger('post is filtered');
|
||||
return;
|
||||
}
|
||||
@@ -2116,6 +2153,7 @@ class Activity {
|
||||
}
|
||||
|
||||
static function update_poll($item, $post) {
|
||||
|
||||
$multi = false;
|
||||
$mid = $post['mid'];
|
||||
$content = $post['title'];
|
||||
@@ -2200,7 +2238,8 @@ class Activity {
|
||||
dbesc(datetime_convert()),
|
||||
intval($item['id'])
|
||||
);
|
||||
Master::Summon(['Notifier', 'wall-new', $item['id']]);
|
||||
|
||||
Master::Summon(['Notifier', 'wall-new', $item['id'], $post['mid'] /* trick queueworker de-duplication */ ]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2209,6 +2248,21 @@ class Activity {
|
||||
|
||||
static function decode_note($act) {
|
||||
|
||||
$response_activity = false;
|
||||
|
||||
$s = [];
|
||||
|
||||
// These activities should have been handled separately in the Inbox module and should not be turned into posts
|
||||
|
||||
if (
|
||||
in_array($act->type, ['Follow', 'Accept', 'Reject', 'Create', 'Update']) &&
|
||||
is_array($act->obj) &&
|
||||
array_key_exists('type', $act->obj) &&
|
||||
($act->obj['type'] === 'Follow' || ActivityStreams::is_an_actor($act->obj['type']))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Within our family of projects, Follow/Unfollow of a thread is an internal activity which should not be transmitted,
|
||||
// hence if we receive it - ignore or reject it.
|
||||
// Unfollow is not defined by ActivityStreams, which prefers Undo->Follow.
|
||||
@@ -2218,22 +2272,31 @@ class Activity {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response_activity = false;
|
||||
if (!isset($act->actor['id'])) {
|
||||
logger('No actor!');
|
||||
return false;
|
||||
}
|
||||
|
||||
$s = [];
|
||||
// ensure we store the original actor
|
||||
self::actor_store($act->actor['id'], $act->actor);
|
||||
|
||||
$s['owner_xchan'] = $act->actor['id'];
|
||||
$s['author_xchan'] = $act->actor['id'];
|
||||
|
||||
if (is_array($act->obj)) {
|
||||
$content = self::get_content($act->obj);
|
||||
}
|
||||
|
||||
$s['owner_xchan'] = $act->actor['id'];
|
||||
$s['author_xchan'] = $act->actor['id'];
|
||||
$s['mid'] = ((is_array($act->obj) && isset($act->obj['id'])) ? $act->obj['id'] : $act->obj);
|
||||
|
||||
// ensure we store the original actor
|
||||
self::actor_store($act->actor['id'], $act->actor);
|
||||
if (!$s['mid']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Friendica sends the diaspora guid in a nonstandard field via AP
|
||||
// If no uuid is provided we will create an uuid v5 from the mid
|
||||
$s['uuid'] = ((is_array($act->obj) && isset($act->obj['diaspora:guid'])) ? $act->obj['diaspora:guid'] : uuid_from_url($s['mid']));
|
||||
|
||||
$s['mid'] = $act->obj['id'];
|
||||
$s['uuid'] = $act->obj['diaspora:guid'];
|
||||
$s['parent_mid'] = $act->parent_id;
|
||||
|
||||
if (array_key_exists('published', $act->data)) {
|
||||
@@ -2257,13 +2320,18 @@ class Activity {
|
||||
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
|
||||
}
|
||||
|
||||
if ($act->type === 'Invite' && is_array($act->obj) && array_key_exists('type', $act->obj) && $act->obj['type'] === 'Event') {
|
||||
$s['mid'] = $s['parent_mid'] = $act->id;
|
||||
}
|
||||
|
||||
if (ActivityStreams::is_response_activity($act->type)) {
|
||||
|
||||
$response_activity = true;
|
||||
|
||||
$s['mid'] = $act->id;
|
||||
// $s['parent_mid'] = $act->obj['id'];
|
||||
$s['uuid'] = $act->data['diaspora:guid'];
|
||||
$s['uuid'] = ((is_array($act->data) && isset($act->data['diaspora:guid'])) ? $act->data['diaspora:guid'] : uuid_from_url($s['mid']));
|
||||
|
||||
$s['parent_mid'] = ((is_array($act->obj) && isset($act->obj['id'])) ? $act->obj['id'] : $act->obj);
|
||||
|
||||
// over-ride the object timestamp with the activity
|
||||
|
||||
@@ -2276,8 +2344,8 @@ class Activity {
|
||||
}
|
||||
|
||||
$obj_actor = ((isset($act->obj['actor'])) ? $act->obj['actor'] : $act->get_actor('attributedTo', $act->obj));
|
||||
// ensure we store the original actor
|
||||
|
||||
// ensure we store the original actor
|
||||
self::actor_store($obj_actor['id'], $obj_actor);
|
||||
|
||||
$mention = self::get_actor_bbmention($obj_actor['id']);
|
||||
@@ -2306,13 +2374,41 @@ class Activity {
|
||||
}
|
||||
|
||||
if ($act->type === 'Announce') {
|
||||
$content['content'] = sprintf(t('🔁 Repeated %1$s\'s %2$s'), $mention, $act->obj['type']);
|
||||
$s['author_xchan'] = $obj_actor['id'];
|
||||
$s['mid'] = $act->obj['id'];
|
||||
$s['parent_mid'] = $act->obj['id'];
|
||||
}
|
||||
if ($act->type === 'emojiReaction') {
|
||||
$content['content'] = (($act->tgt && $act->tgt['type'] === 'Image') ? '[img=32x32]' . $act->tgt['url'] . '[/img]' : '&#x' . $act->tgt['name'] . ';');
|
||||
}
|
||||
}
|
||||
|
||||
$s['item_thread_top'] = 0;
|
||||
$s['comment_policy'] = 'authenticated';
|
||||
|
||||
if ($s['mid'] === $s['parent_mid']) {
|
||||
$s['item_thread_top'] = 1;
|
||||
|
||||
// it is a parent node - decode the comment policy info if present
|
||||
if (isset($act->obj['commentPolicy'])) {
|
||||
$until = strpos($act->obj['commentPolicy'], 'until=');
|
||||
if ($until !== false) {
|
||||
$s['comments_closed'] = datetime_convert('UTC', 'UTC', substr($act->obj['commentPolicy'], $until + 6));
|
||||
if ($s['comments_closed'] < datetime_convert()) {
|
||||
$s['nocomment'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$remainder = substr($act->obj['commentPolicy'], 0, (($until) ? $until : strlen($act->obj['commentPolicy'])));
|
||||
if ($remainder) {
|
||||
$s['comment_policy'] = $remainder;
|
||||
}
|
||||
if (!(isset($item['comment_policy']) && strlen($item['comment_policy']))) {
|
||||
$s['comment_policy'] = 'contacts';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!array_key_exists('created', $s))
|
||||
$s['created'] = datetime_convert();
|
||||
|
||||
@@ -2323,6 +2419,16 @@ class Activity {
|
||||
$s['summary'] = self::bb_content($content, 'summary');
|
||||
$s['body'] = ((self::bb_content($content, 'bbcode') && (!$response_activity)) ? self::bb_content($content, 'bbcode') : self::bb_content($content, 'content'));
|
||||
|
||||
if (isset($act->obj['quoteUrl'])) {
|
||||
$quote_bbcode = self::get_quote_bbcode($act->obj['quoteUrl']);
|
||||
|
||||
if ($s['body']) {
|
||||
$s['body'] .= "\r\n\r\n";
|
||||
}
|
||||
|
||||
$s['body'] .= $quote_bbcode;
|
||||
}
|
||||
|
||||
$s['verb'] = self::activity_decode_mapper($act->type);
|
||||
|
||||
// Mastodon does not provide update timestamps when updating poll tallies which means race conditions may occur here.
|
||||
@@ -2339,6 +2445,12 @@ class Activity {
|
||||
$s['obj_type'] = ACTIVITY_OBJ_COMMENT;
|
||||
}
|
||||
|
||||
$s['obj'] = $act->obj;
|
||||
if (is_array($s['obj']) && array_path_exists('actor/id', $s['obj'])) {
|
||||
$s['obj']['actor'] = $s['obj']['actor']['id'];
|
||||
}
|
||||
|
||||
/*
|
||||
$eventptr = null;
|
||||
|
||||
if ($act->obj['type'] === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event') {
|
||||
@@ -2359,19 +2471,19 @@ class Activity {
|
||||
$s['obj']['asld'] = $eventptr;
|
||||
$s['obj']['type'] = ACTIVITY_OBJ_EVENT;
|
||||
$s['obj']['id'] = $eventptr['id'];
|
||||
$s['obj']['title'] = $eventptr['name'];
|
||||
$s['obj']['title'] = html2plain($eventptr['name']);
|
||||
|
||||
if (strpos($act->obj['startTime'], 'Z'))
|
||||
$s['obj']['adjust'] = true;
|
||||
else
|
||||
$s['obj']['adjust'] = false;
|
||||
$s['obj']['adjust'] = true;
|
||||
|
||||
$s['obj']['dtstart'] = datetime_convert('UTC', 'UTC', $eventptr['startTime']);
|
||||
if ($act->obj['endTime'])
|
||||
$s['obj']['dtend'] = datetime_convert('UTC', 'UTC', $eventptr['endTime']);
|
||||
else
|
||||
$s['obj']['nofinish'] = true;
|
||||
$s['obj']['description'] = $eventptr['content'];
|
||||
$s['obj']['description'] = html2bbcode($eventptr['content']);
|
||||
|
||||
if (array_path_exists('location/content', $eventptr))
|
||||
$s['obj']['location'] = $eventptr['location']['content'];
|
||||
@@ -2380,6 +2492,7 @@ class Activity {
|
||||
else {
|
||||
$s['obj'] = $act->obj;
|
||||
}
|
||||
*/
|
||||
|
||||
$generator = $act->get_property_obj('generator');
|
||||
if ((!$generator) && (!$response_activity)) {
|
||||
@@ -2419,7 +2532,7 @@ class Activity {
|
||||
if (array_key_exists('type', $act->obj)) {
|
||||
|
||||
if ($act->obj['type'] === 'Note' && $s['attach']) {
|
||||
$s['body'] .= self::bb_attach($s['attach'], $s['body']);
|
||||
$s['body'] = self::bb_attach($s['attach'], $s['body']) . $s['body'];
|
||||
}
|
||||
|
||||
if ($act->obj['type'] === 'Question' && in_array($act->type, ['Create', 'Update'])) {
|
||||
@@ -2447,31 +2560,57 @@ class Activity {
|
||||
'video/webm'
|
||||
];
|
||||
|
||||
$mps = [];
|
||||
$mps = [];
|
||||
$poster = null;
|
||||
$ptr = null;
|
||||
|
||||
// try to find a poster to display on the video element
|
||||
|
||||
if (array_key_exists('icon',$act->obj)) {
|
||||
if (is_array($act->obj['icon'])) {
|
||||
if (array_key_exists(0,$act->obj['icon'])) {
|
||||
$ptr = $act->obj['icon'];
|
||||
}
|
||||
else {
|
||||
$ptr = [ $act->obj['icon'] ];
|
||||
}
|
||||
}
|
||||
if ($ptr) {
|
||||
foreach ($ptr as $foo) {
|
||||
if (is_array($foo) && array_key_exists('type',$foo) && $foo['type'] === 'Image' && is_string($foo['url'])) {
|
||||
$poster = $foo['url'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tag = (($poster) ? '[video poster="' . $poster . '"]' : '[video]' );
|
||||
$ptr = null;
|
||||
|
||||
if (array_key_exists('url', $act->obj)) {
|
||||
if (array_key_exists('url',$act->obj)) {
|
||||
if (is_array($act->obj['url'])) {
|
||||
if (array_key_exists(0, $act->obj['url'])) {
|
||||
if (array_key_exists(0,$act->obj['url'])) {
|
||||
$ptr = $act->obj['url'];
|
||||
}
|
||||
else {
|
||||
$ptr = [$act->obj['url']];
|
||||
$ptr = [ $act->obj['url'] ];
|
||||
}
|
||||
foreach ($ptr as $vurl) {
|
||||
// peertube uses the non-standard element name 'mimeType' here
|
||||
if (array_key_exists('mimeType', $vurl)) {
|
||||
if (in_array($vurl['mimeType'], $vtypes)) {
|
||||
if (!array_key_exists('width', $vurl)) {
|
||||
$vurl['width'] = 0;
|
||||
}
|
||||
$mps[] = $vurl;
|
||||
// handle peertube's weird url link tree if we find it here
|
||||
// 0 => html link, 1 => application/x-mpegURL with 'tag' set to an array of actual media links
|
||||
foreach ($ptr as $idex) {
|
||||
if (is_array($idex) && array_key_exists('mediaType',$idex)) {
|
||||
if ($idex['mediaType'] === 'application/x-mpegURL' && isset($idex['tag']) && is_array($idex['tag'])) {
|
||||
$ptr = $idex['tag'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
elseif (array_key_exists('mediaType', $vurl)) {
|
||||
}
|
||||
|
||||
foreach ($ptr as $vurl) {
|
||||
if (array_key_exists('mediaType',$vurl)) {
|
||||
if (in_array($vurl['mediaType'], $vtypes)) {
|
||||
if (!array_key_exists('width', $vurl)) {
|
||||
$vurl['width'] = 0;
|
||||
if (! array_key_exists('height',$vurl)) {
|
||||
$vurl['height'] = 0;
|
||||
}
|
||||
$mps[] = $vurl;
|
||||
}
|
||||
@@ -2479,17 +2618,18 @@ class Activity {
|
||||
}
|
||||
}
|
||||
if ($mps) {
|
||||
usort($mps, [__CLASS__, 'vid_sort']);
|
||||
usort($mps,[ '\Zotlabs\Lib\Activity', 'vid_sort' ]);
|
||||
foreach ($mps as $m) {
|
||||
if (intval($m['width']) < 500 && self::media_not_in_body($m['href'], $s['body'])) {
|
||||
$s['body'] .= "\n\n" . '[video]' . $m['href'] . '[/video]';
|
||||
if (intval($m['height']) < 500 && Activity::media_not_in_body($m['href'],$s['body'])) {
|
||||
$s['body'] = $tag . $m['href'] . '[/video]' . "\n\n" . $s['body'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'], $s['body'])) {
|
||||
$s['body'] .= "\n\n" . '[video]' . $act->obj['url'] . '[/video]';
|
||||
elseif (is_string($act->obj['url']) && Activity::media_not_in_body($act->obj['url'],$s['body'])) {
|
||||
$s['body'] = $tag . $act->obj['url'] . '[/video]' . "\n\n" . $s['body'];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2513,13 +2653,13 @@ class Activity {
|
||||
}
|
||||
foreach ($ptr as $vurl) {
|
||||
if (in_array($vurl['mediaType'], $atypes) && self::media_not_in_body($vurl['href'], $s['body'])) {
|
||||
$s['body'] .= "\n\n" . '[audio]' . $vurl['href'] . '[/audio]';
|
||||
$s['body'] = '[audio]' . $vurl['href'] . '[/audio]' . "\n\n" . $s['body'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (is_string($act->obj['url']) && self::media_not_in_body($act->obj['url'], $s['body'])) {
|
||||
$s['body'] .= "\n\n" . '[audio]' . $act->obj['url'] . '[/audio]';
|
||||
$s['body'] = '[audio]' . $act->obj['url'] . '[/audio]' . "\n\n" . $s['body'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2594,7 +2734,6 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (in_array($act->obj['type'], ['Note', 'Article', 'Page'])) {
|
||||
$ptr = null;
|
||||
|
||||
@@ -2637,13 +2776,78 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
|
||||
$ap_rawmsg = '';
|
||||
$diaspora_rawmsg = '';
|
||||
$raw_arr = [];
|
||||
|
||||
$parent = (($s['parent_mid'] && $s['parent_mid'] === $s['mid']) ? true : false);
|
||||
if ($parent) {
|
||||
$raw_arr = json_decode($act->raw, true);
|
||||
|
||||
// This is a zot6 packet and the raw activitypub or diaspora message json
|
||||
// is possibly available in the attachement.
|
||||
if (array_key_exists('signed', $raw_arr) && is_array($act->data['attachment'])) {
|
||||
foreach($act->data['attachment'] as $a) {
|
||||
if (
|
||||
isset($a['type']) && $a['type'] === 'PropertyValue' &&
|
||||
isset($a['name']) && $a['name'] === 'zot.activitypub.rawmsg' &&
|
||||
isset($a['value'])
|
||||
) {
|
||||
$ap_rawmsg = $a['value'];
|
||||
}
|
||||
if (
|
||||
isset($a['type']) && $a['type'] === 'PropertyValue' &&
|
||||
isset($a['name']) && $a['name'] === 'zot.diaspora.fields' &&
|
||||
isset($a['value'])
|
||||
) {
|
||||
$diaspora_rawmsg = $a['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// old style: can be removed after most hubs are on 7.0.2
|
||||
elseif (array_key_exists('signed', $raw_arr) && is_array($act->obj) && is_array($act->obj['attachment'])) {
|
||||
foreach($act->obj['attachment'] as $a) {
|
||||
if (
|
||||
isset($a['type']) && $a['type'] === 'PropertyValue' &&
|
||||
isset($a['name']) && $a['name'] === 'zot.activitypub.rawmsg' &&
|
||||
isset($a['value'])
|
||||
) {
|
||||
$ap_rawmsg = $a['value'];
|
||||
}
|
||||
|
||||
if (
|
||||
isset($a['type']) && $a['type'] === 'PropertyValue' &&
|
||||
isset($a['name']) && $a['name'] === 'zot.diaspora.fields' &&
|
||||
isset($a['value'])
|
||||
) {
|
||||
$diaspora_rawmsg = $a['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// catch the likes
|
||||
if (!$ap_rawmsg && $response_activity) {
|
||||
$ap_rawmsg = json_encode($act->data, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
// end old style
|
||||
|
||||
if (!$ap_rawmsg && array_key_exists('signed', $raw_arr)) {
|
||||
// zap
|
||||
$ap_rawmsg = json_encode($act->data, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
if ($ap_rawmsg) {
|
||||
set_iconfig($s, 'activitypub', 'rawmsg', $ap_rawmsg, 1);
|
||||
}
|
||||
elseif (!array_key_exists('signed', $raw_arr)) {
|
||||
set_iconfig($s, 'activitypub', 'rawmsg', $act->raw, 1);
|
||||
}
|
||||
|
||||
if ($diaspora_rawmsg) {
|
||||
set_iconfig($s, 'diaspora', 'fields', $diaspora_rawmsg, 1);
|
||||
}
|
||||
|
||||
set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
|
||||
|
||||
$hookinfo = [
|
||||
'act' => $act,
|
||||
's' => $s
|
||||
@@ -2667,12 +2871,6 @@ class Activity {
|
||||
return;
|
||||
}*/
|
||||
|
||||
// TODO: this his handled in pubcrawl atm.
|
||||
// very unpleasant and imperfect way of determining a Mastodon DM
|
||||
/*if ($act->raw_recips && array_key_exists('to',$act->raw_recips) && is_array($act->raw_recips['to']) && count($act->raw_recips['to']) === 1 && $act->raw_recips['to'][0] === channel_url($channel) && ! $act->raw_recips['cc']) {
|
||||
$item['item_private'] = 2;
|
||||
}*/
|
||||
|
||||
if ($item['parent_mid'] && $item['parent_mid'] !== $item['mid']) {
|
||||
$is_child_node = true;
|
||||
}
|
||||
@@ -2692,6 +2890,17 @@ class Activity {
|
||||
// set the owner to the owner of the parent
|
||||
$item['owner_xchan'] = $p[0]['owner_xchan'];
|
||||
|
||||
// quietly reject group comment boosts by group owner
|
||||
// (usually only sent via ActivityPub so groups will work on microblog platforms)
|
||||
// This catches those activities if they slipped in via a conversation fetch
|
||||
|
||||
if ($p[0]['parent_mid'] !== $item['parent_mid']) {
|
||||
if ($item['verb'] === 'Announce' && $item['author_xchan'] === $item['owner_xchan']) {
|
||||
logger('group boost activity by group owner rejected');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check permissions against the author, not the sender
|
||||
$allowed = perm_is_allowed($channel['channel_id'], $item['author_xchan'], 'post_comments');
|
||||
if ((!$allowed)/* && $permit_mentions*/) {
|
||||
@@ -2826,19 +3035,23 @@ class Activity {
|
||||
return;
|
||||
|
||||
if ($channel['channel_system']) {
|
||||
if (!MessageFilter::evaluate($item, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) {
|
||||
$incl = get_config('system','pubstream_incl');
|
||||
$excl = get_config('system','pubstream_excl');
|
||||
|
||||
if(($incl || $excl) && !MessageFilter::evaluate($item, $incl, $excl)) {
|
||||
logger('post is filtered');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($observer_hash),
|
||||
$abook = q("select * from abook where ( abook_xchan = '%s' OR abook_xchan = '%s') and abook_channel = %d ",
|
||||
dbesc($item['author_xchan']),
|
||||
dbesc($item['owner_xchan']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if ($abook) {
|
||||
if (!post_is_importable($item, $abook[0])) {
|
||||
if (!post_is_importable($channel['channel_id'], $item, $abook)) {
|
||||
logger('post is filtered');
|
||||
return;
|
||||
}
|
||||
@@ -2908,6 +3121,19 @@ class Activity {
|
||||
$item['thr_parent'] = $parent[0]['parent_mid'];
|
||||
}
|
||||
$item['parent_mid'] = $parent[0]['parent_mid'];
|
||||
//$item['item_private'] = $parent[0]['item_private'];
|
||||
|
||||
}
|
||||
|
||||
// An ugly and imperfect way to recognise a mastodon direct message
|
||||
if (
|
||||
$item['item_private'] === 1 &&
|
||||
!isset($act->raw_recips['cc']) &&
|
||||
is_array($act->raw_recips['to']) &&
|
||||
in_array(channel_url($channel), $act->raw_recips['to']) &&
|
||||
!in_array($act->actor['followers'], $act->raw_recips['to'])
|
||||
) {
|
||||
$item['item_private'] = 2;
|
||||
}
|
||||
|
||||
// TODO: not implemented
|
||||
@@ -2918,6 +3144,12 @@ class Activity {
|
||||
intval($item['uid'])
|
||||
);
|
||||
if ($r) {
|
||||
|
||||
// If we already have the item, dismiss its announce
|
||||
if ($act->type === 'Announce') {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($item['edited'] > $r[0]['edited']) {
|
||||
$item['id'] = $r[0]['id'];
|
||||
$x = item_store_update($item);
|
||||
@@ -2934,12 +3166,12 @@ class Activity {
|
||||
logger('topfetch', LOGGER_DEBUG);
|
||||
// if the thread owner is a connnection, we will already receive any additional comments to their posts
|
||||
// but if they are not we can try to fetch others in the background
|
||||
$x = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
$connected = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($parent[0]['owner_xchan'])
|
||||
);
|
||||
if (!$x) {
|
||||
if (!$connected) {
|
||||
// determine if the top-level post provides a replies collection
|
||||
if ($parent[0]['obj']) {
|
||||
$parent[0]['obj'] = json_decode($parent[0]['obj'], true);
|
||||
@@ -3191,6 +3423,7 @@ class Activity {
|
||||
|
||||
}
|
||||
|
||||
/* this is deprecated and not used anymore
|
||||
static function announce_note($channel, $observer_hash, $act) {
|
||||
|
||||
$s = [];
|
||||
@@ -3321,6 +3554,7 @@ class Activity {
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
static function like_note($channel, $observer_hash, $act) {
|
||||
|
||||
@@ -3541,7 +3775,49 @@ class Activity {
|
||||
$event['nofinish'] = true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
$eventptr = null;
|
||||
|
||||
if ($act->obj['type'] === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event') {
|
||||
$eventptr = $act->obj['object'];
|
||||
$s['mid'] = $s['parent_mid'] = $act->obj['id'];
|
||||
}
|
||||
|
||||
if ($act->obj['type'] === 'Event') {
|
||||
if ($act->type === 'Invite') {
|
||||
$s['mid'] = $s['parent_mid'] = $act->id;
|
||||
}
|
||||
$eventptr = $act->obj;
|
||||
}
|
||||
|
||||
if ($eventptr) {
|
||||
|
||||
$s['obj'] = [];
|
||||
$s['obj']['asld'] = $eventptr;
|
||||
$s['obj']['type'] = ACTIVITY_OBJ_EVENT;
|
||||
$s['obj']['id'] = $eventptr['id'];
|
||||
$s['obj']['title'] = html2plain($eventptr['name']);
|
||||
|
||||
if (strpos($act->obj['startTime'], 'Z'))
|
||||
$s['obj']['adjust'] = true;
|
||||
else
|
||||
$s['obj']['adjust'] = true;
|
||||
|
||||
$s['obj']['dtstart'] = datetime_convert('UTC', 'UTC', $eventptr['startTime']);
|
||||
if ($act->obj['endTime'])
|
||||
$s['obj']['dtend'] = datetime_convert('UTC', 'UTC', $eventptr['endTime']);
|
||||
else
|
||||
$s['obj']['nofinish'] = true;
|
||||
$s['obj']['description'] = html2bbcode($eventptr['content']);
|
||||
|
||||
if (array_path_exists('location/content', $eventptr))
|
||||
$s['obj']['location'] = $eventptr['location']['content'];
|
||||
|
||||
}
|
||||
else {
|
||||
$s['obj'] = $act->obj;
|
||||
}
|
||||
*/
|
||||
foreach (['name', 'summary', 'content'] as $a) {
|
||||
if (($x = self::get_textfield($act, $a)) !== false) {
|
||||
$content[$a] = $x;
|
||||
@@ -3626,7 +3902,10 @@ class Activity {
|
||||
}
|
||||
|
||||
static function get_cached_actor($id) {
|
||||
$actor = XConfig::Get($id, 'system', 'actor_record');
|
||||
|
||||
// remove any fragments like #main-key since these won't be present in our cached data
|
||||
$cache_url = ((strpos($id, '#')) ? substr($id, 0, strpos($id, '#')) : $id);
|
||||
$actor = XConfig::Get($cache_url, 'system', 'actor_record');
|
||||
|
||||
if ($actor) {
|
||||
return $actor;
|
||||
@@ -3635,7 +3914,7 @@ class Activity {
|
||||
// try other get_cached_actor providers (e.g. diaspora)
|
||||
$hookdata = [
|
||||
'id' => $id,
|
||||
'actor' => false
|
||||
'actor' => null
|
||||
];
|
||||
|
||||
call_hooks('get_cached_actor_provider', $hookdata);
|
||||
@@ -3695,7 +3974,7 @@ class Activity {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
foreach ($tag as $t) {
|
||||
foreach ($actor['tag'] as $t) {
|
||||
if ((isset($t['type']) && $t['type'] === 'PropertyValue') &&
|
||||
(isset($t['name']) && $t['name'] === 'Protocol') &&
|
||||
(isset($t['value']) && in_array($t['value'], ['zot6', 'activitypub', 'diaspora']))
|
||||
@@ -3706,4 +3985,32 @@ class Activity {
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function get_quote_bbcode($url) {
|
||||
|
||||
$ret = '';
|
||||
|
||||
$a = self::fetch($url);
|
||||
if ($a) {
|
||||
$act = new ActivityStreams($a);
|
||||
|
||||
if ($act->is_valid()) {
|
||||
$content = self::get_content($act->obj);
|
||||
|
||||
$ret .= "[share author='" . urlencode($act->actor['name']) .
|
||||
"' profile='" . $act->actor['id'] .
|
||||
"' avatar='" . $act->actor['icon']['url'] .
|
||||
"' link='" . $act->obj['id'] .
|
||||
"' auth='" . ((is_matrix_url($act->actor['id'])) ? 'true' : 'false') .
|
||||
"' posted='" . $act->obj['published'] .
|
||||
"' message_id='" . $act->obj['id'] .
|
||||
"']";
|
||||
$ret .= self::bb_content($content, 'content');
|
||||
$ret .= '[/share]';
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ class ActivityStreams {
|
||||
|
||||
public $raw = null;
|
||||
public $data = null;
|
||||
public $meta = null;
|
||||
public $valid = false;
|
||||
public $deleted = false;
|
||||
public $id = '';
|
||||
@@ -36,10 +37,14 @@ class ActivityStreams {
|
||||
*/
|
||||
function __construct($string) {
|
||||
|
||||
if(!$string)
|
||||
return;
|
||||
|
||||
$this->raw = $string;
|
||||
|
||||
if (is_array($string)) {
|
||||
$this->data = $string;
|
||||
$this->raw = json_encode($string, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
else {
|
||||
$this->data = json_decode($string, true);
|
||||
@@ -56,10 +61,10 @@ class ActivityStreams {
|
||||
if ($ret['signer']) {
|
||||
$saved = json_encode($this->data, JSON_UNESCAPED_SLASHES);
|
||||
$this->data = $tmp;
|
||||
$this->data['signer'] = $ret['signer'];
|
||||
$this->data['signed_data'] = $saved;
|
||||
$this->meta['signer'] = $ret['signer'];
|
||||
$this->meta['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$this->data['hubloc'] = $ret['hubloc'];
|
||||
$this->meta['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +92,7 @@ class ActivityStreams {
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if ($this->ldsig) {
|
||||
$this->signer = $this->get_compound_property('creator', $this->ldsig);
|
||||
$this->signer = $this->get_actor('creator', $this->ldsig);
|
||||
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
@@ -285,7 +290,7 @@ class ActivityStreams {
|
||||
if (!$s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,10 +348,10 @@ class ActivityStreams {
|
||||
if ($ret['signer']) {
|
||||
$saved = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$x = $tmp;
|
||||
$x['signer'] = $ret['signer'];
|
||||
$x['signed_data'] = $saved;
|
||||
$x['meta']['signer'] = $ret['signer'];
|
||||
$x['meta']['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$x['hubloc'] = $ret['hubloc'];
|
||||
$x['meta']['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,15 +422,19 @@ class ActivityStreams {
|
||||
|
||||
static function get_accept_header_string($channel = null) {
|
||||
|
||||
$ret = '';
|
||||
|
||||
$hookdata = [];
|
||||
if ($channel)
|
||||
$hookdata['channel'] = $channel;
|
||||
|
||||
$hookdata['data'] = 'application/x-zot-activity+json';
|
||||
$hookdata['data'] = ['application/x-zot-activity+json'];
|
||||
|
||||
call_hooks('get_accept_header_string', $hookdata);
|
||||
|
||||
return $hookdata['data'];
|
||||
$ret = implode(', ', $hookdata['data']);
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -67,17 +67,15 @@ class Apps {
|
||||
static public function get_base_apps() {
|
||||
$x = get_config('system','base_apps',[
|
||||
'Connections',
|
||||
'Contact Roles',
|
||||
'Network',
|
||||
'Settings',
|
||||
'Files',
|
||||
'Channel Home',
|
||||
'View Profile',
|
||||
'Channel',
|
||||
'Photos',
|
||||
'Calendar',
|
||||
'Directory',
|
||||
'Search',
|
||||
'Help',
|
||||
'Profile Photo',
|
||||
'HQ',
|
||||
'Post'
|
||||
]);
|
||||
@@ -346,7 +344,7 @@ class Apps {
|
||||
'Files' => t('Files'),
|
||||
'Webpages' => t('Webpages'),
|
||||
'Wiki' => t('Wiki'),
|
||||
'Channel Home' => t('Channel Home'),
|
||||
'Channel' => t('Channel'),
|
||||
'View Profile' => t('View Profile'),
|
||||
'Photos' => t('Photos'),
|
||||
'Calendar' => t('Calendar'),
|
||||
@@ -377,10 +375,10 @@ class Apps {
|
||||
'OAuth Apps Manager' => t('OAuth Apps Manager'),
|
||||
'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'),
|
||||
'PDL Editor' => t('PDL Editor'),
|
||||
'Permission Categories' => t('Permission Categories'),
|
||||
'Contact Roles' => t('Contact Roles'),
|
||||
'Public Stream' => t('Public Stream'),
|
||||
'My Chatrooms' => t('My Chatrooms'),
|
||||
'Channel Export' => t('Channel Export'),
|
||||
'Channel Export' => t('Channel Export')
|
||||
);
|
||||
|
||||
if(array_key_exists('name',$arr)) {
|
||||
@@ -428,7 +426,7 @@ class Apps {
|
||||
|
||||
self::translate_system_apps($papp);
|
||||
|
||||
if(trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
|
||||
if(isset($papp['plugin']) && trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin']))))
|
||||
return '';
|
||||
|
||||
$papp['papp'] = self::papp_encode($papp);
|
||||
|
||||
@@ -261,7 +261,8 @@ class Connect {
|
||||
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_instance' => (($singleton) ? z_root() : '')
|
||||
'abook_instance' => (($singleton) ? z_root() : ''),
|
||||
'abook_role' => get_pconfig($uid, 'system', 'default_permcat', 'default')
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -300,7 +301,7 @@ class Connect {
|
||||
/** If there is a default group for this channel, add this connection to it */
|
||||
|
||||
if ($default_group) {
|
||||
$g = AccessList::rec_byhash($uid,$default_group);
|
||||
$g = AccessList::by_hash($uid,$default_group);
|
||||
if ($g) {
|
||||
AccessList::member_add($uid,'',$xchan_hash,$g['id']);
|
||||
}
|
||||
|
||||
@@ -87,6 +87,10 @@ class Crypto {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$alg) {
|
||||
$alg = 'sha256';
|
||||
}
|
||||
|
||||
try {
|
||||
$verify = openssl_verify($data, $sig, $key, $alg);
|
||||
} catch (Exception $e) {
|
||||
|
||||
@@ -256,7 +256,7 @@ class Enotify {
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
if (array_key_exists('item',$params) && (! activity_match($params['item']['verb'],ACTIVITY_LIKE))) {
|
||||
if (array_key_exists('item',$params) && activity_match($params['item']['verb'],ACTIVITY_LIKE)) {
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
pop_lang();
|
||||
@@ -845,6 +845,10 @@ class Enotify {
|
||||
// convert this logic into a json array just like the system notifications
|
||||
|
||||
$who = (($item['verb'] === ACTIVITY_SHARE) ? 'owner' : 'author');
|
||||
$body = html2plain(bbcode($item['body'], ['drop_media']), 75, true);
|
||||
if ($body) {
|
||||
$body = htmlentities($body, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
|
||||
$x = array(
|
||||
'notify_link' => $item['llink'],
|
||||
@@ -858,7 +862,7 @@ class Enotify {
|
||||
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? gen_link_id($item['thr_parent']) : gen_link_id($item['mid'])),
|
||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||
'message' => bbcode(escape_tags($itemem_text)),
|
||||
'body' => htmlentities(html2plain(bbcode($item['body'], ['drop_media', true]), 75, true), ENT_QUOTES, 'UTF-8', false),
|
||||
'body' => $body,
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'uid' => $item['uid'],
|
||||
@@ -902,7 +906,7 @@ class Enotify {
|
||||
static public function format_intros($rr) {
|
||||
|
||||
return [
|
||||
'notify_link' => z_root() . '/connections/ifpending',
|
||||
'notify_link' => z_root() . '/connections#' . $rr['abook_id'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'addr' => $rr['xchan_addr'],
|
||||
'url' => $rr['xchan_url'],
|
||||
|
||||
@@ -1,405 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
|
||||
class Group {
|
||||
|
||||
static function add($uid,$name,$public = 0) {
|
||||
|
||||
$ret = false;
|
||||
if(x($uid) && x($name)) {
|
||||
$r = self::byname($uid,$name); // check for dups
|
||||
if($r !== false) {
|
||||
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a group which we once deleted
|
||||
// all the old members are gone, but the group remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead group, but old content which
|
||||
// was restricted to this group may now be seen by the new group members.
|
||||
|
||||
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice( t('A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
$dups = false;
|
||||
$hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
|
||||
|
||||
$r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
|
||||
if($r)
|
||||
$dups = true;
|
||||
} while($dups == true);
|
||||
|
||||
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||
VALUES( '%s', %d, %d, '%s' ) ",
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
intval($public),
|
||||
dbesc($name)
|
||||
);
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function remove($uid,$name) {
|
||||
$ret = false;
|
||||
if(x($uid) && x($name)) {
|
||||
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
}
|
||||
|
||||
if(! $group_id)
|
||||
return false;
|
||||
|
||||
// remove group from default posting lists
|
||||
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
$user_info = $r[0];
|
||||
$change = false;
|
||||
|
||||
if($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
}
|
||||
if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
}
|
||||
if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
}
|
||||
|
||||
if($change) {
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
WHERE channel_id = %d",
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
dbesc($user_info['channel_deny_gid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all members
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
|
||||
intval($uid),
|
||||
intval($group_id)
|
||||
);
|
||||
|
||||
// remove group
|
||||
$r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
$ret = $r;
|
||||
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function byname($uid,$name) {
|
||||
if((! $uid) || (! strlen($name)))
|
||||
return false;
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if($r)
|
||||
return $r[0]['id'];
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function rec_byhash($uid,$hash) {
|
||||
if((! $uid) || (! strlen($hash)))
|
||||
return false;
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r)
|
||||
return $r[0];
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function member_remove($uid,$name,$member) {
|
||||
$gid = self::byname($uid,$name);
|
||||
if(! $gid)
|
||||
return false;
|
||||
if(! ( $uid && $gid && $member))
|
||||
return false;
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function member_add($uid,$name,$member,$gid = 0) {
|
||||
if(! $gid)
|
||||
$gid = self::byname($uid,$name);
|
||||
if((! $gid) || (! $uid) || (! $member))
|
||||
return false;
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if($r)
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
if(! $r)
|
||||
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function members($gid) {
|
||||
$ret = array();
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||
intval($gid),
|
||||
intval(local_channel()),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r)
|
||||
$ret = $r;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_xchan($gid) {
|
||||
$ret = [];
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
intval($gid),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_profile_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
|
||||
if(intval($gid)) {
|
||||
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static function select($uid,$group = '') {
|
||||
|
||||
$grps = [];
|
||||
$o = '';
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
|
||||
}
|
||||
|
||||
}
|
||||
logger('select: ' . print_r($grps,true), LOGGER_DATA);
|
||||
|
||||
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
|
||||
'$label' => t('Add new connections to this privacy group'),
|
||||
'$groups' => $grps
|
||||
));
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||
|
||||
$o = '';
|
||||
|
||||
if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = array();
|
||||
if($cid) {
|
||||
$member_of = self::containing(local_channel(),$cid);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
if ($edit) {
|
||||
$groupedit = [ 'href' => "group/".$rr['id'], 'title' => t('edit') ];
|
||||
}
|
||||
else {
|
||||
$groupedit = null;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'],$member_of),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$tpl = get_markup_template("group_side.tpl");
|
||||
$o = replace_macros($tpl, array(
|
||||
'$title' => t('Privacy Groups'),
|
||||
'$edittext' => t('Edit group'),
|
||||
'$createtext' => t('Add privacy group'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
static function expand($g) {
|
||||
if(! (is_array($g) && count($g)))
|
||||
return array();
|
||||
|
||||
$ret = [];
|
||||
$x = [];
|
||||
|
||||
// private profile linked virtual groups
|
||||
|
||||
foreach($g as $gv) {
|
||||
if(substr($gv,0,3) === 'vp.') {
|
||||
$profile_hash = substr($gv,3);
|
||||
if($profile_hash) {
|
||||
$r = q("select abook_xchan from abook where abook_profile = '%s'",
|
||||
dbesc($profile_hash)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$ret[] = $rv['abook_xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
|
||||
if($x) {
|
||||
stringify_array_elms($x,true);
|
||||
$groups = implode(',', $x);
|
||||
if($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function member_of($c) {
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
return $r;
|
||||
|
||||
}
|
||||
|
||||
static function containing($uid,$c) {
|
||||
|
||||
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
$ret = array();
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
$ret[] = $rr['gid'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -75,22 +75,23 @@ class LDSignatures {
|
||||
}
|
||||
|
||||
static function hash($obj) {
|
||||
|
||||
return hash('sha256',self::normalise($obj));
|
||||
return hash('sha256', self::normalise($obj));
|
||||
}
|
||||
|
||||
static function normalise($data) {
|
||||
$ret = '';
|
||||
|
||||
if(is_string($data)) {
|
||||
$data = json_decode($data);
|
||||
}
|
||||
|
||||
if(! is_object($data))
|
||||
return '';
|
||||
return $ret;
|
||||
|
||||
jsonld_set_document_loader('jsonld_document_loader');
|
||||
|
||||
try {
|
||||
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
$ret = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Don't log the exception - this can exhaust memory
|
||||
@@ -98,7 +99,7 @@ class LDSignatures {
|
||||
logger('normalise error: ' . print_r($data,true));
|
||||
}
|
||||
|
||||
return $d;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function salmon_sign($data,$channel) {
|
||||
|
||||
@@ -230,8 +230,35 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('config', $arr) && is_array($arr['config']) && count($arr['config'])) {
|
||||
foreach ($arr['config'] as $cat => $k) {
|
||||
foreach ($arr['config'][$cat] as $k => $v)
|
||||
set_pconfig($channel['channel_id'], $cat, $k, $v);
|
||||
$pconfig_updated = [];
|
||||
|
||||
foreach($arr['config'][$cat] as $k => $v) {
|
||||
if ($cat === 'hz_delpconfig' && strpos($k, 'b64.') === 0) {
|
||||
$delpconfig = explode(':', unpack_link_id($k));
|
||||
|
||||
// delete the provided pconfig
|
||||
del_pconfig($channel['channel_id'], $delpconfig[0], $delpconfig[1], $v);
|
||||
|
||||
// delete the messenger pconfig
|
||||
del_pconfig($channel['channel_id'], 'hz_delpconfig', $k);
|
||||
}
|
||||
|
||||
if (strpos($k,'pcfgud:') === 0) {
|
||||
$realk = substr($k,7);
|
||||
$pconfig_updated[$realk] = $v;
|
||||
unset($arr['config'][$cat][$k]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($arr['config'][$cat] as $k => $v) {
|
||||
if (!isset($pconfig_updated[$k])) {
|
||||
$pconfig_updated[$k] = NULL;
|
||||
}
|
||||
|
||||
if ($cat !== 'hz_delpconfig') {
|
||||
set_pconfig($channel['channel_id'],$cat,$k,$v,$pconfig_updated[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,19 +411,42 @@ class Libsync {
|
||||
// This relies on the undocumented behaviour that red sites send xchan info with the abook
|
||||
// and import_author_xchan will look them up on all federated networks
|
||||
|
||||
if ($abook['abook_xchan'] && $abook['xchan_addr']) {
|
||||
$found = false;
|
||||
if ($abook['abook_xchan'] && $abook['xchan_addr'] && (! in_array($abook['xchan_network'], [ 'token', 'unknown' ]))) {
|
||||
$h = Libzot::get_hublocs($abook['abook_xchan']);
|
||||
if (!$h) {
|
||||
if ($h) {
|
||||
$found = true;
|
||||
}
|
||||
else {
|
||||
$xhash = import_author_xchan(encode_item_xchan($abook));
|
||||
if (!$xhash) {
|
||||
if ($xhash) {
|
||||
$found = true;
|
||||
}
|
||||
else {
|
||||
logger('Import of ' . $abook['xchan_addr'] . ' failed.');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found && !in_array($abook['xchan_network'], ['zot6', 'activitypub', 'diaspora'])) {
|
||||
// just import the record.
|
||||
$xc = [];
|
||||
foreach ($abook as $k => $v) {
|
||||
if (strpos($k,'xchan_') === 0) {
|
||||
$xc[$k] = $v;
|
||||
}
|
||||
}
|
||||
$r = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($xc['xchan_hash'])
|
||||
);
|
||||
if (! $r) {
|
||||
xchan_store_lowlevel($xc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ($abook as $k => $v) {
|
||||
if (in_array($k, $disallowed) || (strpos($k, 'abook') !== 0)) {
|
||||
if (in_array($k, $disallowed) || (strpos($k, 'abook_') !== 0)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($k, $fields)) {
|
||||
@@ -410,6 +460,13 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('abook_instance', $clean) && $clean['abook_instance'] && strpos($clean['abook_instance'], z_root()) === false) {
|
||||
$clean['abook_not_here'] = 1;
|
||||
|
||||
// guest pass or access token - don't try to probe since it is one-way
|
||||
// we are relying on the undocumented behaviour that the abook record also contains the xchan
|
||||
if ($abook['xchan_network'] === 'token') {
|
||||
$clean['abook_instance'] .= ',';
|
||||
$clean['abook_instance'] .= z_root();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -768,14 +825,13 @@ class Libsync {
|
||||
|
||||
// match as many fields as possible in case anything at all changed.
|
||||
|
||||
$r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_site_id = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
|
||||
$r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
|
||||
dbesc($sender['hash']),
|
||||
dbesc($sender['id']),
|
||||
dbesc($sender['id_sig']),
|
||||
dbesc($location['id_url']),
|
||||
dbesc($location['url']),
|
||||
dbesc($location['url_sig']),
|
||||
dbesc($location['site_id']),
|
||||
dbesc($location['host']),
|
||||
dbesc($location['address']),
|
||||
dbesc($location['callback']),
|
||||
@@ -784,6 +840,15 @@ class Libsync {
|
||||
if ($r) {
|
||||
logger('Hub exists: ' . $location['url'], LOGGER_DEBUG);
|
||||
|
||||
// generate a new hubloc_site_id if it's wrong due to historical bugs 2021-11-30
|
||||
|
||||
if ($r[0]['hubloc_site_id'] !== $location['site_id']) {
|
||||
q("update hubloc set hubloc_site_id = '%s' where hubloc_id = %d",
|
||||
dbesc(Libzot::make_xchan_hash($location['url'], $location['sitekey'])),
|
||||
intval($r[0]['hubloc_id'])
|
||||
);
|
||||
}
|
||||
|
||||
// update connection timestamp if this is the site we're talking to
|
||||
// This only happens when called from import_xchan
|
||||
|
||||
|
||||
@@ -386,9 +386,10 @@ class Libzot {
|
||||
else {
|
||||
|
||||
$p = Permissions::connect_perms($channel['channel_id']);
|
||||
$my_perms = $p['perms'];
|
||||
|
||||
$my_perms = $p['perms'];
|
||||
$automatic = $p['automatic'];
|
||||
$role = (($automatic) ? $p['role'] : '');
|
||||
|
||||
// new connection
|
||||
|
||||
@@ -410,7 +411,8 @@ class Libzot {
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_dob' => $next_birthday,
|
||||
'abook_pending' => intval(($automatic) ? 0 : 1)
|
||||
'abook_pending' => intval(($automatic) ? 0 : 1),
|
||||
'abook_role' => $role
|
||||
]
|
||||
);
|
||||
|
||||
@@ -435,7 +437,7 @@ class Libzot {
|
||||
'type' => NOTIFY_INTRO,
|
||||
'from_xchan' => $x['hash'],
|
||||
'to_xchan' => $channel['channel_hash'],
|
||||
'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
|
||||
'link' => z_root() . '/connections#' . $new_connection[0]['abook_id']
|
||||
]
|
||||
);
|
||||
|
||||
@@ -453,10 +455,10 @@ class Libzot {
|
||||
$default_group = $channel['channel_default_group'];
|
||||
|
||||
if ($default_group) {
|
||||
$g = Group::rec_byhash($channel['channel_id'], $default_group);
|
||||
$g = AccessList::by_hash($channel['channel_id'], $default_group);
|
||||
|
||||
if ($g) {
|
||||
Group::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
|
||||
AccessList::member_add($channel['channel_id'], '', $x['hash'], $g['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -674,6 +676,10 @@ class Libzot {
|
||||
|
||||
logger('import_xchan: ' . $xchan_hash, LOGGER_DEBUG);
|
||||
|
||||
if (isset($arr['signing_algorithm']) && $arr['signing_algorithm']) {
|
||||
set_xconfig($xchan_hash, 'system', 'signing_algorithm', $arr['signing_algorithm']);
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($xchan_hash)
|
||||
);
|
||||
@@ -1001,7 +1007,7 @@ class Libzot {
|
||||
|
||||
$x = Crypto::unencapsulate($x, get_config('system', 'prvkey'));
|
||||
|
||||
if (!is_array($x)) {
|
||||
if ($x && !is_array($x)) {
|
||||
$x = json_decode($x, true);
|
||||
}
|
||||
|
||||
@@ -1143,6 +1149,7 @@ class Libzot {
|
||||
if ($env['encoding'] === 'activitystreams') {
|
||||
|
||||
$AS = new ActivityStreams($data);
|
||||
|
||||
if (!$AS->is_valid()) {
|
||||
logger('Activity rejected: ' . print_r($data, true));
|
||||
return;
|
||||
@@ -1158,8 +1165,6 @@ class Libzot {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$deliveries = null;
|
||||
|
||||
if (array_key_exists('recipients', $env) && count($env['recipients'])) {
|
||||
@@ -1217,7 +1222,7 @@ class Libzot {
|
||||
|
||||
if (in_array($env['type'], ['activity', 'response'])) {
|
||||
|
||||
if(!isset($AS->actor['id'])) {
|
||||
if(empty($AS->actor['id'])) {
|
||||
logger('No actor id!');
|
||||
return;
|
||||
}
|
||||
@@ -1226,6 +1231,16 @@ class Libzot {
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
// Author is unknown to this site. Perform channel discovery and try again.
|
||||
$z = discover_by_webbie($AS->actor['id']);
|
||||
if ($z) {
|
||||
$r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s'",
|
||||
dbesc($AS->actor['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
$r = self::zot_record_preferred($r);
|
||||
$arr['author_xchan'] = $r['hubloc_hash'];
|
||||
@@ -1279,25 +1294,14 @@ class Libzot {
|
||||
|
||||
if ($AS->data['hubloc']) {
|
||||
$arr['item_verified'] = true;
|
||||
|
||||
if (!array_key_exists('comment_policy', $arr)) {
|
||||
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
|
||||
// Anything else we'll say is zot - which could have a range of project names
|
||||
$s = q("select site_project from site where site_url = '%s' limit 1",
|
||||
dbesc($r[0]['hubloc_url'])
|
||||
);
|
||||
|
||||
if ((!$s) || (in_array($s[0]['site_project'], ['', 'osada']))) {
|
||||
$arr['comment_policy'] = 'authenticated';
|
||||
}
|
||||
else {
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($AS->data['signed_data']) {
|
||||
IConfig::Set($arr, 'activitypub', 'signed_data', $AS->data['signed_data'], false);
|
||||
if (!array_key_exists('comment_policy', $arr)) {
|
||||
$arr['comment_policy'] = 'authenticated';
|
||||
}
|
||||
|
||||
if ($AS->meta['signed_data']) {
|
||||
IConfig::Set($arr, 'activitypub', 'signed_data', $AS->meta['signed_data'], false);
|
||||
}
|
||||
|
||||
logger('Activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
|
||||
@@ -1568,7 +1572,11 @@ class Libzot {
|
||||
$local_public = false;
|
||||
continue;
|
||||
}
|
||||
if (!MessageFilter::evaluate($arr, get_config('system', 'pubstream_incl'), get_config('system', 'pubstream_excl'))) {
|
||||
|
||||
$incl = get_config('system','pubstream_incl');
|
||||
$excl = get_config('system','pubstream_excl');
|
||||
|
||||
if(($incl || $excl) && !MessageFilter::evaluate($arr, $incl, $excl)) {
|
||||
$local_public = false;
|
||||
continue;
|
||||
}
|
||||
@@ -1592,6 +1600,7 @@ class Libzot {
|
||||
|
||||
if ((!$tag_delivery) && (!$local_public)) {
|
||||
$allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
|
||||
|
||||
if ((!$allowed) && $perm === 'post_comments') {
|
||||
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
@@ -1742,11 +1751,13 @@ class Libzot {
|
||||
}
|
||||
}
|
||||
|
||||
$ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
// This is used to fetch allow/deny rules if either the sender
|
||||
// or owner is a connection. post_is_importable() evaluates all of them
|
||||
$abook = q("select * from abook where abook_channel = %d and ( abook_xchan = '%s' OR abook_xchan = '%s' )",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($arr['owner_xchan'])
|
||||
dbesc($arr['owner_xchan']),
|
||||
dbesc($arr['author_xchan'])
|
||||
);
|
||||
$abook = (($ab) ? $ab[0] : null);
|
||||
|
||||
if (intval($arr['item_deleted'])) {
|
||||
|
||||
@@ -1797,17 +1808,18 @@ class Libzot {
|
||||
elseif ($arr['edited'] > $r[0]['edited']) {
|
||||
$arr['id'] = $r[0]['id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
if (($arr['mid'] == $arr['parent_mid']) && (!post_is_importable($arr, $abook))) {
|
||||
$DR->update('update ignored');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
else {
|
||||
$item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
|
||||
$DR->update('updated');
|
||||
$result[] = $DR->get();
|
||||
if (!$relay)
|
||||
add_source_route($item_id, $sender);
|
||||
}
|
||||
|
||||
if (post_is_importable($channel['channel_id'], $arr, $abook)) {
|
||||
$item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
|
||||
$DR->update('updated');
|
||||
$result[] = $DR->get();
|
||||
if (!$relay) {
|
||||
add_source_route($item_id, $sender);
|
||||
}
|
||||
} else {
|
||||
$DR->update('update ignored');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$DR->update('update ignored');
|
||||
@@ -1837,20 +1849,29 @@ class Libzot {
|
||||
|
||||
$item_id = 0;
|
||||
|
||||
if (($arr['mid'] == $arr['parent_mid']) && (!post_is_importable($arr, $abook))) {
|
||||
$DR->update('post ignored');
|
||||
$result[] = $DR->get();
|
||||
$maxlen = get_max_import_size();
|
||||
|
||||
if ($maxlen && mb_strlen($arr['body']) > $maxlen) {
|
||||
$arr['body'] = mb_substr($arr['body'], 0, $maxlen, 'UTF-8');
|
||||
logger('message length exceeds max_import_size: truncated');
|
||||
}
|
||||
else {
|
||||
|
||||
if ($maxlen && mb_strlen($arr['summary']) > $maxlen) {
|
||||
$arr['summary'] = mb_substr($arr['summary'], 0, $maxlen, 'UTF-8');
|
||||
logger('message summary length exceeds max_import_size: truncated');
|
||||
}
|
||||
|
||||
if (post_is_importable($arr['uid'], $arr, $abook)) {
|
||||
$item_result = item_store($arr);
|
||||
if ($item_result['success']) {
|
||||
$item_id = $item_result['item_id'];
|
||||
$parr = [
|
||||
$parr = [
|
||||
'item_id' => $item_id,
|
||||
'item' => $arr,
|
||||
'sender' => $sender,
|
||||
'item' => $arr,
|
||||
'sender' => $sender,
|
||||
'channel' => $channel
|
||||
];
|
||||
|
||||
/**
|
||||
* @hooks activity_received
|
||||
* Called when an activity (post, comment, like, etc.) has been received from a zot source.
|
||||
@@ -1860,13 +1881,19 @@ class Libzot {
|
||||
* * \e array \b channel
|
||||
*/
|
||||
call_hooks('activity_received', $parr);
|
||||
|
||||
// don't add a source route if it's a relay or later recipients will get a route mismatch
|
||||
if (!$relay)
|
||||
if (!$relay) {
|
||||
add_source_route($item_id, $sender);
|
||||
}
|
||||
}
|
||||
$DR->update(($item_id) ? 'posted' : 'storage failed: ' . $item_result['message']);
|
||||
$result[] = $DR->get();
|
||||
} else {
|
||||
$DR->update('post ignored');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// preserve conversations with which you are involved from expiration
|
||||
@@ -1925,6 +1952,7 @@ class Libzot {
|
||||
dbesc($a['signature']['signer'])
|
||||
);
|
||||
|
||||
|
||||
foreach ($items as $activity) {
|
||||
|
||||
$AS = new ActivityStreams($activity);
|
||||
@@ -1986,9 +2014,9 @@ class Libzot {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
|
||||
if ($AS->data['signed_data']) {
|
||||
IConfig::Set($arr, 'activitypub', 'signed_data', $AS->data['signed_data'], false);
|
||||
$j = json_decode($AS->data['signed_data'], true);
|
||||
if ($AS->meta['signed_data']) {
|
||||
IConfig::Set($arr, 'activitypub', 'signed_data', $AS->meta['signed_data'], false);
|
||||
$j = json_decode($AS->meta['signed_data'], true);
|
||||
if ($j) {
|
||||
IConfig::Set($arr, 'activitypub', 'rawmsg', json_encode(JSalmon::unpack($j['data'])), true);
|
||||
}
|
||||
@@ -2480,14 +2508,14 @@ class Libzot {
|
||||
$access_policy = ACCESS_PRIVATE;
|
||||
}
|
||||
|
||||
$directory_url = htmlspecialchars($arr['directory_url'], ENT_COMPAT, 'UTF-8', false);
|
||||
$url = htmlspecialchars(strtolower($arr['url']), ENT_COMPAT, 'UTF-8', false);
|
||||
$sellpage = htmlspecialchars($arr['sellpage'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_location = htmlspecialchars($arr['location'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_realm = htmlspecialchars($arr['realm'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_project = htmlspecialchars($arr['project'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_crypto = ((array_key_exists('encryption', $arr) && is_array($arr['encryption'])) ? htmlspecialchars(implode(',', $arr['encryption']), ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$site_version = ((array_key_exists('version', $arr)) ? htmlspecialchars($arr['version'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$directory_url = htmlspecialchars((string)$arr['directory_url'], ENT_COMPAT, 'UTF-8', false);
|
||||
$url = htmlspecialchars((string)strtolower($arr['url']), ENT_COMPAT, 'UTF-8', false);
|
||||
$sellpage = htmlspecialchars((string)$arr['sellpage'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_location = htmlspecialchars((string)$arr['location'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_realm = htmlspecialchars((string)$arr['realm'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_project = htmlspecialchars((string)$arr['project'], ENT_COMPAT, 'UTF-8', false);
|
||||
$site_crypto = ((array_key_exists('encryption', $arr) && is_array($arr['encryption'])) ? htmlspecialchars((string)implode(',', $arr['encryption']), ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$site_version = ((array_key_exists('version', $arr)) ? htmlspecialchars((string)$arr['version'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
|
||||
// You can have one and only one primary directory per realm.
|
||||
// Downgrade any others claiming to be primary. As they have
|
||||
@@ -2785,28 +2813,6 @@ class Libzot {
|
||||
if ($deleted || $censored || $sys_channel)
|
||||
$searchable = false;
|
||||
|
||||
$public_forum = false;
|
||||
|
||||
$role = get_pconfig($e['channel_id'], 'system', 'permissions_role');
|
||||
if ($role === 'forum' || $role === 'repository') {
|
||||
$public_forum = true;
|
||||
}
|
||||
else {
|
||||
// check if it has characteristics of a public forum based on custom permissions.
|
||||
$m = Permissions::FilledAutoperms($e['channel_id']);
|
||||
if ($m) {
|
||||
foreach ($m as $k => $v) {
|
||||
if ($k == 'tag_deliver' && intval($v) == 1)
|
||||
$ch++;
|
||||
if ($k == 'send_stream' && intval($v) == 0)
|
||||
$ch++;
|
||||
}
|
||||
if ($ch == 2)
|
||||
$public_forum = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This is for birthdays and keywords, but must check access permissions
|
||||
$p = q("select * from profile where uid = %d and is_default = 1",
|
||||
intval($e['channel_id'])
|
||||
@@ -2865,6 +2871,7 @@ class Libzot {
|
||||
];
|
||||
|
||||
$ret['public_key'] = $e['xchan_pubkey'];
|
||||
$ret['signing_algorithm'] = 'rsa-sha256';
|
||||
$ret['username'] = $e['channel_address'];
|
||||
$ret['name'] = $e['xchan_name'];
|
||||
$ret['name_updated'] = $e['xchan_name_date'];
|
||||
@@ -2875,6 +2882,7 @@ class Libzot {
|
||||
];
|
||||
|
||||
$ret['channel_role'] = get_pconfig($e['channel_id'], 'system', 'permissions_role', 'custom');
|
||||
$ret['channel_type'] = ((get_pconfig($e['channel_id'], 'system', 'group_actor')) ? 'group' : 'normal');
|
||||
|
||||
$hookinfo = [
|
||||
'channel_id' => $id,
|
||||
@@ -2890,8 +2898,10 @@ class Libzot {
|
||||
$ret['protocols'] = $hookinfo['protocols'];
|
||||
$ret['searchable'] = $searchable;
|
||||
$ret['adult_content'] = $adult_channel;
|
||||
$ret['public_forum'] = $public_forum;
|
||||
|
||||
// now all forums (public, restricted, and private) set the public_forum flag. So it really means "is a group"
|
||||
// and has nothing to do with accessibility.
|
||||
$ret['public_forum'] = get_pconfig($e['channel_id'], 'system', 'group_actor');
|
||||
$ret['comments'] = map_scope(PermissionLimits::Get($e['channel_id'], 'post_comments'));
|
||||
$ret['mail'] = map_scope(PermissionLimits::Get($e['channel_id'], 'post_mail'));
|
||||
|
||||
@@ -3189,7 +3199,7 @@ class Libzot {
|
||||
}
|
||||
|
||||
static function update_cached_hubloc($hubloc) {
|
||||
if ($hubloc['hubloc_updated'] > datetime_convert('UTC','UTC','now - 1 week') || $hubloc['hubloc_url'] === z_root()) {
|
||||
if ($hubloc['hubloc_updated'] > datetime_convert('UTC','UTC','now - 3 days') || $hubloc['hubloc_url'] === z_root()) {
|
||||
return;
|
||||
}
|
||||
self::refresh( [ 'hubloc_id_url' => $hubloc['hubloc_id_url'] ] );
|
||||
|
||||
@@ -2,85 +2,104 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
class MessageFilter {
|
||||
|
||||
public static function evaluate($item, $incl, $excl) {
|
||||
|
||||
static public function evaluate($item,$incl,$excl) {
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
$text = prepare_text($item['body'],$item['mimetype']);
|
||||
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/x-multicode'));
|
||||
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
|
||||
|
||||
|
||||
$lang = null;
|
||||
|
||||
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
|
||||
if ((strpos($incl, 'lang=') !== false) || (strpos($excl, 'lang=') !== false) || (strpos($incl, 'lang!=') !== false) || (strpos($excl, 'lang!=') !== false)) {
|
||||
$lang = detect_language($text);
|
||||
}
|
||||
|
||||
$tags = ((is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
|
||||
$tags = ((isset($item['term']) && is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
|
||||
|
||||
// exclude always has priority
|
||||
|
||||
$exclude = (($excl) ? explode("\n",$excl) : null);
|
||||
$exclude = (($excl) ? explode("\n", $excl) : null);
|
||||
|
||||
if($exclude) {
|
||||
foreach($exclude as $word) {
|
||||
if ($exclude) {
|
||||
foreach ($exclude as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
if (! $word) {
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return false;
|
||||
}
|
||||
elseif(substr($word,0,1) === '$' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
if (substr($word, 0, 1) === '#' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '$' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if (($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} elseif (substr($word, 0, 2) === '?+') {
|
||||
if (self::test_condition(substr($word, 2), $item['obj'])) {
|
||||
return false;
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '?') {
|
||||
if (self::test_condition(substr($word, 1), $item)) {
|
||||
return false;
|
||||
}
|
||||
} elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
|
||||
return false;
|
||||
} elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
|
||||
return false;
|
||||
} elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
|
||||
return false;
|
||||
} elseif (stristr($text, $word) !== false) {
|
||||
return false;
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
return false;
|
||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||
return false;
|
||||
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||
return false;
|
||||
elseif(stristr($text,$word) !== false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$include = (($incl) ? explode("\n",$incl) : null);
|
||||
$include = (($incl) ? explode("\n", $incl) : null);
|
||||
|
||||
if($include) {
|
||||
foreach($include as $word) {
|
||||
if ($include) {
|
||||
foreach ($include as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
if (! $word) {
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return true;
|
||||
}
|
||||
elseif(substr($word,0,1) === '$' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
if (substr($word, 0, 1) === '#' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '$' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if (($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif (substr($word, 0, 2) === '?+') {
|
||||
if (self::test_condition(substr($word, 2), $item['obj'])) {
|
||||
return true;
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '?') {
|
||||
if (self::test_condition(substr($word, 1), $item)) {
|
||||
return true;
|
||||
}
|
||||
} elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
|
||||
return true;
|
||||
} elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
|
||||
return true;
|
||||
} elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
|
||||
return true;
|
||||
} elseif (stristr($text, $word) !== false) {
|
||||
return true;
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
return true;
|
||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||
return true;
|
||||
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||
return true;
|
||||
elseif(stristr($text,$word) !== false)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -88,4 +107,113 @@ class MessageFilter {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Test for Conditional Execution conditions. Shamelessly ripped off from Code/Render/Comanche
|
||||
*
|
||||
* This is extensible. The first version of variable testing supports tests of the forms:
|
||||
*
|
||||
* - ?foo ~= baz which will check if item.foo contains the string 'baz';
|
||||
* - ?foo == baz which will check if item.foo is the string 'baz';
|
||||
* - ?foo != baz which will check if item.foo is not the string 'baz';
|
||||
* - ?foo >= 3 which will check if item.foo is greater than or equal to 3;
|
||||
* - ?foo > 3 which will check if item.foo is greater than 3;
|
||||
* - ?foo <= 3 which will check if item.foo is less than or equal to 3;
|
||||
* - ?foo < 3 which will check if item.foo is less than 3;
|
||||
*
|
||||
* - ?foo {} baz which will check if 'baz' is an array element in item.foo
|
||||
* - ?foo {*} baz which will check if 'baz' is an array key in item.foo
|
||||
* - ?foo which will check for a return of a true condition for item.foo;
|
||||
*
|
||||
* The values 0, '', an empty array, and an unset value will all evaluate to false.
|
||||
*
|
||||
* @param string $s
|
||||
* @param array $item
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public static function test_condition($s,$item) {
|
||||
|
||||
if (preg_match('/(.*?)\s\~\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (stripos($x, trim($matches[2])) !== false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\=\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x == trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\!\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x != trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\>\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x >= trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\<\=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x <= trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x > trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\>\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x < trim($matches[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/[\$](.*?)\s\{\}\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (is_array($x) && in_array(trim($matches[2]), $x)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)\s\{\*\}\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (is_array($x) && array_key_exists(trim($matches[2]), $x)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if ($x) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
/**
|
||||
* @brief Class for handling channel specific configurations.
|
||||
*
|
||||
@@ -32,15 +34,15 @@ class PConfig {
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
|
||||
if(! is_array(\App::$config)) {
|
||||
if(! is_array(App::$config)) {
|
||||
btlogger('App::$config not an array');
|
||||
}
|
||||
|
||||
if(! array_key_exists($uid, \App::$config)) {
|
||||
\App::$config[$uid] = array();
|
||||
if(! array_key_exists($uid, App::$config)) {
|
||||
App::$config[$uid] = array();
|
||||
}
|
||||
|
||||
if(! is_array(\App::$config[$uid])) {
|
||||
if(! is_array(App::$config[$uid])) {
|
||||
btlogger('App::$config[$uid] not an array: ' . $uid);
|
||||
}
|
||||
|
||||
@@ -52,12 +54,12 @@ class PConfig {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if(! array_key_exists($c, \App::$config[$uid])) {
|
||||
\App::$config[$uid][$c] = array();
|
||||
\App::$config[$uid][$c]['config_loaded'] = true;
|
||||
if(! array_key_exists($c, App::$config[$uid])) {
|
||||
App::$config[$uid][$c] = array();
|
||||
App::$config[$uid][$c]['config_loaded'] = true;
|
||||
}
|
||||
\App::$config[$uid][$c][$k] = $rr['v'];
|
||||
\App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
|
||||
App::$config[$uid][$c][$k] = $rr['v'];
|
||||
App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,15 +88,15 @@ class PConfig {
|
||||
if(is_null($uid) || $uid === false)
|
||||
return $default;
|
||||
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
self::Load($uid);
|
||||
|
||||
if((! array_key_exists($family, \App::$config[$uid])) || (! array_key_exists($key, \App::$config[$uid][$family])))
|
||||
if((! array_key_exists($family, App::$config[$uid])) || (! array_key_exists($key, App::$config[$uid][$family])))
|
||||
return $default;
|
||||
|
||||
return ((! is_array(\App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$uid][$family][$key]))
|
||||
? unserialize(\App::$config[$uid][$family][$key])
|
||||
: \App::$config[$uid][$family][$key]
|
||||
return ((! is_array(App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', App::$config[$uid][$family][$key]))
|
||||
? unserialize(App::$config[$uid][$family][$key])
|
||||
: App::$config[$uid][$family][$key]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -133,6 +135,7 @@ class PConfig {
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
$new = false;
|
||||
$update = false;
|
||||
|
||||
$now = datetime_convert();
|
||||
if (! $updated) {
|
||||
@@ -143,23 +146,22 @@ class PConfig {
|
||||
$updated = datetime_convert('UTC','UTC','-2 seconds');
|
||||
}
|
||||
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
$hash = gen_link_id($family.':'.$key);
|
||||
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
|
||||
if (self::Get($uid, 'hz_delpconfig', $hash) > $now) {
|
||||
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
|
||||
return self::Get($uid,$family,$key);
|
||||
} else {
|
||||
self::Delete($uid,'hz_delpconfig',$hash);
|
||||
self::Delete($uid, 'hz_delpconfig', $hash);
|
||||
}
|
||||
}
|
||||
|
||||
if(self::Get($uid, $family, $key) === false) {
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
\App::$config[$uid] = array();
|
||||
if(! array_key_exists($family, \App::$config[$uid]))
|
||||
\App::$config[$uid][$family] = array();
|
||||
|
||||
if(! array_key_exists($uid, App::$config))
|
||||
App::$config[$uid] = array();
|
||||
if(! array_key_exists($family, App::$config[$uid]))
|
||||
App::$config[$uid][$family] = array();
|
||||
|
||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($uid),
|
||||
@@ -177,13 +179,14 @@ class PConfig {
|
||||
logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR);
|
||||
}
|
||||
|
||||
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
$new = true;
|
||||
App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
|
||||
}
|
||||
else {
|
||||
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
$update = (App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
|
||||
if ($new) {
|
||||
if ($update) {
|
||||
|
||||
// @NOTE There is still a possible race condition under limited circumstances
|
||||
// where a value will be updated by another thread with more current data than
|
||||
@@ -198,7 +201,7 @@ class PConfig {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||
|
||||
} else {
|
||||
logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR);
|
||||
@@ -211,16 +214,16 @@ class PConfig {
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel clones.
|
||||
|
||||
if(! array_key_exists('transient', \App::$config[$uid]))
|
||||
\App::$config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, \App::$config[$uid]['transient']))
|
||||
\App::$config[$uid]['transient'][$family] = array();
|
||||
if(! array_key_exists('transient', App::$config[$uid]))
|
||||
App::$config[$uid]['transient'] = array();
|
||||
if(! array_key_exists($family, App::$config[$uid]['transient']))
|
||||
App::$config[$uid]['transient'][$family] = array();
|
||||
|
||||
\App::$config[$uid][$family][$key] = $value;
|
||||
App::$config[$uid][$family][$key] = $value;
|
||||
|
||||
if ($new) {
|
||||
\App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
\App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
|
||||
if ($new || $update) {
|
||||
App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
|
||||
}
|
||||
|
||||
if($ret)
|
||||
@@ -253,7 +256,7 @@ class PConfig {
|
||||
|
||||
$updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds');
|
||||
$now = datetime_convert();
|
||||
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
$newer = (App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||
|
||||
if (! $newer) {
|
||||
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
|
||||
@@ -262,12 +265,12 @@ class PConfig {
|
||||
|
||||
$ret = false;
|
||||
|
||||
if (isset(\App::$config[$uid][$family][$key])) {
|
||||
unset(\App::$config[$uid][$family][$key]);
|
||||
if (isset(App::$config[$uid][$family][$key])) {
|
||||
unset(App::$config[$uid][$family][$key]);
|
||||
}
|
||||
|
||||
if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) {
|
||||
unset(\App::$config[$uid][$family]['pcfgud:'.$key]);
|
||||
if (isset(App::$config[$uid][$family]['pcfgud:'.$key])) {
|
||||
unset(App::$config[$uid][$family]['pcfgud:'.$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
@@ -278,9 +281,9 @@ class PConfig {
|
||||
|
||||
// Synchronize delete with clones.
|
||||
|
||||
if ($family != 'hz_delpconfig') {
|
||||
$hash = hash('sha256',$family.':'.$key);
|
||||
set_pconfig($uid,'hz_delpconfig',$hash,$updated);
|
||||
if ($family !== 'hz_delpconfig') {
|
||||
$hash = gen_link_id($family.':'.$key);
|
||||
set_pconfig($uid, 'hz_delpconfig', $hash, $updated);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Access\PermissionRoles;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
/**
|
||||
* @brief Permission Categories. Permission rules for various classes of connections.
|
||||
@@ -38,33 +39,33 @@ class Permcat {
|
||||
|
||||
// first check role perms for a perms_connect setting
|
||||
|
||||
$role = get_pconfig($channel_id,'system','permissions_role');
|
||||
if($role) {
|
||||
$role = get_pconfig($channel_id, 'system', 'permissions_role');
|
||||
if ($role) {
|
||||
$x = PermissionRoles::role_perms($role);
|
||||
if($x['perms_connect']) {
|
||||
if ($x['perms_connect']) {
|
||||
$perms = Permissions::FilledPerms($x['perms_connect']);
|
||||
}
|
||||
}
|
||||
|
||||
// if no role perms it may be a custom role, see if there any autoperms
|
||||
|
||||
if(! $perms) {
|
||||
if (!$perms) {
|
||||
$perms = Permissions::FilledAutoPerms($channel_id);
|
||||
}
|
||||
|
||||
// if no autoperms it may be a custom role with manual perms
|
||||
|
||||
if(! $perms) {
|
||||
if (!$perms) {
|
||||
$r = q("select channel_hash from channel where channel_id = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
if ($r) {
|
||||
$x = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'my_perms'",
|
||||
intval($channel_id),
|
||||
dbesc($r[0]['channel_hash'])
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
if ($x) {
|
||||
foreach ($x as $xv) {
|
||||
$perms[$xv['k']] = intval($xv['v']);
|
||||
}
|
||||
}
|
||||
@@ -73,25 +74,27 @@ class Permcat {
|
||||
|
||||
// nothing was found - create a filled permission array where all permissions are 0
|
||||
|
||||
if(! $perms) {
|
||||
if (!$perms) {
|
||||
$perms = Permissions::FilledPerms([]);
|
||||
}
|
||||
|
||||
$this->permcats[] = [
|
||||
'name' => 'default',
|
||||
'localname' => t('default','permcat'),
|
||||
'localname' => t('Default', 'permcat'),
|
||||
'perms' => Permissions::Operms($perms),
|
||||
'raw_perms' => $perms,
|
||||
'system' => 1
|
||||
];
|
||||
|
||||
|
||||
$p = $this->load_permcats($channel_id);
|
||||
if($p) {
|
||||
for($x = 0; $x < count($p); $x++) {
|
||||
if ($p) {
|
||||
for ($x = 0; $x < count($p); $x++) {
|
||||
$this->permcats[] = [
|
||||
'name' => $p[$x][0],
|
||||
'localname' => $p[$x][1],
|
||||
'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
|
||||
'raw_perms' => Permissions::FilledPerms($p[$x][2]),
|
||||
'system' => intval($p[$x][3])
|
||||
];
|
||||
}
|
||||
@@ -116,9 +119,9 @@ class Permcat {
|
||||
* * \e bool \b error if $name not found in permcats true
|
||||
*/
|
||||
public function fetch($name) {
|
||||
if($name && $this->permcats) {
|
||||
foreach($this->permcats as $permcat) {
|
||||
if(strcasecmp($permcat['name'], $name) === 0) {
|
||||
if ($name && $this->permcats) {
|
||||
foreach ($this->permcats as $permcat) {
|
||||
if (strcasecmp($permcat['name'], $name) === 0) {
|
||||
return $permcat;
|
||||
}
|
||||
}
|
||||
@@ -128,31 +131,28 @@ class Permcat {
|
||||
}
|
||||
|
||||
public function load_permcats($uid) {
|
||||
|
||||
/*
|
||||
$permcats = [
|
||||
[ 'follower', t('follower','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_like' ], 1
|
||||
],
|
||||
[ 'contributor', t('contributor','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_wall','post_comments','write_wiki','post_like','tag_deliver','chat' ], 1
|
||||
],
|
||||
[ 'publisher', t('publisher','permcat'),
|
||||
[ 'contributor', t('Contributor','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
|
||||
'write_storage','post_wall','write_pages','write_wiki','post_comments','post_like','tag_deliver',
|
||||
'chat', 'republish' ], 1
|
||||
]
|
||||
'write_storage','post_wall','write_pages','write_wiki','post_comments', 'post_mail', 'post_like',
|
||||
'chat' ], 1
|
||||
],
|
||||
[ 'muted', t('Muted','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_comments','write_wiki','post_like' ], 1
|
||||
],
|
||||
];
|
||||
|
||||
if($uid) {
|
||||
*/
|
||||
if ($uid) {
|
||||
$x = q("select * from pconfig where uid = %d and cat = 'permcat'",
|
||||
intval($uid)
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
|
||||
$permcats[] = [ $xv['k'], $xv['k'], $value, 0 ];
|
||||
|
||||
if ($x) {
|
||||
foreach ($x as $xv) {
|
||||
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
|
||||
$permcats[] = [$xv['k'], $xv['k'], $value, 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,11 +167,11 @@ class Permcat {
|
||||
}
|
||||
|
||||
static public function find_permcat($arr, $name) {
|
||||
if((! $arr) || (! $name))
|
||||
if ((!$arr) || (!$name))
|
||||
return false;
|
||||
|
||||
foreach($arr as $p)
|
||||
if($p['name'] == $name)
|
||||
foreach ($arr as $p)
|
||||
if ($p['name'] == $name)
|
||||
return $p['value'];
|
||||
}
|
||||
|
||||
@@ -183,4 +183,105 @@ class Permcat {
|
||||
PConfig::Delete($channel_id, 'permcat', $name);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief assign a contact role to contacts
|
||||
*
|
||||
* @param array $channel
|
||||
* @param string $role the name of the role
|
||||
* @param array $contacts an array of contact hashes
|
||||
*/
|
||||
public static function assign($channel, $role, $contacts) {
|
||||
|
||||
if (!isset($channel['channel_id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($contacts) || empty($contacts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$role) {
|
||||
// lookup the default
|
||||
$role = get_pconfig($channel['channel_id'], 'system', 'default_permcat', 'default');
|
||||
}
|
||||
|
||||
|
||||
// Doublecheck that we do not assign a role to ourself.
|
||||
// It does not make a difference but could be confusing.
|
||||
if (in_array($channel['channel_hash'], $contacts)) {
|
||||
$contacts = array_diff($contacts, [$channel['channel_hash']]);
|
||||
}
|
||||
|
||||
$all_perms = Permissions::Perms();
|
||||
$permcats = new Permcat($channel['channel_id']);
|
||||
$role_perms = $permcats->fetch($role);
|
||||
|
||||
if (isset($role_perms['error'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$perms = $role_perms['raw_perms'];
|
||||
|
||||
$values_sql = '';
|
||||
stringify_array_elms($contacts, true);
|
||||
|
||||
if ($all_perms && $perms) {
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
foreach ($all_perms as $perm => $desc) {
|
||||
if (array_key_exists($perm, $perms)) {
|
||||
$values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', " . intval($perms[$perm]) . "),";
|
||||
}
|
||||
else {
|
||||
$values_sql .= " (" . intval($channel['channel_id']) . ", " . protect_sprintf($contact) . ", 'my_perms', '" . dbesc($perm) . "', 0), ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$values_sql = rtrim($values_sql, ',');
|
||||
|
||||
dbq("DELETE FROM abconfig WHERE chan = " . intval($channel['channel_id']) . " AND cat = 'my_perms' AND xchan IN (" . protect_sprintf(implode(',', $contacts)) . ")");
|
||||
|
||||
dbq("INSERT INTO abconfig ( chan, xchan, cat, k, v ) VALUES $values_sql");
|
||||
|
||||
q("UPDATE abook SET abook_role = '%s'
|
||||
WHERE abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook_channel = %d",
|
||||
dbesc($role),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook.abook_xchan = xchan.xchan_hash WHERE abook.abook_xchan IN (" . protect_sprintf(implode(',', $contacts)) . ") AND abook.abook_channel = %d AND abook_self = 0",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
foreach ($r as $rr) {
|
||||
|
||||
if (intval($rr['abook_self'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Master::Summon([
|
||||
'Notifier',
|
||||
'permission_update',
|
||||
$rr['abook_id']
|
||||
]);
|
||||
|
||||
$clone = $rr;
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
|
||||
if ($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Access\AccessList;
|
||||
|
||||
require_once('include/text.php');
|
||||
|
||||
@@ -58,6 +60,9 @@ class ThreadItem {
|
||||
$child = new ThreadItem($item);
|
||||
$this->add_child($child);
|
||||
}
|
||||
|
||||
// performance: we have already added the children
|
||||
unset($this->data['children']);
|
||||
}
|
||||
|
||||
// allow a site to configure the order and content of the reaction emoji list
|
||||
@@ -98,11 +103,25 @@ class ThreadItem {
|
||||
$conv = $this->get_conversation();
|
||||
$observer = $conv->get_observer();
|
||||
|
||||
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
||||
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
|
||||
? t('Private Message')
|
||||
$acl = new AccessList(false);
|
||||
$acl->set($item);
|
||||
|
||||
$lock = ((intval($item['item_private']) || ($item['uid'] == local_channel() && $acl->is_private()))
|
||||
? t('Restricted message')
|
||||
: false);
|
||||
$locktype = $item['item_private'];
|
||||
|
||||
// 1 = restricted message, 2 = direct message
|
||||
$locktype = intval($item['item_private']);
|
||||
|
||||
if ($locktype === 2) {
|
||||
$lock = t('Direct message');
|
||||
}
|
||||
|
||||
// 0 = limited based on public policy
|
||||
if ($item['uid'] == local_channel() && intval($item['item_private']) && !$acl->is_private() && strlen($item['public_policy'])) {
|
||||
$lock = t('Public Policy');
|
||||
$locktype = 0;
|
||||
}
|
||||
|
||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
|
||||
|
||||
@@ -110,6 +129,16 @@ class ThreadItem {
|
||||
if($item['author']['xchan_network'] === 'rss')
|
||||
$shareable = true;
|
||||
|
||||
// @fixme
|
||||
// Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
|
||||
// Sharing a poll using a regular embedded share is harder because the poll will need to fork. This is due to comment permissions.
|
||||
// The original poll author may not accept responses from strangers. Forking the poll will receive responses from the sharer's
|
||||
// followers, but there's no elegant way to merge these two sets of results together. For now, we'll disable sharing polls.
|
||||
|
||||
if ($item['obj_type'] === 'Question') {
|
||||
$shareable = false;
|
||||
}
|
||||
|
||||
$privacy_warning = false;
|
||||
if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
|
||||
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
|
||||
@@ -384,6 +413,12 @@ class ThreadItem {
|
||||
$pinned_items = ($allowed_type ? get_pconfig($item['uid'], 'pinned', $item['item_type'], []) : []);
|
||||
$pinned = ((!empty($pinned_items) && in_array($midb64, $pinned_items)) ? true : false);
|
||||
|
||||
$contact = [];
|
||||
|
||||
if(App::$contacts && array_key_exists($item['author_xchan'], App::$contacts)) {
|
||||
$contact = App::$contacts[$item['author_xchan']];
|
||||
}
|
||||
|
||||
$tmp_item = array(
|
||||
'template' => $this->get_template(),
|
||||
'mode' => $mode,
|
||||
@@ -401,6 +436,7 @@ class ThreadItem {
|
||||
'mids' => $json_mids,
|
||||
'parent' => $item['parent'],
|
||||
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||
'author_is_group_actor' => (($item['author']['xchan_pubforum']) ? t('Forum') : ''),
|
||||
'isevent' => $isevent,
|
||||
'attend' => $attend,
|
||||
'consensus' => $consensus,
|
||||
@@ -503,7 +539,9 @@ class ThreadItem {
|
||||
'wait' => t('Please wait'),
|
||||
'thread_level' => $thread_level,
|
||||
'settings' => $settings,
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? gen_link_id($item['thr_parent']) : '')
|
||||
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? gen_link_id($item['thr_parent']) : ''),
|
||||
'contact_id' => (($contact) ? $contact['abook_id'] : '')
|
||||
|
||||
);
|
||||
|
||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||
|
||||
@@ -87,4 +87,4 @@ class ZotURL {
|
||||
return ids_to_array($r,'hubloc_url');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Zotfinger {
|
||||
|
||||
static function exec($resource,$channel = null, $verify = true) {
|
||||
static function exec($resource, $channel = null, $verify = true, $recurse = true) {
|
||||
|
||||
if(! $resource) {
|
||||
return false;
|
||||
@@ -39,6 +39,30 @@ class Zotfinger {
|
||||
|
||||
logger('fetch: ' . print_r($x,true));
|
||||
|
||||
if (in_array(intval($x['return_code']), [ 404, 410 ]) && $recurse) {
|
||||
|
||||
// The resource has been deleted or doesn't exist at this location.
|
||||
// Try to find another nomadic resource for this channel and return that.
|
||||
|
||||
// First, see if there's a hubloc for this site. Fetch that record to
|
||||
// obtain the nomadic identity hash. Then use that to find any additional
|
||||
// nomadic locations.
|
||||
|
||||
$h = Activity::get_actor_hublocs($resource, 'zot6');
|
||||
if ($h) {
|
||||
// mark this location deleted
|
||||
hubloc_delete($h[0]);
|
||||
$hubs = Activity::get_actor_hublocs($h[0]['hubloc_hash']);
|
||||
if ($hubs) {
|
||||
foreach ($hubs as $hub) {
|
||||
if ($hub['hubloc_id_url'] !== $resource && !$hub['hubloc_deleted']) {
|
||||
return self::exec($hub['hubloc_id_url'], $channel, $verify);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($x['success']) {
|
||||
if ($verify) {
|
||||
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
use Zotlabs\Lib\AccessList;
|
||||
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/group.php';
|
||||
|
||||
/**
|
||||
* @brief ACL selector json backend.
|
||||
@@ -123,7 +123,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
"name" => t('Profile','acl') . ' ' . $rv['profile_name'],
|
||||
"id" => 'vp' . $rv['id'],
|
||||
"xid" => 'vp.' . $rv['profile_guid'],
|
||||
"uids" => group_get_profile_members_xchan(local_channel(), $rv['id']),
|
||||
"uids" => AccessList::profile_members_xchan(local_channel(), $rv['id']),
|
||||
"link" => ''
|
||||
);
|
||||
}
|
||||
@@ -146,14 +146,14 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
|
||||
if($r) {
|
||||
foreach($r as $g){
|
||||
// logger('acl: group: ' . $g['gname'] . ' members: ' . group_get_members_xchan($g['id']));
|
||||
// logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(), $g['id']));
|
||||
$groups[] = array(
|
||||
"type" => "g",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['gname'],
|
||||
"id" => $g['id'],
|
||||
"xid" => $g['hash'],
|
||||
"uids" => group_get_members_xchan($g['id']),
|
||||
"uids" => AccessList::members_xchan(local_channel(), $g['id']),
|
||||
"link" => ''
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,18 @@ class Queue {
|
||||
LibQueue::remove_by_posturl($_REQUEST['emptyhub']);
|
||||
}
|
||||
|
||||
$r = q("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
|
||||
if($_REQUEST['deliverhub']) {
|
||||
|
||||
$hubq = q("SELECT * FROM outq WHERE outq_posturl = '%s'",
|
||||
dbesc($_REQUEST['deliverhub'])
|
||||
);
|
||||
|
||||
foreach ($hubq as $q) {
|
||||
LibQueue::deliver($q, true);
|
||||
}
|
||||
}
|
||||
|
||||
$r = dbq("select count(outq_posturl) as total, max(outq_priority) as priority, outq_posturl from outq
|
||||
where outq_delivered = 0 group by outq_posturl order by total desc");
|
||||
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
@@ -37,6 +48,7 @@ class Queue {
|
||||
'$priority' => t('Priority'),
|
||||
'$desturl' => t('Destination URL'),
|
||||
'$nukehub' => t('Mark hub permanently offline'),
|
||||
'$deliverhub' => t('Retry delivery to this hub'),
|
||||
'$empty' => t('Empty queue for this hub'),
|
||||
'$lastconn' => t('Last known contact'),
|
||||
'$hasentries' => ((count($r)) ? true : false),
|
||||
|
||||
@@ -339,12 +339,15 @@ class Site {
|
||||
// now invert the logic for the setting.
|
||||
$discover_tab = (1 - $discover_tab);
|
||||
|
||||
$perm_roles = \Zotlabs\Access\PermissionRoles::roles();
|
||||
$default_role = get_config('system','default_permissions_role','social');
|
||||
$perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles();
|
||||
$default_role = get_config('system', 'default_permissions_role', 'personal');
|
||||
|
||||
if (!in_array($default_role, array_keys($perm_roles))) {
|
||||
$default_role = 'personal';
|
||||
}
|
||||
|
||||
$role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles);
|
||||
|
||||
|
||||
$homelogin = get_config('system','login_on_homepage');
|
||||
$enable_context_help = get_config('system','enable_context_help');
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class Apschema extends \Zotlabs\Web\Controller {
|
||||
'zot' => z_root() . '/apschema#',
|
||||
'id' => '@id',
|
||||
'type' => '@type',
|
||||
'commentPolicy' => 'as:commentPolicy',
|
||||
'commentPolicy' => 'zot:commentPolicy',
|
||||
'meData' => 'zot:meData',
|
||||
'meDataType' => 'zot:meDataType',
|
||||
'meEncoding' => 'zot:meEncoding',
|
||||
@@ -33,6 +33,9 @@ class Apschema extends \Zotlabs\Web\Controller {
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
|
||||
|
||||
'magicEnv' => [
|
||||
'@id' => 'zot:magicEnv',
|
||||
'@type' => '@id'
|
||||
|
||||
@@ -66,8 +66,7 @@ class Channel extends Controller {
|
||||
$sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6');
|
||||
|
||||
if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
|
||||
$data = json_encode(Libzot::zotinfo(['address' => $channel['channel_address'], 'target_url' => $sigdata['signer']]));
|
||||
|
||||
$data = json_encode(Libzot::zotinfo(['guid_hash' => $channel['channel_hash'], 'target_url' => $sigdata['signer']]));
|
||||
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||
dbesc($sigdata['signer'])
|
||||
);
|
||||
@@ -96,6 +95,10 @@ class Channel extends Controller {
|
||||
http_status_exit(410, 'Gone');
|
||||
}
|
||||
|
||||
if (get_pconfig($channel['channel_id'], 'system', 'index_opt_out')) {
|
||||
App::$meta->set('robots', 'noindex, noarchive');
|
||||
}
|
||||
|
||||
if (ActivityStreams::is_as_request($channel)) {
|
||||
|
||||
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
|
||||
|
||||
@@ -2,32 +2,32 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Permcat;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/group.php');
|
||||
|
||||
class Connections extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
App::$profile_uid = local_channel();
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
if($channel)
|
||||
head_set_icon($channel['xchan_photo_s']);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
$sort_type = 0;
|
||||
$o = '';
|
||||
|
||||
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return login();
|
||||
@@ -44,13 +44,13 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$pending = false;
|
||||
$unconnected = false;
|
||||
$all = false;
|
||||
|
||||
|
||||
if(! $_REQUEST['aj'])
|
||||
$_SESSION['return_url'] = App::$query_string;
|
||||
|
||||
|
||||
$search_flags = "";
|
||||
$head = '';
|
||||
|
||||
|
||||
if(argc() == 2) {
|
||||
switch(argv(1)) {
|
||||
case 'active':
|
||||
@@ -106,7 +106,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
// $head = t('Unconnected');
|
||||
// $unconnected = true;
|
||||
// break;
|
||||
|
||||
|
||||
case 'all':
|
||||
$head = t('All');
|
||||
break;
|
||||
@@ -115,19 +115,19 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$active = true;
|
||||
$head = t('Active');
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$sql_extra = $search_flags;
|
||||
if(argv(1) === 'pending')
|
||||
$sql_extra .= " and abook_ignored = 0 ";
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
$sql_extra = " and abook_blocked = 0 ";
|
||||
$unblocked = true;
|
||||
}
|
||||
|
||||
|
||||
switch($_REQUEST['order']) {
|
||||
case 'name_desc':
|
||||
$sql_order = 'xchan_name DESC';
|
||||
@@ -143,32 +143,32 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
|
||||
|
||||
|
||||
$tabs = array(
|
||||
/*
|
||||
array(
|
||||
'label' => t('Suggestions'),
|
||||
'url' => z_root() . '/suggest',
|
||||
'url' => z_root() . '/suggest',
|
||||
'sel' => '',
|
||||
'title' => t('Suggest new connections'),
|
||||
),
|
||||
*/
|
||||
|
||||
|
||||
'active' => array(
|
||||
'label' => t('Active Connections'),
|
||||
'url' => z_root() . '/connections/active',
|
||||
'url' => z_root() . '/connections/active',
|
||||
'sel' => ($active) ? 'active' : '',
|
||||
'title' => t('Show active connections'),
|
||||
),
|
||||
|
||||
'pending' => array(
|
||||
'label' => t('New Connections'),
|
||||
'url' => z_root() . '/connections/pending',
|
||||
'url' => z_root() . '/connections/pending',
|
||||
'sel' => ($pending) ? 'active' : '',
|
||||
'title' => t('Show pending (new) connections'),
|
||||
),
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
array(
|
||||
'label' => t('Unblocked'),
|
||||
@@ -177,55 +177,55 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'title' => t('Only show unblocked connections'),
|
||||
),
|
||||
*/
|
||||
|
||||
|
||||
'blocked' => array(
|
||||
'label' => t('Blocked'),
|
||||
'url' => z_root() . '/connections/blocked',
|
||||
'sel' => ($blocked) ? 'active' : '',
|
||||
'title' => t('Only show blocked connections'),
|
||||
),
|
||||
|
||||
|
||||
'ignored' => array(
|
||||
'label' => t('Ignored'),
|
||||
'url' => z_root() . '/connections/ignored',
|
||||
'sel' => ($ignored) ? 'active' : '',
|
||||
'title' => t('Only show ignored connections'),
|
||||
),
|
||||
|
||||
|
||||
'archived' => array(
|
||||
'label' => t('Archived/Unreachable'),
|
||||
'url' => z_root() . '/connections/archived',
|
||||
'sel' => ($archived) ? 'active' : '',
|
||||
'title' => t('Only show archived/unreachable connections'),
|
||||
),
|
||||
|
||||
|
||||
'hidden' => array(
|
||||
'label' => t('Hidden'),
|
||||
'url' => z_root() . '/connections/hidden',
|
||||
'sel' => ($hidden) ? 'active' : '',
|
||||
'title' => t('Only show hidden connections'),
|
||||
),
|
||||
|
||||
|
||||
// array(
|
||||
// 'label' => t('Unconnected'),
|
||||
// 'url' => z_root() . '/connections/unconnected',
|
||||
// 'sel' => ($unconnected) ? 'active' : '',
|
||||
// 'title' => t('Only show one-way connections'),
|
||||
// ),
|
||||
|
||||
|
||||
|
||||
'all' => array(
|
||||
'label' => t('All Connections'),
|
||||
'url' => z_root() . '/connections',
|
||||
'url' => z_root() . '/connections',
|
||||
'sel' => ($all) ? 'active' : '',
|
||||
'title' => t('Show all connections'),
|
||||
),
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
//$tab_tpl = get_markup_template('common_tabs.tpl');
|
||||
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
|
||||
|
||||
|
||||
$searching = false;
|
||||
if($search) {
|
||||
$search_hdr = $search;
|
||||
@@ -233,12 +233,12 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$searching = true;
|
||||
}
|
||||
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
|
||||
|
||||
|
||||
if($_REQUEST['gid']) {
|
||||
$sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
|
||||
}
|
||||
|
||||
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
||||
|
||||
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
||||
where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ",
|
||||
intval(local_channel())
|
||||
);
|
||||
@@ -246,19 +246,27 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
App::set_pager_total($r[0]['total']);
|
||||
$total = $r[0]['total'];
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
||||
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra ORDER BY $sql_order LIMIT %d OFFSET %d ",
|
||||
intval(local_channel()),
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
);
|
||||
|
||||
|
||||
$roles = new Permcat(local_channel());
|
||||
$roles_list = $roles->listing();
|
||||
$roles_dict = [];
|
||||
|
||||
foreach ($roles_list as $role) {
|
||||
$roles_dict[$role['name']] = $role['localname'];
|
||||
}
|
||||
|
||||
$contacts = array();
|
||||
|
||||
|
||||
if($r) {
|
||||
|
||||
vcard_query($r);
|
||||
//vcard_query($r);
|
||||
|
||||
|
||||
foreach($r as $rr) {
|
||||
@@ -268,7 +276,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$phone = $rr['vcard']['tels'][0]['nr'];
|
||||
else
|
||||
$phone = '';
|
||||
|
||||
|
||||
$status_str = '';
|
||||
$status = array(
|
||||
((intval($rr['abook_active'])) ? t('Active') : ''),
|
||||
@@ -306,7 +314,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$perminfo['connperms'] .= t('Nothing');
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach($status as $str) {
|
||||
if(!$str)
|
||||
continue;
|
||||
@@ -314,19 +322,16 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
$status_str .= ', ';
|
||||
}
|
||||
$status_str = rtrim($status_str, ', ');
|
||||
|
||||
|
||||
$contacts[] = array(
|
||||
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
|
||||
'edit_hover' => t('Edit connection'),
|
||||
'edit' => t('Edit'),
|
||||
'delete_hover' => t('Delete connection'),
|
||||
'id' => $rr['abook_id'],
|
||||
'thumb' => $rr['xchan_photo_m'],
|
||||
'thumb' => $rr['xchan_photo_m'],
|
||||
'name' => $rr['xchan_name'],
|
||||
'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''),
|
||||
'link' => z_root() . '/connedit/' . $rr['abook_id'],
|
||||
'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop',
|
||||
'delete' => t('Delete'),
|
||||
'url' => chanlink_hash($rr['xchan_hash']),
|
||||
'webbie_label' => t('Channel address'),
|
||||
'webbie' => $rr['xchan_addr'],
|
||||
@@ -337,6 +342,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'phone' => $phone,
|
||||
'status_label' => t('Status'),
|
||||
'status' => $status_str,
|
||||
'states' => $status,
|
||||
'connected_label' => t('Connected'),
|
||||
'connected' => datetime_convert('UTC',date_default_timezone_get(),$rr['abook_created'], 'c'),
|
||||
'approve_hover' => t('Approve connection'),
|
||||
@@ -349,13 +355,22 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
'perminfo' => $perminfo,
|
||||
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
|
||||
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
|
||||
'connect_hover' => t('Connect at this location')
|
||||
'connect_hover' => t('Connect at this location'),
|
||||
'role' => $roles_dict[$rr['abook_role']],
|
||||
'pending' => intval($rr['abook_pending'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$limit = service_class_fetch(local_channel(),'total_channels');
|
||||
if($limit !== false) {
|
||||
$abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $$total, $limit);
|
||||
}
|
||||
else {
|
||||
$abook_usage_message = '';
|
||||
}
|
||||
|
||||
if($_REQUEST['aj']) {
|
||||
if($contacts) {
|
||||
$o = replace_macros(get_markup_template('contactsajax.tpl'),array(
|
||||
@@ -371,27 +386,30 @@ class Connections extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
else {
|
||||
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||
$o .= replace_macros(get_markup_template('connections.tpl'),array(
|
||||
$o .= replace_macros(get_markup_template('connections.tpl'), [
|
||||
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
|
||||
'$tabs' => $tabs,
|
||||
'$total' => $total,
|
||||
'$search' => $search_hdr,
|
||||
'$label' => t('Search'),
|
||||
'$role_label' => t('Contact role'),
|
||||
'$desc' => t('Search your connections'),
|
||||
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
|
||||
'$finding' => (($searching) ? t('Contact search') . ": '" . $search . "'" : ""),
|
||||
'$submit' => t('Find'),
|
||||
'$edit' => t('Edit'),
|
||||
'$approve' => t('Approve'),
|
||||
'$cmd' => App::$cmd,
|
||||
'$contacts' => $contacts,
|
||||
'$paginate' => paginate($a),
|
||||
|
||||
));
|
||||
'$abook_usage_message' => $abook_usage_message,
|
||||
'$group_label' => t('This is a group/forum channel')
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if(! $contacts)
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
675
Zotlabs/Module/Contactedit.php
Normal file
675
Zotlabs/Module/Contactedit.php
Normal file
@@ -0,0 +1,675 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/* @file Cobtactedit.php
|
||||
* @brief In this file the connection-editor form is generated and evaluated.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
use App;
|
||||
use Sabre\VObject\Reader;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Web\HTTPHeaders;
|
||||
use Zotlabs\Lib\Permcat;
|
||||
use Zotlabs\Lib\AccessList;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/group.php');
|
||||
require_once('include/photos.php');
|
||||
|
||||
class Contactedit extends Controller {
|
||||
|
||||
/* @brief Initialize the connection-editor
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
function init() {
|
||||
|
||||
if (!local_channel())
|
||||
return;
|
||||
|
||||
if ((argc() >= 2) && intval(argv(1))) {
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook LEFT JOIN xchan ON abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d AND abook_id = %d AND abook_self = 0 AND xchan_deleted = 0",
|
||||
intval(local_channel()),
|
||||
intval(argv(1))
|
||||
);
|
||||
if (!$r) {
|
||||
json_return_and_die([
|
||||
'success' => false,
|
||||
'message' => t('Invalid abook_id')
|
||||
]);
|
||||
}
|
||||
|
||||
App::$poi = $r[0];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @brief Evaluate posted values and set changes
|
||||
*
|
||||
*/
|
||||
|
||||
function post() {
|
||||
|
||||
if (!local_channel())
|
||||
return;
|
||||
|
||||
$contact_id = intval(argv(1));
|
||||
if (!$contact_id)
|
||||
return;
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$contact = App::$poi;
|
||||
|
||||
if (!$contact) {
|
||||
notice(t('Could not access contact record.') . EOL);
|
||||
killme();
|
||||
}
|
||||
|
||||
call_hooks('contact_edit_post', $_REQUEST);
|
||||
|
||||
if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
|
||||
$pgrp_ids = q("SELECT id FROM pgrp WHERE deleted = 0 AND uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
foreach($pgrp_ids as $pgrp) {
|
||||
if (array_key_exists('pgrp_id_' . $pgrp['id'], $_REQUEST)) {
|
||||
AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $pgrp['id']);
|
||||
}
|
||||
else {
|
||||
AccessList::member_remove(local_channel(), '', $contact['abook_xchan'], $pgrp['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$profile_id = ((array_key_exists('profile_assign', $_REQUEST)) ? $_REQUEST['profile_assign'] : $contact['abook_profile']);
|
||||
|
||||
if ($profile_id) {
|
||||
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($profile_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
if (!count($r)) {
|
||||
notice(t('Could not locate selected profile.') . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$abook_incl = ((array_key_exists('abook_incl', $_REQUEST)) ? escape_tags($_REQUEST['abook_incl']) : $contact['abook_incl']);
|
||||
$abook_excl = ((array_key_exists('abook_excl', $_REQUEST)) ? escape_tags($_REQUEST['abook_excl']) : $contact['abook_excl']);
|
||||
$abook_role = ((array_key_exists('permcat', $_REQUEST)) ? escape_tags($_REQUEST['permcat']) : $contact['abook_role']);
|
||||
|
||||
if (!array_key_exists('closeness', $_REQUEST)) {
|
||||
$_REQUEST['closeness'] = 80;
|
||||
}
|
||||
|
||||
$closeness = intval($_REQUEST['closeness']);
|
||||
|
||||
if ($closeness < 0 || $closeness > 99) {
|
||||
$closeness = 80;
|
||||
}
|
||||
|
||||
$new_friend = ((intval($contact['abook_pending'])) ? true : false);
|
||||
|
||||
\Zotlabs\Lib\Permcat::assign($channel, $abook_role, [$contact['abook_xchan']]);
|
||||
|
||||
$abook_pending = (($new_friend) ? 0 : $contact['abook_pending']);
|
||||
|
||||
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
|
||||
abook_incl = '%s', abook_excl = '%s'
|
||||
where abook_id = %d AND abook_channel = %d",
|
||||
dbesc($profile_id),
|
||||
intval($closeness),
|
||||
intval($abook_pending),
|
||||
dbesc($abook_incl),
|
||||
dbesc($abook_excl),
|
||||
intval($contact_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$_REQUEST['success'] = false;
|
||||
|
||||
if ($r) {
|
||||
$_REQUEST['success'] = true;
|
||||
}
|
||||
|
||||
|
||||
if (!intval($contact['abook_self'])) {
|
||||
if ($new_friend) {
|
||||
Master::Summon(['Notifier', 'permission_accept', $contact_id]);
|
||||
}
|
||||
|
||||
Master::Summon([
|
||||
'Notifier',
|
||||
(($new_friend) ? 'permission_create' : 'permission_update'),
|
||||
$contact_id
|
||||
]);
|
||||
}
|
||||
|
||||
if ($new_friend) {
|
||||
$default_group = $channel['channel_default_group'];
|
||||
if ($default_group) {
|
||||
$g = AccessList::by_hash(local_channel(), $default_group);
|
||||
if ($g) {
|
||||
AccessList::member_add(local_channel(), '', $contact['abook_xchan'], $g['id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if settings permit ("post new friend activity" is allowed, and
|
||||
// friends in general or this friend in particular aren't hidden)
|
||||
// and send out a new friend activity
|
||||
|
||||
$pr = q("select * from profile where uid = %d and is_default = 1 and hide_friends = 0",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if (($pr) && (!intval($contact['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
|
||||
$xarr = [];
|
||||
|
||||
$xarr['item_wall'] = 1;
|
||||
$xarr['item_origin'] = 1;
|
||||
$xarr['item_thread_top'] = 1;
|
||||
$xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
|
||||
$xarr['allow_cid'] = $channel['channel_allow_cid'];
|
||||
$xarr['allow_gid'] = $channel['channel_allow_gid'];
|
||||
$xarr['deny_cid'] = $channel['channel_deny_cid'];
|
||||
$xarr['deny_gid'] = $channel['channel_deny_gid'];
|
||||
$xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
|
||||
|
||||
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $contact['xchan_url'] . ']' . $contact['xchan_name'] . '[/zrl]';
|
||||
|
||||
$xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=80x80]' . $contact['xchan_photo_m'] . '[/zmg][/zrl]';
|
||||
|
||||
post_activity_item($xarr);
|
||||
|
||||
}
|
||||
|
||||
// pull in a bit of content if there is any to pull in
|
||||
Master::Summon(['Onepoll', $contact_id]);
|
||||
|
||||
}
|
||||
|
||||
// Refresh the structure in memory with the new data
|
||||
$this->init();
|
||||
|
||||
if ($new_friend) {
|
||||
$arr = ['channel_id' => local_channel(), 'abook' => App::$poi];
|
||||
call_hooks('accept_follow', $arr);
|
||||
}
|
||||
|
||||
$this->contactedit_clone();
|
||||
$this->get();
|
||||
|
||||
killme();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* @brief Generate content of contact edit page
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
function get() {
|
||||
|
||||
if (!local_channel()) {
|
||||
killme();
|
||||
}
|
||||
|
||||
if (!App::$poi) {
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
$contact_id = App::$poi['abook_id'];
|
||||
$contact = App::$poi;
|
||||
$section = ((array_key_exists('section', $_REQUEST)) ? $_REQUEST['section'] : 'roles');
|
||||
$sub_section = ((array_key_exists('sub_section', $_REQUEST)) ? $_REQUEST['sub_section'] : '');
|
||||
|
||||
|
||||
if (argc() == 3) {
|
||||
$cmd = argv(2);
|
||||
$ret = $this->do_action($contact, $cmd);
|
||||
$contact = App::$poi;
|
||||
|
||||
$tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [
|
||||
'$tools_label' => t('Contact Tools'),
|
||||
'$tools' => $this->get_tools($contact),
|
||||
]);
|
||||
|
||||
$ret['tools'] = $tools_html;
|
||||
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$groups = [];
|
||||
|
||||
if (Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$member_of = AccessList::containing(local_channel(), $contact['xchan_hash']);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$default_group = false;
|
||||
if ($rr['hash'] === $channel['channel_default_group']) {
|
||||
$default_group = true;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'pgrp_id_' . $rr['id'],
|
||||
$rr['gname'],
|
||||
// if it's a new contact preset the default group if we have one
|
||||
(($default_group && $contact['abook_pending']) ? 1 : in_array($rr['id'], $member_of)),
|
||||
'',
|
||||
[t('No'), t('Yes')]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$slide = '';
|
||||
|
||||
if (Apps::system_app_installed(local_channel(), 'Affinity Tool')) {
|
||||
|
||||
$labels = [
|
||||
t('Me'),
|
||||
t('Family'),
|
||||
t('Friends'),
|
||||
t('Acquaintances'),
|
||||
t('All')
|
||||
];
|
||||
call_hooks('affinity_labels', $labels);
|
||||
$label_str = '';
|
||||
|
||||
if ($labels) {
|
||||
foreach ($labels as $l) {
|
||||
if ($label_str) {
|
||||
$label_str .= ", '|'";
|
||||
$label_str .= ", '" . $l . "'";
|
||||
}
|
||||
else
|
||||
$label_str .= "'" . $l . "'";
|
||||
}
|
||||
}
|
||||
|
||||
$slider_tpl = get_markup_template('contact_slider.tpl');
|
||||
|
||||
$slideval = intval($contact['abook_closeness']);
|
||||
|
||||
$slide = replace_macros($slider_tpl, [
|
||||
'$min' => 1,
|
||||
'$val' => $slideval,
|
||||
'$labels' => $label_str,
|
||||
]);
|
||||
}
|
||||
|
||||
$perms = [];
|
||||
$global_perms = Permissions::Perms();
|
||||
$existing = get_all_perms(local_channel(), $contact['abook_xchan'], false);
|
||||
$unapproved = ['pending', t('Approve this contact'), '', t('Accept contact to allow communication'), [t('No'), ('Yes')]];
|
||||
$multiprofs = ((feature_enabled(local_channel(), 'multi_profiles')) ? true : false);
|
||||
|
||||
$theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
|
||||
intval(local_channel()),
|
||||
dbesc($contact['abook_xchan'])
|
||||
);
|
||||
|
||||
$their_perms = [];
|
||||
if ($theirs) {
|
||||
foreach ($theirs as $t) {
|
||||
$their_perms[$t['k']] = $t['v'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($global_perms as $k => $v) {
|
||||
$thisperm = $existing[$k];
|
||||
$checkinherited = PermissionLimits::Get(local_channel(), $k);
|
||||
$perms[] = ['perms_' . $k, $v, ((array_key_exists($k, $their_perms)) ? intval($their_perms[$k]) : ''), $thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '0' : '1'), '', $checkinherited];
|
||||
}
|
||||
|
||||
$pcat = new Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
|
||||
$current_permcat = (($contact['abook_pending']) ? $default_role : $contact['abook_role']);
|
||||
|
||||
$roles_dict = [];
|
||||
foreach ($pcatlist as $role) {
|
||||
$roles_dict[$role['name']] = $role['localname'];
|
||||
}
|
||||
|
||||
|
||||
if (!$current_permcat) {
|
||||
notice(t('Please select a role for this contact!') . EOL);
|
||||
$permcats[] = '';
|
||||
}
|
||||
|
||||
if ($pcatlist) {
|
||||
foreach ($pcatlist as $pc) {
|
||||
$permcats[$pc['name']] = $pc['localname'];
|
||||
}
|
||||
}
|
||||
|
||||
$locstr = locations_by_netid($contact['xchan_hash']);
|
||||
if (!$locstr) {
|
||||
$locstr = unpunify($contact['xchan_url']);
|
||||
}
|
||||
|
||||
$clone_warn = '';
|
||||
$clonable = in_array($contact['xchan_network'], ['zot6', 'rss']);
|
||||
if (!$clonable) {
|
||||
$clone_warn = '<strong>';
|
||||
$clone_warn .= ((intval($contact['abook_not_here']))
|
||||
? t('This contact is unreachable from this location.')
|
||||
: t('This contact may be unreachable from other channel locations.')
|
||||
);
|
||||
$clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.');
|
||||
}
|
||||
|
||||
$header_card = '<img src="' . $contact['xchan_photo_s'] . '" class="rounded" style="width: 3rem; height: 3rem;"> ' . $contact['xchan_name'];
|
||||
|
||||
$header_html = replace_macros(get_markup_template("contact_edit_header.tpl"), [
|
||||
'$img_src' => $contact['xchan_photo_s'],
|
||||
'$name' => $contact['xchan_name'],
|
||||
'$addr' => (($contact['xchan_addr']) ? $contact['xchan_addr'] : $contact['xchan_url']),
|
||||
'$href' => ((is_matrix_url($contact['xchan_url'])) ? zid($contact['xchan_url']) : $contact['xchan_url']),
|
||||
'$link_label' => t('View profile'),
|
||||
'$is_group' => $contact['xchan_pubforum'],
|
||||
'$group_label' => t('This is a group/forum channel')
|
||||
]);
|
||||
|
||||
$tools_html = replace_macros(get_markup_template("contact_edit_tools.tpl"), [
|
||||
'$tools_label' => t('Contact Tools'),
|
||||
'$tools' => $this->get_tools($contact),
|
||||
]);
|
||||
|
||||
$tpl = get_markup_template("contact_edit.tpl");
|
||||
|
||||
$o = replace_macros($tpl, [
|
||||
'$permcat' => ['permcat', t('Select a role for this contact'), $current_permcat, '', $permcats],
|
||||
'$permcat_new' => t('Contact roles'),
|
||||
'$permcat_value' => bin2hex($current_permcat),
|
||||
// '$addr' => unpunify($contact['xchan_addr']),
|
||||
// '$primeurl' => unpunify($contact['xchan_url']),
|
||||
'$section' => $section,
|
||||
'$sub_section' => $sub_section,
|
||||
'$groups' => $groups,
|
||||
// '$addr_text' => t('This contacts\'s primary address is'),
|
||||
// '$loc_text' => t('Available locations:'),
|
||||
// '$locstr' => $locstr,
|
||||
// '$unclonable' => $clone_warn,
|
||||
'$lbl_slider' => t('Slide to adjust your degree of friendship'),
|
||||
'$connfilter' => feature_enabled(local_channel(), 'connfilter'),
|
||||
'$connfilter_label' => t('Custom Filter'),
|
||||
'$incl' => ['abook_incl', t('Only import posts with this text'), $contact['abook_incl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
|
||||
'$excl' => ['abook_excl', t('Do not import posts with this text'), $contact['abook_excl'], t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')],
|
||||
'$slide' => $slide,
|
||||
// '$pending_label' => t('Contact Pending Approval'),
|
||||
// '$is_pending' => (intval($contact['abook_pending']) ? 1 : ''),
|
||||
// '$unapproved' => $unapproved,
|
||||
'$submit' => ((intval($contact['abook_pending'])) ? t('Approve contact') : t('Submit')),
|
||||
'$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
|
||||
'$them' => t('Their'),
|
||||
'$me' => t('My'),
|
||||
'$perms' => $perms,
|
||||
// '$lastupdtext' => t('Last update:'),
|
||||
// '$last_update' => relative_date($contact['abook_connected']),
|
||||
'$profile_select' => contact_profile_assign($contact['abook_profile']),
|
||||
'$multiprofs' => $multiprofs,
|
||||
'$contact_id' => $contact['abook_id'],
|
||||
// '$name' => $contact['xchan_name'],
|
||||
'$roles_label' => t('Roles'),
|
||||
'$compare_label' => t('Compare permissions'),
|
||||
'$permission_label' => t('Permission'),
|
||||
'$pgroups_label' => t('Privacy groups'),
|
||||
'$profiles_label' => t('Profiles'),
|
||||
'$affinity_label' => t('Affinity'),
|
||||
'$filter_label' => t('Content filter')
|
||||
]);
|
||||
|
||||
$arr = ['contact' => $contact, 'output' => $o];
|
||||
|
||||
call_hooks('contact_edit', $arr);
|
||||
|
||||
if (is_ajax()) {
|
||||
json_return_and_die([
|
||||
'success' => ((intval($_REQUEST['success'])) ? intval($_REQUEST['success']) : 1),
|
||||
'message' => (($_REQUEST['success']) ? t('Contact updated') : t('Contact update failed')),
|
||||
'id' => $contact_id,
|
||||
'title' => $header_html,
|
||||
'role' => ((intval($contact['abook_pending'])) ? '' : $roles_dict[$current_permcat]),
|
||||
'body' => $arr['output'],
|
||||
'tools' => $tools_html,
|
||||
'submit' => ((intval($contact['abook_pending'])) ? t('Approve connection') : t('Submit')),
|
||||
'pending' => intval($contact['abook_pending'])
|
||||
]);
|
||||
}
|
||||
|
||||
return $arr['output'];
|
||||
|
||||
}
|
||||
|
||||
function contactedit_clone() {
|
||||
|
||||
if (!App::$poi)
|
||||
return;
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$clone = App::$poi;
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'], $clone['abook_xchan']);
|
||||
if ($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */, ['abook' => [$clone]]);
|
||||
}
|
||||
|
||||
function do_action($contact, $cmd) {
|
||||
$ret = [
|
||||
'sucess' => false,
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
if ($cmd === 'resetphoto') {
|
||||
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
|
||||
dbesc($contact['xchan_hash'])
|
||||
);
|
||||
$cmd = 'refresh';
|
||||
}
|
||||
|
||||
if ($cmd === 'refresh') {
|
||||
if ($contact['xchan_network'] === 'zot6') {
|
||||
if (Libzot::refresh($contact, App::get_channel())) {
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Refresh succeeded');
|
||||
}
|
||||
else {
|
||||
$ret['message'] = t('Refresh failed - channel is currently unavailable');
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if you are on a different network we'll force a refresh of the connection basic info
|
||||
Master::Summon(['Notifier', 'permission_update', $contact['abook_id']]);
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Refresh succeeded');
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($cmd === 'block') {
|
||||
if (abook_toggle_flag($contact, ABOOK_FLAG_BLOCKED)) {
|
||||
$this->init(); // refresh data
|
||||
|
||||
$this->contactedit_clone();
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Block status updated');
|
||||
}
|
||||
else {
|
||||
$ret['success'] = false;
|
||||
$ret['message'] = t('Block failed');
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($cmd === 'ignore') {
|
||||
if (abook_toggle_flag($contact, ABOOK_FLAG_IGNORED)) {
|
||||
$this->init(); // refresh data
|
||||
|
||||
$this->contactedit_clone();
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Ignore status updated');
|
||||
}
|
||||
else {
|
||||
$ret['success'] = false;
|
||||
$ret['message'] = t('Ignore failed');
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($cmd === 'archive') {
|
||||
if (abook_toggle_flag($contact, ABOOK_FLAG_ARCHIVED)) {
|
||||
$this->init(); // refresh data
|
||||
|
||||
$this->contactedit_clone();
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Archive status updated');
|
||||
}
|
||||
else {
|
||||
$ret['success'] = false;
|
||||
$ret['message'] = t('Archive failed');
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($cmd === 'hide') {
|
||||
if (abook_toggle_flag($contact, ABOOK_FLAG_HIDDEN)) {
|
||||
$this->init(); // refresh data
|
||||
|
||||
$this->contactedit_clone();
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Hide status updated');
|
||||
}
|
||||
else {
|
||||
$ret['success'] = false;
|
||||
$ret['message'] = t('Hide failed');
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// We'll prevent somebody from unapproving an already approved contact.
|
||||
// Though maybe somebody will want this eventually (??)
|
||||
|
||||
//if ($cmd === 'approve') {
|
||||
//if (intval($contact['abook_pending'])) {
|
||||
//if (abook_toggle_flag($contact, ABOOK_FLAG_PENDING)) {
|
||||
//$this->contactedit_clone();
|
||||
//}
|
||||
//else
|
||||
//notice(t('Unable to set address book parameters.') . EOL);
|
||||
//}
|
||||
//goaway(z_root() . '/connedit/' . $contact_id);
|
||||
//}
|
||||
|
||||
|
||||
if ($cmd === 'drop') {
|
||||
|
||||
if (contact_remove(local_channel(), $contact['abook_id'])) {
|
||||
|
||||
Master::Summon(['Notifier', 'purge', local_channel(), $contact['xchan_hash']]);
|
||||
Libsync::build_sync_packet(0 /* use the current local_channel */,
|
||||
['abook' => [
|
||||
[
|
||||
'abook_xchan' => $contact['abook_xchan'],
|
||||
'entry_deleted' => true
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Contact removed');
|
||||
}
|
||||
else {
|
||||
$ret['success'] = false;
|
||||
$ret['message'] = t('Delete failed');
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
function get_tools($contact) {
|
||||
return [
|
||||
|
||||
'refresh' => [
|
||||
'label' => t('Refresh Permissions'),
|
||||
'title' => t('Fetch updated permissions'),
|
||||
],
|
||||
|
||||
'rephoto' => [
|
||||
'label' => t('Refresh Photo'),
|
||||
'title' => t('Fetch updated photo'),
|
||||
],
|
||||
|
||||
|
||||
'block' => [
|
||||
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
|
||||
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),
|
||||
'title' => t('Block (or Unblock) all communications with this connection'),
|
||||
'info' => (intval($contact['abook_blocked']) ? t('This connection is blocked!') : ''),
|
||||
],
|
||||
|
||||
'ignore' => [
|
||||
'label' => (intval($contact['abook_ignored']) ? t('Unignore') : t('Ignore')),
|
||||
'sel' => (intval($contact['abook_ignored']) ? 'active' : ''),
|
||||
'title' => t('Ignore (or Unignore) all inbound communications from this connection'),
|
||||
'info' => (intval($contact['abook_ignored']) ? t('This connection is ignored!') : ''),
|
||||
],
|
||||
|
||||
'archive' => [
|
||||
'label' => (intval($contact['abook_archived']) ? t('Unarchive') : t('Archive')),
|
||||
'sel' => (intval($contact['abook_archived']) ? 'active' : ''),
|
||||
'title' => t('Archive (or Unarchive) this connection - mark channel dead but keep content'),
|
||||
'info' => (intval($contact['abook_archived']) ? t('This connection is archived!') : ''),
|
||||
],
|
||||
|
||||
'hide' => [
|
||||
'label' => (intval($contact['abook_hidden']) ? t('Unhide') : t('Hide')),
|
||||
'sel' => (intval($contact['abook_hidden']) ? 'active' : ''),
|
||||
'title' => t('Hide or Unhide this connection from your other connections'),
|
||||
'info' => (intval($contact['abook_hidden']) ? t('This connection is hidden!') : ''),
|
||||
],
|
||||
|
||||
'delete' => [
|
||||
'label' => t('Delete'),
|
||||
'sel' => '',
|
||||
'title' => t('Delete this connection'),
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/group.php');
|
||||
use Zotlabs\Lib\AccessList;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
|
||||
class Contactgroup extends \Zotlabs\Web\Controller {
|
||||
class Contactgroup extends Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
if((argc() > 2) && (intval(argv(1))) && (argv(2))) {
|
||||
$r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
|
||||
dbesc(base64url_decode(argv(2))),
|
||||
@@ -20,9 +20,9 @@ class Contactgroup extends \Zotlabs\Web\Controller {
|
||||
if($r)
|
||||
$change = $r[0]['abook_xchan'];
|
||||
}
|
||||
|
||||
|
||||
if((argc() > 1) && (intval(argv(1)))) {
|
||||
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
@@ -30,25 +30,25 @@ class Contactgroup extends \Zotlabs\Web\Controller {
|
||||
if(! $r) {
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$group = $r[0];
|
||||
$members = group_get_members($group['id']);
|
||||
$members = AccessList::members(local_channel(), $group['id']);
|
||||
$preselected = array();
|
||||
if(count($members)) {
|
||||
foreach($members as $member)
|
||||
$preselected[] = $member['xchan_hash'];
|
||||
}
|
||||
|
||||
|
||||
if($change) {
|
||||
if(in_array($change,$preselected)) {
|
||||
group_rmv_member(local_channel(),$group['gname'],$change);
|
||||
AccessList::member_remove(local_channel(),$group['gname'],$change);
|
||||
}
|
||||
else {
|
||||
group_add_member(local_channel(),$group['gname'],$change);
|
||||
AccessList::member_add(local_channel(),$group['gname'],$change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/group.php');
|
||||
require_once('include/photos.php');
|
||||
|
||||
class Defperms extends Controller {
|
||||
@@ -23,8 +22,8 @@ class Defperms extends Controller {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
|
||||
return;
|
||||
//if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
|
||||
// return;
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
@@ -50,8 +49,8 @@ class Defperms extends Controller {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
|
||||
return;
|
||||
//if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
|
||||
// return;
|
||||
|
||||
$contact_id = intval(argv(1));
|
||||
if(! $contact_id)
|
||||
@@ -183,12 +182,12 @@ class Defperms extends Controller {
|
||||
return login();
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
$papp = Apps::get_papp('Default Permissions');
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
//~ if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
|
||||
//~ //Do not display any associated widgets at this point
|
||||
//~ App::$pdl = '';
|
||||
//~ $papp = Apps::get_papp('Default Permissions');
|
||||
//~ return Apps::app_render($papp, 'module');
|
||||
//~ }
|
||||
|
||||
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
|
||||
$channel = App::get_channel();
|
||||
|
||||
@@ -254,21 +254,21 @@ class Directory extends Controller {
|
||||
$connect_link = '';
|
||||
|
||||
$location = '';
|
||||
if(strlen($rr['locale']))
|
||||
if(isset($rr['locale']))
|
||||
$location .= $rr['locale'];
|
||||
if(strlen($rr['region'])) {
|
||||
if(strlen($rr['locale']))
|
||||
if(isset($rr['region'])) {
|
||||
if($location)
|
||||
$location .= ', ';
|
||||
$location .= $rr['region'];
|
||||
}
|
||||
if(strlen($rr['country'])) {
|
||||
if(strlen($location))
|
||||
if(isset($rr['country'])) {
|
||||
if($location)
|
||||
$location .= ', ';
|
||||
$location .= $rr['country'];
|
||||
}
|
||||
|
||||
$age = '';
|
||||
if(strlen($rr['birthday'])) {
|
||||
if(isset($rr['birthday'])) {
|
||||
if(($years = age($rr['birthday'],'UTC','')) > 0)
|
||||
$age = $years;
|
||||
}
|
||||
|
||||
@@ -56,9 +56,10 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
|
||||
$r = q("select * from dreport where dreport_xchan = '%s' and (dreport_mid = '%s' or dreport_mid = '%s')",
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($mid)
|
||||
dbesc($mid),
|
||||
dbesc(str_replace('/item/', '/activity/', $mid))
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
|
||||
@@ -108,7 +108,7 @@ class Follow extends Controller {
|
||||
}
|
||||
Libsync::build_sync_packet(0, [ 'abook' => [ $clone ] ], true);
|
||||
|
||||
$can_view_stream = their_perms_contains($channel['channel_id'],$clone['abook_xchan'],'view_stream');
|
||||
$can_view_stream = intval(get_abconfig($channel['channel_id'], $clone['abook_xchan'], 'their_perms', 'view_stream'));
|
||||
|
||||
// If we can view their stream, pull in some posts
|
||||
|
||||
@@ -117,7 +117,7 @@ class Follow extends Controller {
|
||||
}
|
||||
|
||||
if ($interactive) {
|
||||
goaway(z_root() . '/connedit/' . $result['abook']['abook_id'] . '?follow=1');
|
||||
goaway(z_root() . '/connections#' . $result['abook']['abook_id']);
|
||||
}
|
||||
else {
|
||||
json_return_and_die([ 'success' => true ]);
|
||||
|
||||
@@ -5,8 +5,7 @@ use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/group.php');
|
||||
use Zotlabs\Lib\AccessList;
|
||||
|
||||
class Group extends Controller {
|
||||
|
||||
@@ -41,16 +40,17 @@ class Group extends Controller {
|
||||
|
||||
$name = notags(trim($_POST['groupname']));
|
||||
$public = intval($_POST['public']);
|
||||
$r = group_add(local_channel(),$name,$public);
|
||||
$r = AccessList::add(local_channel(),$name,$public);
|
||||
$group_hash = $r;
|
||||
|
||||
if($r) {
|
||||
info( t('Privacy group created.') . EOL );
|
||||
}
|
||||
else {
|
||||
notice( t('Could not create privacy group.') . EOL );
|
||||
}
|
||||
goaway(z_root() . '/group');
|
||||
|
||||
}
|
||||
|
||||
if((argc() == 2) && (intval(argv(1)))) {
|
||||
check_form_security_token_redirectOnErr('/group', 'group_edit');
|
||||
|
||||
@@ -65,10 +65,11 @@ class Group extends Controller {
|
||||
}
|
||||
$group = $r[0];
|
||||
$groupname = notags(trim($_POST['groupname']));
|
||||
$group_hash = $group['hash'];
|
||||
$public = intval($_POST['public']);
|
||||
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
|
||||
call_hooks ('privacygroup_extras_post',$hookinfo);
|
||||
call_hooks('privacygroup_extras_post',$hookinfo);
|
||||
|
||||
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
|
||||
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
|
||||
@@ -79,13 +80,25 @@ class Group extends Controller {
|
||||
);
|
||||
if($r)
|
||||
info( t('Privacy group updated.') . EOL );
|
||||
|
||||
|
||||
Libsync::build_sync_packet(local_channel(),null,true);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/group/' . argv(1) . '/' . argv(2));
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$default_group = ((isset($_POST['set_default_group'])) ? $group_hash : (($channel['channel_default_group'] === $group_hash) ? '' : $channel['channel_default_group']));
|
||||
$default_acl = ((isset($_POST['set_default_acl'])) ? '<' . $group_hash . '>' : (($channel['channel_allow_gid'] === '<' . $group_hash . '>') ? '' : $channel['channel_allow_gid']));
|
||||
|
||||
q("update channel set channel_default_group = '%s', channel_allow_gid = '%s'
|
||||
where channel_id = %d",
|
||||
dbesc($default_group),
|
||||
dbesc($default_acl),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet(local_channel(),null,true);
|
||||
|
||||
goaway(z_root() . '/group/' . argv(1) . ((argv(2)) ? '/' . argv(2) : ''));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -117,51 +130,32 @@ class Group extends Controller {
|
||||
|
||||
if((argc() == 1) || ((argc() == 2) && (argv(1) === 'new'))) {
|
||||
|
||||
$new = (((argc() == 2) && (argv(1) === 'new')) ? true : false);
|
||||
|
||||
$groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$i = 0;
|
||||
foreach($groups as $group) {
|
||||
$entries[$i]['name'] = $group['gname'];
|
||||
$entries[$i]['id'] = $group['id'];
|
||||
$entries[$i]['count'] = count(group_get_members($group['id']));
|
||||
$i++;
|
||||
}
|
||||
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ];
|
||||
call_hooks ('privacygroup_extras',$hookinfo);
|
||||
$pgrp_extras = $hookinfo['pgrp_extras'];
|
||||
|
||||
$is_default_acl = ['set_default_acl', t('Post to this group by default'), 0, '', [t('No'), t('Yes')]];
|
||||
$is_default_group = ['set_default_group', t('Add new contacts to this group by default'), 0, '', [t('No'), t('Yes')]];
|
||||
|
||||
|
||||
$tpl = get_markup_template('privacy_groups.tpl');
|
||||
$o = replace_macros($tpl, [
|
||||
'$title' => t('Privacy Groups'),
|
||||
'$add_new_label' => t('Add Group'),
|
||||
'$new' => $new,
|
||||
|
||||
// new group form
|
||||
'$gname' => array('groupname',t('Privacy group name')),
|
||||
'$public' => array('public',t('Members are visible to other channels'), false),
|
||||
'$public' => array('public',t('Members are visible to other channels'), 0, '', [t('No'), t('Yes')]),
|
||||
'$pgrp_extras' => $pgrp_extras,
|
||||
'$form_security_token' => get_form_security_token("group_edit"),
|
||||
'$submit' => t('Submit'),
|
||||
|
||||
// groups list
|
||||
'$title' => t('Privacy Groups'),
|
||||
'$name_label' => t('Name'),
|
||||
'$count_label' => t('Members'),
|
||||
'$entries' => $entries
|
||||
'$is_default_acl' => $is_default_acl,
|
||||
'$is_default_group' => $is_default_group,
|
||||
]);
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$context = array('$submit' => t('Submit'));
|
||||
$tpl = get_markup_template('group_edit.tpl');
|
||||
|
||||
@@ -174,7 +168,7 @@ class Group extends Controller {
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r)
|
||||
$result = group_rmv(local_channel(),$r[0]['gname']);
|
||||
$result = AccessList::remove(local_channel(),$r[0]['gname']);
|
||||
if($result) {
|
||||
$hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ];
|
||||
call_hooks ('privacygroup_extras_drop',$hookinfo);
|
||||
@@ -215,7 +209,7 @@ class Group extends Controller {
|
||||
$group = $r[0];
|
||||
|
||||
|
||||
$members = group_get_members($group['id']);
|
||||
$members = AccessList::members(local_channel(), $group['id']);
|
||||
|
||||
$preselected = array();
|
||||
if(count($members)) {
|
||||
@@ -227,13 +221,13 @@ class Group extends Controller {
|
||||
if($change) {
|
||||
|
||||
if(in_array($change,$preselected)) {
|
||||
group_rmv_member(local_channel(),$group['gname'],$change);
|
||||
AccessList::member_remove(local_channel(),$group['gname'],$change);
|
||||
}
|
||||
else {
|
||||
group_add_member(local_channel(),$group['gname'],$change);
|
||||
AccessList::member_add(local_channel(),$group['gname'],$change);
|
||||
}
|
||||
|
||||
$members = group_get_members($group['id']);
|
||||
$members = AccessList::members(local_channel(), $group['id']);
|
||||
|
||||
$preselected = array();
|
||||
if(count($members)) {
|
||||
@@ -252,9 +246,9 @@ class Group extends Controller {
|
||||
'$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''),
|
||||
'$gid' => $group['id'],
|
||||
'$drop' => $drop_txt,
|
||||
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''),
|
||||
'$public' => array('public',t('Members are visible to other channels'), $group['visible'], '', [t('No'), t('Yes')]),
|
||||
'$form_security_token_edit' => get_form_security_token('group_edit'),
|
||||
'$delete' => t('Delete Group'),
|
||||
'$delete' => t('Delete'),
|
||||
'$form_security_token_drop' => get_form_security_token("group_drop"),
|
||||
'$pgrp_extras' => $pgrp_extras,
|
||||
);
|
||||
@@ -280,7 +274,7 @@ class Group extends Controller {
|
||||
$groupeditor['members'][] = micropro($member,true,'mpgroup', $textmode);
|
||||
}
|
||||
else
|
||||
group_rmv_member(local_channel(),$group['gname'],$member['xchan_hash']);
|
||||
AccessList::member_remove(local_channel(),$group['gname'],$member['xchan_hash']);
|
||||
}
|
||||
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc",
|
||||
@@ -302,6 +296,12 @@ class Group extends Controller {
|
||||
$context['$desc'] = t('Click a channel to toggle membership');
|
||||
$context['$pgrp_extras'] = $pgrp_extras;
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$context['$is_default_acl'] = ['set_default_acl', t('Post to this group by default'), intval($group['hash'] === trim($channel['channel_allow_gid'], '<>')), '', [t('No'), t('Yes')]];
|
||||
$context['$is_default_group'] = ['set_default_group', t('Add new contacts to this group by default'), intval($group['hash'] === $channel['channel_default_group']), '', [t('No'), t('Yes')]];
|
||||
|
||||
|
||||
if($change) {
|
||||
$tpl = get_markup_template('groupeditor.tpl');
|
||||
echo replace_macros($tpl, $context);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Zotlabs\Module;
|
||||
class Hcard extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
if(argc() > 1)
|
||||
$which = argv(1);
|
||||
else {
|
||||
@@ -13,12 +13,12 @@ class Hcard extends \Zotlabs\Web\Controller {
|
||||
\App::$error = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
logger('hcard_request: ' . $which, LOGGER_DEBUG);
|
||||
|
||||
$profile = '';
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||
$which = $channel['channel_address'];
|
||||
$profile = argv(1);
|
||||
@@ -30,22 +30,22 @@ class Hcard extends \Zotlabs\Web\Controller {
|
||||
$profile = '';
|
||||
$profile = $r[0]['profile_guid'];
|
||||
}
|
||||
|
||||
head_add_link( [
|
||||
'rel' => 'alternate',
|
||||
|
||||
head_add_link( [
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/atom+xml',
|
||||
'title' => t('Posts and comments'),
|
||||
'href' => z_root() . '/feed/' . $which
|
||||
]);
|
||||
|
||||
head_add_link( [
|
||||
'rel' => 'alternate',
|
||||
head_add_link( [
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/atom+xml',
|
||||
'title' => t('Only posts'),
|
||||
'href' => z_root() . '/feed/' . $which . '?f=&top=1'
|
||||
]);
|
||||
|
||||
|
||||
|
||||
if(! $profile) {
|
||||
$x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1",
|
||||
dbesc(argv(1))
|
||||
@@ -54,20 +54,20 @@ class Hcard extends \Zotlabs\Web\Controller {
|
||||
\App::$profile = $x[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
profile_load($which,$profile);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
$x = new \Zotlabs\Widget\Profile();
|
||||
$x = new \Zotlabs\Widget\Fullprofile();
|
||||
return $x->widget(array());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$item_hash = '';
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = unpack_link_id(argv(1));
|
||||
}
|
||||
@@ -42,6 +44,9 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
$item_normal_update = item_normal_update();
|
||||
$sys = get_sys_channel();
|
||||
$sys_item = false;
|
||||
$sql_extra = '';
|
||||
|
||||
if(! $item_hash) {
|
||||
$r = q("SELECT mid FROM item
|
||||
@@ -77,11 +82,6 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
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']) . "' ) ";
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$sql_extra = item_permissions_sql($sys['channel_id']);
|
||||
|
||||
$sys_item = false;
|
||||
|
||||
}
|
||||
|
||||
if(! $update) {
|
||||
@@ -99,7 +99,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
|
||||
'default_location' => $channel['channel_location'],
|
||||
'nickname' => $channel['channel_address'],
|
||||
'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||
'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'),
|
||||
'permissions' => $channel_acl,
|
||||
'bang' => '',
|
||||
@@ -114,6 +114,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'reset' => t('Reset form')
|
||||
];
|
||||
|
||||
$a = '';
|
||||
$o = status_editor($a, $x, true);
|
||||
|
||||
}
|
||||
@@ -183,6 +184,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(!$r) {
|
||||
$sys_item = true;
|
||||
$sql_extra = item_permissions_sql($sys['channel_id']);
|
||||
|
||||
$r = q("SELECT item.id AS item_id FROM item
|
||||
LEFT JOIN abook ON item.author_xchan = abook.abook_xchan
|
||||
@@ -209,6 +211,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(!$r) {
|
||||
$sys_item = true;
|
||||
$sql_extra = item_permissions_sql($sys['channel_id']);
|
||||
|
||||
$r = q("SELECT item.parent AS item_id FROM item
|
||||
LEFT JOIN abook ON item.author_xchan = abook.abook_xchan
|
||||
@@ -227,7 +230,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
if($r) {
|
||||
$items = q("SELECT item.*, item.id AS item_id
|
||||
FROM item
|
||||
WHERE parent = '%s' $item_normal ",
|
||||
WHERE parent = '%s' $item_normal $sql_extra",
|
||||
dbesc($r[0]['item_id'])
|
||||
);
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ class Item extends Controller {
|
||||
$consensus = intval($_REQUEST['consensus']);
|
||||
$nocomment = intval($_REQUEST['nocomment']);
|
||||
|
||||
$is_poll = ((trim($_REQUEST['poll_answers'][0]) != '' && trim($_REQUEST['poll_answers'][1]) != '') ? true : false);
|
||||
$is_poll = ((trim((string)$_REQUEST['poll_answers'][0]) != '' && trim((string)$_REQUEST['poll_answers'][1]) != '') ? true : false);
|
||||
|
||||
// 'origin' (if non-zero) indicates that this network is where the message originated,
|
||||
// for the purpose of relaying comments to other conversation members.
|
||||
@@ -416,6 +416,7 @@ class Item extends Controller {
|
||||
|
||||
|
||||
$expires = NULL_DATE;
|
||||
$comments_closed = NULL_DATE;
|
||||
|
||||
$route = '';
|
||||
$parent_item = null;
|
||||
@@ -692,7 +693,9 @@ class Item extends Controller {
|
||||
$postopts = $orig_post['postopts'];
|
||||
$created = $orig_post['created'];
|
||||
$expires = $orig_post['expires'];
|
||||
$comments_closed = $orig_post['comments_closed'];
|
||||
$mid = $orig_post['mid'];
|
||||
$thr_parent = $orig_post['thr_parent'];
|
||||
$parent_mid = $orig_post['parent_mid'];
|
||||
$plink = $orig_post['plink'];
|
||||
}
|
||||
@@ -717,13 +720,13 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
|
||||
$location = notags(trim($_REQUEST['location']));
|
||||
$coord = notags(trim($_REQUEST['coord']));
|
||||
$verb = notags(trim($_REQUEST['verb']));
|
||||
$title = escape_tags(trim($_REQUEST['title']));
|
||||
$summary = trim($_REQUEST['summary']);
|
||||
$body = trim($_REQUEST['body']);
|
||||
$body .= trim($_REQUEST['attachment']);
|
||||
$location = notags(trim((string)$_REQUEST['location']));
|
||||
$coord = notags(trim((string)$_REQUEST['coord']));
|
||||
$verb = notags(trim((string)$_REQUEST['verb']));
|
||||
$title = escape_tags(trim((string)$_REQUEST['title']));
|
||||
$summary = trim((string)$_REQUEST['summary']);
|
||||
$body = trim((string)$_REQUEST['body']);
|
||||
$body .= trim((string)$_REQUEST['attachment']);
|
||||
$postopts = '';
|
||||
|
||||
$allow_empty = ((array_key_exists('allow_empty', $_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
|
||||
@@ -762,7 +765,7 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
|
||||
$mimetype = notags(trim($_REQUEST['mimetype']));
|
||||
$mimetype = notags(trim((string)$_REQUEST['mimetype']));
|
||||
if (!$mimetype)
|
||||
$mimetype = 'text/bbcode';
|
||||
|
||||
@@ -794,13 +797,7 @@ class Item extends Controller {
|
||||
|
||||
// if this is a wall-to-wall post to a group, turn it into a direct message
|
||||
|
||||
$role = get_pconfig($profile_uid, 'system', 'permissions_role');
|
||||
|
||||
$rolesettings = PermissionRoles::role_perms($role);
|
||||
|
||||
$channel_type = isset($rolesettings['channel_type']) ? $rolesettings['channel_type'] : 'normal';
|
||||
|
||||
$is_group = (($channel_type === 'group') ? true : false);
|
||||
$is_group = get_pconfig($profile_uid, 'system', 'group_actor');
|
||||
|
||||
if (($is_group) && ($walltowall) && (!$walltowall_comment)) {
|
||||
$groupww = true;
|
||||
@@ -994,8 +991,9 @@ class Item extends Controller {
|
||||
|
||||
$notify_type = (($parent) ? 'comment-new' : 'wall-new');
|
||||
|
||||
$uuid = (($message_id) ? $message_id : item_message_id());
|
||||
|
||||
if (!$mid) {
|
||||
$uuid = (($message_id) ? $message_id : item_message_id());
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
}
|
||||
|
||||
@@ -1015,10 +1013,23 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
if ($obj) {
|
||||
$obj['url'] = $mid;
|
||||
$obj['attributedTo'] = channel_url($channel);
|
||||
$datarray['obj'] = $obj;
|
||||
$obj_type = 'Question';
|
||||
$obj['url'] = $mid;
|
||||
$obj['id'] = $mid;
|
||||
$obj['diaspora:guid'] = $uuid;
|
||||
$obj['attributedTo'] = channel_url($channel);
|
||||
$obj['published'] = $created;
|
||||
$obj['name'] = $title;
|
||||
|
||||
$datarray['obj'] = $obj;
|
||||
|
||||
if ($obj['endTime']) {
|
||||
$d = datetime_convert('UTC','UTC', $obj['endTime']);
|
||||
if ($d > NULL_DATE) {
|
||||
$comments_closed = $d;
|
||||
}
|
||||
}
|
||||
|
||||
$obj_type = 'Question';
|
||||
}
|
||||
|
||||
if (!$parent_mid) {
|
||||
@@ -1082,6 +1093,7 @@ class Item extends Controller {
|
||||
$datarray['created'] = $created;
|
||||
$datarray['edited'] = (($orig_post) ? datetime_convert() : $created);
|
||||
$datarray['expires'] = $expires;
|
||||
$datarray['comments_closed'] = (($nocomment) ? $created : $comments_closed);
|
||||
$datarray['commented'] = (($orig_post) ? datetime_convert() : $created);
|
||||
$datarray['received'] = (($orig_post) ? datetime_convert() : $created);
|
||||
$datarray['changed'] = (($orig_post) ? datetime_convert() : $created);
|
||||
@@ -1594,6 +1606,8 @@ class Item extends Controller {
|
||||
|
||||
$obj['endTime'] = datetime_convert(date_default_timezone_get(), 'UTC', 'now + ' . $expire_value . ' ' . $expire_unit, ATOM_TIME);
|
||||
|
||||
$obj['directMessage'] = (intval($item['item_private']) === 2);
|
||||
|
||||
if ($item['item_private']) {
|
||||
$obj['to'] = Activity::map_acl($item);
|
||||
}
|
||||
|
||||
@@ -91,6 +91,12 @@ class Like extends Controller {
|
||||
'id' => $arr['item']['id'],
|
||||
'html' => conversation($items, $conv_mode, true, $page_mode),
|
||||
];
|
||||
|
||||
// mod photos
|
||||
if (isset($_REQUEST['reload']) && $_REQUEST['reload']) {
|
||||
$ret['reload'] = 1;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\AccessList;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/security.php');
|
||||
|
||||
class Lockview extends \Zotlabs\Web\Controller {
|
||||
class Lockview extends Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
$atokens = array();
|
||||
$atokens = [];
|
||||
$atoken_xchans = [];
|
||||
$access_list = [];
|
||||
$guest_access_list = [];
|
||||
|
||||
if(local_channel()) {
|
||||
if (local_channel()) {
|
||||
$at = q("select * from atoken where atoken_uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
if($at) {
|
||||
foreach($at as $t) {
|
||||
$atokens[] = atoken_xchan($t);
|
||||
if ($at) {
|
||||
foreach ($at as $t) {
|
||||
$atoken_xchan = atoken_xchan($t);
|
||||
$atokens[] = array_merge($t, $atoken_xchan);
|
||||
$atoken_xchans[] = $atoken_xchan['xchan_hash'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,20 +32,20 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
$type = ((argc() > 1) ? argv(1) : 0);
|
||||
if (is_numeric($type)) {
|
||||
$item_id = intval($type);
|
||||
$type='item';
|
||||
$type = 'item';
|
||||
}
|
||||
else {
|
||||
$item_id = ((argc() > 2) ? intval(argv(2)) : 0);
|
||||
}
|
||||
|
||||
if(! $item_id)
|
||||
if (!$item_id)
|
||||
killme();
|
||||
|
||||
if (! in_array($type, array('item', 'photo', 'attach', 'event', 'menu_item', 'chatroom')))
|
||||
if (!in_array($type, ['item', 'photo', 'attach', 'menu_item', 'chatroom']))
|
||||
killme();
|
||||
|
||||
// we have different naming in in menu_item table and chatroom table
|
||||
switch($type) {
|
||||
switch ($type) {
|
||||
case 'menu_item':
|
||||
$id = 'mitem_id';
|
||||
break;
|
||||
@@ -53,134 +62,177 @@ class Lockview extends \Zotlabs\Web\Controller {
|
||||
intval($item_id)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
if (!$r)
|
||||
killme();
|
||||
|
||||
$item = $r[0];
|
||||
$uid = null;
|
||||
$url = '';
|
||||
|
||||
//we have different naming in in menu_item table and chatroom table
|
||||
switch($type) {
|
||||
switch ($type) {
|
||||
case 'menu_item':
|
||||
$uid = $item['mitem_channel_id'];
|
||||
break;
|
||||
case 'chatroom':
|
||||
$uid = $item['cr_uid'];
|
||||
$uid = $item['cr_uid'];
|
||||
$channel = channelx_by_n($uid);
|
||||
$url = z_root() . '/chat/' . $channel['channel_address'] . '/' . $item['cr_id'];
|
||||
break;
|
||||
case 'item':
|
||||
$uid = $item['uid'];
|
||||
$url = $item['plink'];
|
||||
break;
|
||||
case 'photo':
|
||||
$uid = $item['uid'];
|
||||
$channel = channelx_by_n($uid);
|
||||
$url = z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $item['resource_id'];
|
||||
break;
|
||||
case 'attach':
|
||||
$uid = $item['uid'];
|
||||
$channel = channelx_by_n($uid);
|
||||
$url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $item['display_path'];
|
||||
break;
|
||||
default:
|
||||
$uid = $item['uid'];
|
||||
break;
|
||||
}
|
||||
|
||||
if($uid != local_channel()) {
|
||||
echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>';
|
||||
if (intval($uid) !== local_channel()) {
|
||||
echo '<div class="dropdown-item-text">' . t('Remote privacy information not available') . '</div>';
|
||||
killme();
|
||||
}
|
||||
|
||||
if(intval($item['item_private']) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
|
||||
&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_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>';
|
||||
echo '<div class="dropdown-item-text">' . translate_scope((!$item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>';
|
||||
killme();
|
||||
}
|
||||
|
||||
$allowed_users = expand_acl($item['allow_cid']);
|
||||
$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']);
|
||||
$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);
|
||||
stringify_array_elms($allowed_groups, true);
|
||||
stringify_array_elms($allowed_users, true);
|
||||
stringify_array_elms($deny_groups, true);
|
||||
stringify_array_elms($deny_users, true);
|
||||
|
||||
$allowed_xchans = [];
|
||||
|
||||
$profile_groups = [];
|
||||
if($allowed_groups) {
|
||||
foreach($allowed_groups as $g) {
|
||||
if(substr($g,0,4) === '\'vp.') {
|
||||
$profile_groups[] = '\'' . substr($g,4);
|
||||
if ($allowed_groups) {
|
||||
foreach ($allowed_groups as $g) {
|
||||
if (substr($g, 0, 4) === '\'vp.') {
|
||||
$profile_groups[] = '\'' . substr($g, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count($profile_groups)) {
|
||||
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>';
|
||||
|
||||
if ($profile_groups) {
|
||||
$r = q("SELECT id, profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$pgrp_members = AccessList::profile_members_xchan($uid, $rr['id']);
|
||||
$allowed_xchans = array_merge($allowed_xchans, $pgrp_members);
|
||||
$access_list[] = '<div class="dropdown-item-text" title="' . t('Profile', 'acl') . '">' . $rr['profile_name'] . '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($allowed_groups)) {
|
||||
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>';
|
||||
if ($allowed_groups) {
|
||||
$r = q("SELECT id, gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )");
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$pgrp_members = AccessList::members_xchan($uid, $rr['id']);
|
||||
$allowed_xchans = array_merge($allowed_xchans, $pgrp_members);
|
||||
$access_list[] = '<div class="dropdown-item-text" title="' . t('Privacy group') . '">' . $rr['gname'] . '</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)
|
||||
$l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>';
|
||||
if($atokens) {
|
||||
foreach($atokens as $at) {
|
||||
if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) {
|
||||
$l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>';
|
||||
|
||||
if ($allowed_users) {
|
||||
$r = q("SELECT xchan_name, xchan_hash FROM xchan WHERE xchan_hash IN ( " . implode(', ', $allowed_users) . " )");
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$allowed_xchans[] = $rr['xchan_hash'];
|
||||
if (!in_array($rr['xchan_hash'], $atoken_xchans)) {
|
||||
$access_list[] = '<div class="dropdown-item-text">' . $rr['xchan_name'] . '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$profile_groups = [];
|
||||
if($deny_groups) {
|
||||
foreach($deny_groups as $g) {
|
||||
if(substr($g,0,4) === '\'vp.') {
|
||||
$profile_groups[] = '\'' . substr($g,4);
|
||||
if ($deny_groups) {
|
||||
foreach ($deny_groups as $g) {
|
||||
if (substr($g, 0, 4) === '\'vp.') {
|
||||
$profile_groups[] = '\'' . substr($g, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count($profile_groups)) {
|
||||
|
||||
if ($profile_groups) {
|
||||
$r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )");
|
||||
if($r)
|
||||
foreach($r as $rr)
|
||||
$l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>';
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$access_list[] = '<div class="dropdown-item-text" title="' . t('Profile', 'acl') . '"><strike>' . $rr['profile_name'] . '</strike></b></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(count($deny_groups)) {
|
||||
if ($deny_groups) {
|
||||
$r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $deny_groups) . " )");
|
||||
if($r)
|
||||
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)
|
||||
$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)) {
|
||||
$l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>';
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$access_list[] = '<div class="dropdown-item-text" title="' . t('Privacy group') . '"><strike>' . $rr['gname'] . '</strike></b></div>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
echo $o . implode($l);
|
||||
killme();
|
||||
if ($deny_users) {
|
||||
$r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )");
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$access_list[] = '<div class="dropdown-item-text"><strike>' . $rr['xchan_name'] . '</strike></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($atokens && $allowed_xchans && $url) {
|
||||
|
||||
$guest_access_list = [];
|
||||
|
||||
$allowed_xchans = array_unique($allowed_xchans);
|
||||
foreach ($atokens as $atoken) {
|
||||
if (in_array($atoken['xchan_hash'], $allowed_xchans)) {
|
||||
$guest_access_list[] = '<div class="dropdown-item d-flex justify-content-between cursor-pointer" title="' . sprintf(t('Click to copy link to this ressource for guest %s to clipboard'), $atoken['xchan_name']) . '" data-token="' . $url . '?zat=' . $atoken['atoken_token'] . '" onclick="navigator.clipboard.writeText(this.dataset.token); $.jGrowl(\'' . t('Link copied') . '\', { sticky: false, theme: \'info\', life: 1000 });"><span>' . $atoken['xchan_name'] . '</span><i class="fa fa-copy p-1"></i></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$access_list_header = '';
|
||||
if ($access_list) {
|
||||
$access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>';
|
||||
}
|
||||
|
||||
$guest_access_list_header = '';
|
||||
if ($guest_access_list) {
|
||||
$guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>';
|
||||
}
|
||||
|
||||
$divider = '';
|
||||
if ($access_list && $guest_access_list) {
|
||||
$divider = '<div class="dropdown-divider"></div>';
|
||||
}
|
||||
|
||||
echo $access_list_header . implode($access_list) . $divider . $guest_access_list_header . implode($guest_access_list);
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,15 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\System;
|
||||
use Zotlabs\Render\Theme;
|
||||
|
||||
class Manifest extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
// populate App::$theme_info
|
||||
Theme::current();
|
||||
|
||||
$ret = [
|
||||
'name' => ucfirst(System::get_platform_name()),
|
||||
'short_name' => ucfirst(System::get_platform_name()),
|
||||
@@ -18,12 +22,13 @@ class Manifest extends Controller {
|
||||
[ 'src' => '/images/app/hz-128.png', 'sizes' => '128x128', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-144.png', 'sizes' => '144x144', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-152.png', 'sizes' => '152x152', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png', 'purpose' => 'any maskable' ],
|
||||
[ 'src' => '/images/app/hz-348.png', 'sizes' => '384x384', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz-512.png', 'sizes' => '512x512', 'type' => 'image/png' ],
|
||||
[ 'src' => '/images/app/hz.svg', 'sizes' => '64x64', 'type' => 'image/xml+svg' ]
|
||||
],
|
||||
'theme_color' => '#343a40',
|
||||
'theme_color' => App::$theme_info['theme_color'],
|
||||
'background_color' => App::$theme_info['background_color'],
|
||||
'scope' => '/',
|
||||
'start_url' => z_root(),
|
||||
'display' => 'standalone',
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Group;
|
||||
use Zotlabs\Lib\AccessList;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use App;
|
||||
|
||||
require_once('include/items.php');
|
||||
require_once('include/group.php');
|
||||
require_once('include/contact_widgets.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
@@ -233,7 +232,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
if($group) {
|
||||
|
||||
$contact_str = '';
|
||||
$contacts = group_get_members($group);
|
||||
$contacts = AccessList::members(local_channel(), $group);
|
||||
if($contacts) {
|
||||
$contact_str = ids_to_querystr($contacts, 'xchan', true);
|
||||
}
|
||||
@@ -246,7 +245,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$item_thread_top = '';
|
||||
$sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) ";
|
||||
|
||||
$x = group_rec_byhash(local_channel(), $group_hash);
|
||||
$x = AccessList::by_hash(local_channel(), $group_hash);
|
||||
|
||||
if($x) {
|
||||
$title = replace_macros(get_markup_template('section_title.tpl'), array(
|
||||
@@ -273,15 +272,17 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
// This is for nouveau view public forum cid queries (if a forum notification is clicked)
|
||||
$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
|
||||
intval(local_channel()),
|
||||
intval(TERM_FORUM),
|
||||
dbesc($cid_r[0]['xchan_name'])
|
||||
);
|
||||
//$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
|
||||
//intval(local_channel()),
|
||||
//intval(TERM_FORUM),
|
||||
//dbesc($cid_r[0]['xchan_name'])
|
||||
//);
|
||||
|
||||
$p_str = ids_to_querystr($p, 'parent');
|
||||
if($p_str)
|
||||
$p_sql = " OR item.parent IN ( $p_str ) ";
|
||||
//$p_str = ids_to_querystr($p, 'parent');
|
||||
|
||||
$p_sql = '';
|
||||
//if($p_str)
|
||||
//$p_sql = " OR item.parent IN ( $p_str ) ";
|
||||
|
||||
$sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 $likes_sql ";
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
intval($aid)
|
||||
);
|
||||
if($r && (! intval($r[0]['total']))) {
|
||||
$default_role = get_config('system','default_permissions_role','social');
|
||||
$default_role = get_config('system','default_permissions_role','personal');
|
||||
}
|
||||
|
||||
$limit = account_service_class_fetch(get_account_id(),'total_identities');
|
||||
@@ -170,12 +170,12 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
|
||||
$privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" );
|
||||
|
||||
$perm_roles = \Zotlabs\Access\PermissionRoles::roles();
|
||||
$perm_roles = \Zotlabs\Access\PermissionRoles::channel_roles();
|
||||
|
||||
$name = array('name', t('Channel name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), $name_help, "*");
|
||||
$nickhub = '@' . \App::get_hostname();
|
||||
$nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*");
|
||||
$role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles);
|
||||
$role = array('permissions_role' , t('Channel role'), ($privacy_role) ? $privacy_role : 'personal', '', $perm_roles);
|
||||
|
||||
$o = replace_macros(get_markup_template('new_channel.tpl'), array(
|
||||
'$title' => t('Create a Channel'),
|
||||
|
||||
553
Zotlabs/Module/Pdledit_gui.php
Normal file
553
Zotlabs/Module/Pdledit_gui.php
Normal file
@@ -0,0 +1,553 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Render\Comanche;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Pdledit_gui extends Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if (!local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$_REQUEST['module']) {
|
||||
return;
|
||||
}
|
||||
|
||||
$module = $_REQUEST['module'];
|
||||
|
||||
$ret = [
|
||||
'success' => false,
|
||||
'module' => $module
|
||||
];
|
||||
|
||||
if ($_REQUEST['reset']) {
|
||||
del_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl');
|
||||
Libsync::build_sync_packet();
|
||||
$ret['success'] = true;
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
if ($_REQUEST['save']) {
|
||||
if (!$_REQUEST['data']) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$data = json_decode($_REQUEST['data'],true);
|
||||
$stored_pdl_result = self::get_pdl($module);
|
||||
$pdl = $stored_pdl_result['pdl'];
|
||||
|
||||
foreach ($data as $region => $entries) {
|
||||
$region_pdl = '';
|
||||
foreach ($entries as $entry) {
|
||||
$region_pdl .= base64_decode($entry) . "\r\n";
|
||||
}
|
||||
$pdl = preg_replace('/\[region=' . $region . '\](.*?)\[\/region\]/ism', '[region=' . $region . ']' . "\r\n" . $region_pdl . "\r\n" . '[/region]', $pdl);
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl));
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
$ret['success'] = true;
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
if ($_REQUEST['save_src']) {
|
||||
set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($_REQUEST['src']));
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
$ret['success'] = true;
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
if ($_REQUEST['save_template']) {
|
||||
if (!$_REQUEST['data']) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$template = $_REQUEST['data'][0]['value'];
|
||||
$pdl_result = self::get_pdl($module);
|
||||
$stored_template = self::get_template($pdl_result['pdl']);
|
||||
|
||||
if ($template === $stored_template) {
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl_result['pdl'], $matches);
|
||||
if ($cnt) {
|
||||
$pdl = str_replace('[template]' . $stored_template . '[/template]', '[template]' . $template . '[/template]', $pdl_result['pdl']);
|
||||
}
|
||||
else {
|
||||
$pdl = '[template]' . $template . '[/template]' . "\r\n";
|
||||
$pdl .= $pdl_result['pdl'];
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(), 'system', 'mod_' . $module . '.pdl', escape_tags($pdl));
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
$ret['success'] = true;
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$module = argv(1);
|
||||
|
||||
if (!$module) {
|
||||
goaway(z_root() . '/pdledit_gui/hq');
|
||||
}
|
||||
|
||||
$pdl_result = self::get_pdl($module);
|
||||
|
||||
$pdl = $pdl_result['pdl'];
|
||||
$modified = $pdl_result['modified'];
|
||||
|
||||
if(!$pdl) {
|
||||
return t('Layout not found');
|
||||
}
|
||||
|
||||
$template = self::get_template($pdl);
|
||||
|
||||
$template_info = self::get_template_info($template);
|
||||
|
||||
if(empty($template_info['contentregion'])) {
|
||||
return t('This template does not support pdledi_gui (no content regions defined)');
|
||||
}
|
||||
|
||||
App::$page['template'] = $template;
|
||||
|
||||
$regions = self::get_regions($pdl);
|
||||
|
||||
foreach ($regions as $k => $v) {
|
||||
$region_str = '';
|
||||
if (is_array($v)) {
|
||||
ksort($v);
|
||||
foreach ($v as $entry) {
|
||||
// Get the info from the file and replace entry if we get anything useful
|
||||
$widget_info = get_widget_info($entry['name']);
|
||||
$entry['name'] = (($widget_info['name']) ? $widget_info['name'] : $entry['name']);
|
||||
$entry['desc'] = (($widget_info['description']) ? $widget_info['description'] : $entry['desc']);
|
||||
|
||||
$region_str .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
|
||||
'$entry' => $entry
|
||||
]);
|
||||
}
|
||||
}
|
||||
App::$layout['region_' . $k] = $region_str;
|
||||
}
|
||||
|
||||
$templates = self::get_templates();
|
||||
$templates_html = replace_macros(get_markup_template('pdledit_gui_templates.tpl'), [
|
||||
'$templates' => $templates,
|
||||
'$active' => $template
|
||||
]);
|
||||
|
||||
$items_html = '';
|
||||
|
||||
//$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
|
||||
//'$entry' => [
|
||||
//'type' => 'content',
|
||||
//'name' => t('Main page content'),
|
||||
//'src' => base64_encode('$content')
|
||||
//],
|
||||
//'$disable_controls' => true
|
||||
//]);
|
||||
|
||||
foreach (self::get_widgets($module) as $entry) {
|
||||
$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
|
||||
'$entry' => $entry,
|
||||
'$disable_controls' => true
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (self::get_menus() as $entry) {
|
||||
$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
|
||||
'$entry' => $entry,
|
||||
'$disable_controls' => true
|
||||
]);
|
||||
}
|
||||
|
||||
foreach (self::get_blocks() as $entry) {
|
||||
$items_html .= replace_macros(get_markup_template('pdledit_gui_item.tpl'), [
|
||||
'$entry' => $entry,
|
||||
'$disable_controls' => true
|
||||
]);
|
||||
}
|
||||
|
||||
App::$layout['region_content'] .= replace_macros(get_markup_template('pdledit_gui.tpl'), [
|
||||
'$content_regions' => $template_info['contentregion'],
|
||||
'$page_src' => base64_encode($pdl),
|
||||
'$templates' => base64_encode($templates_html),
|
||||
'$modules' => base64_encode(self::get_modules()),
|
||||
'$items' => base64_encode($items_html),
|
||||
'$module_modified' => $modified,
|
||||
'$module' => $module
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
function get_templates() {
|
||||
$ret = [];
|
||||
|
||||
$files = glob('view/php/*.php');
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$name = basename($f, '.php');
|
||||
$x = get_template_info($name);
|
||||
if(!empty($x['contentregion'])) {
|
||||
$ret[] = [
|
||||
'name' => $name,
|
||||
'desc' => $x['description']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_modules() {
|
||||
$ret = '';
|
||||
|
||||
$files = glob('Zotlabs/Module/*.php');
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$name = lcfirst(basename($f,'.php'));
|
||||
|
||||
if ($name === 'admin' && !is_site_admin()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$x = theme_include('mod_' . $name . '.pdl');
|
||||
if($x) {
|
||||
$ret .= '<div class="mb-2"><a href="pdledit_gui/' . $name . '">' . $name . '</a></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_widgets($module) {
|
||||
$ret = [];
|
||||
|
||||
$checkpaths = [
|
||||
'Zotlabs/Widget/*.php'
|
||||
];
|
||||
|
||||
foreach ($checkpaths as $path) {
|
||||
$files = glob($path);
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$name = lcfirst(basename($f, '.php'));
|
||||
|
||||
$widget_info = get_widget_info($name);
|
||||
if ($widget_info['requires'] && strpos($widget_info['requires'], 'admin') !== false && !is_site_admin()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($widget_info['requires'] && strpos($widget_info['requires'], $module) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ret[] = [
|
||||
'type' => 'widget',
|
||||
'name' => $widget_info['name'] ?? $name,
|
||||
'desc' => $widget_info['description'] ?? '',
|
||||
'src' => base64_encode('[widget=' . $name . '][/widget]')
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_menus() {
|
||||
$ret = [];
|
||||
|
||||
$r = q("select * from menu where menu_channel_id = %d and menu_flags = 0",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
foreach ($r as $rr) {
|
||||
$name = $rr['menu_name'];
|
||||
$desc = $rr['menu_desc'];
|
||||
$ret[] = [
|
||||
'type' => 'menu',
|
||||
'name' => $name,
|
||||
'desc' => $desc,
|
||||
'src' => base64_encode('[menu]' . $name . '[/menu]')
|
||||
];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_blocks() {
|
||||
$ret = [];
|
||||
|
||||
$r = q("select v, title, summary from item join iconfig on iconfig.iid = item.id and item.uid = %d
|
||||
and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
foreach ($r as $rr) {
|
||||
$name = $rr['v'];
|
||||
$desc = (($rr['title']) ? $rr['title'] : $rr['summary']);
|
||||
$ret[] = [
|
||||
'type' => 'block',
|
||||
'name' => $name,
|
||||
'desc' => $desc,
|
||||
'src' => base64_encode('[block]' . $name . '[/block]')
|
||||
];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_template($pdl) {
|
||||
$ret = 'default';
|
||||
|
||||
$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $pdl, $matches);
|
||||
if($cnt && isset($matches[1])) {
|
||||
$ret = trim($matches[1]);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function get_regions($pdl) {
|
||||
$ret = [];
|
||||
$supported_regions = ['aside', 'content', 'right_aside'];
|
||||
|
||||
$cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $pdl, $matches, PREG_SET_ORDER);
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
if (!in_array($mtch[1], $supported_regions)) {
|
||||
continue;
|
||||
}
|
||||
$ret[$mtch[1]] = self::parse_region($mtch[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function parse_region($pdl) {
|
||||
$ret = [];
|
||||
|
||||
$cnt = preg_match_all('/\$content\b/ism', $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
$offset = intval($mtch[0][1]);
|
||||
$name = trim($mtch[0][0]);
|
||||
//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
|
||||
$src = base64_encode($mtch[0][0]);
|
||||
$ret[$offset] = [
|
||||
'type' => 'content',
|
||||
'name' => t('Main page content'),
|
||||
'desc' => t('The main page content can not be edited!'),
|
||||
'src' => $src
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
$offset = intval($mtch[1][1]);
|
||||
$name = trim($mtch[1][0]);
|
||||
//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
|
||||
$src = base64_encode($mtch[0][0]);
|
||||
|
||||
$ret[$offset] = [
|
||||
'type' => 'menu',
|
||||
'name' => $name,
|
||||
'desc' => '',
|
||||
'src' => $src
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// menu class e.g. [menu=horizontal]my_menu[/menu] or [menu=tabbed]my_menu[/menu]
|
||||
// allows different menu renderings to be applied
|
||||
|
||||
//$cnt = preg_match_all("/\[menu=(.*?)\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
//if($cnt) {
|
||||
//foreach($matches as $mtch) {
|
||||
//$s = str_replace($mtch[0],$this->menu(trim($mtch[2]),$mtch[1]),$s);
|
||||
//}
|
||||
//}
|
||||
|
||||
|
||||
$cnt = preg_match_all("/\[block\](.*?)\[\/block\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
$offset = intval($mtch[1][1]);
|
||||
$name = trim($mtch[1][0]);
|
||||
//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
|
||||
$src = base64_encode($mtch[0][0]);
|
||||
$ret[$offset] = [
|
||||
'type' => 'block',
|
||||
'name' => $name,
|
||||
'desc' => '',
|
||||
'src' => $src
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
//$cnt = preg_match_all("/\[block=(.*?)\](.*?)\[\/block\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
//if($cnt) {
|
||||
//foreach($matches as $mtch) {
|
||||
//$s = str_replace($mtch[0],$this->block(trim($mtch[2]),trim($mtch[1])),$s);
|
||||
//}
|
||||
//}
|
||||
|
||||
//$cnt = preg_match_all("/\[js\](.*?)\[\/js\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
//if($cnt) {
|
||||
//foreach($matches as $mtch) {
|
||||
//$s = str_replace($mtch[0],$this->js(trim($mtch[1])),$s);
|
||||
//}
|
||||
//}
|
||||
|
||||
//$cnt = preg_match_all("/\[css\](.*?)\[\/css\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
//if($cnt) {
|
||||
//foreach($matches as $mtch) {
|
||||
//$s = str_replace($mtch[0],$this->css(trim($mtch[1])),$s);
|
||||
//}
|
||||
//}
|
||||
|
||||
// need to modify this to accept parameters
|
||||
|
||||
$cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $pdl, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
|
||||
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
$offset = intval($mtch[1][1]);
|
||||
$name = trim($mtch[1][0]);
|
||||
//$src = base64url_encode(preg_replace(['/\s*\[/', '/\]\s*/'], ['[', ']'], $mtch[0][0]));
|
||||
$src = base64_encode($mtch[0][0]);
|
||||
$ret[$offset] = [
|
||||
'type' => 'widget',
|
||||
'name' => $name,
|
||||
'desc' => '',
|
||||
'src' => $src
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parse template comment in search of template info.
|
||||
*
|
||||
* like
|
||||
* \code
|
||||
* * Name: MyWidget
|
||||
* * Description: A widget
|
||||
* * Version: 1.2.3
|
||||
* * Author: John <profile url>
|
||||
* * Author: Jane <email>
|
||||
* * ContentRegionID: some_id
|
||||
* * ContentRegionID: some_other_id
|
||||
* *
|
||||
*\endcode
|
||||
* @param string $template the name of the template
|
||||
* @return array with the information
|
||||
*/
|
||||
function get_template_info($template){
|
||||
$m = [];
|
||||
$info = [
|
||||
'name' => $template,
|
||||
'description' => '',
|
||||
'author' => [],
|
||||
'maintainer' => [],
|
||||
'version' => '',
|
||||
'contentregion' => []
|
||||
];
|
||||
|
||||
$checkpaths = [
|
||||
'view/php/' . $template . '.php',
|
||||
];
|
||||
|
||||
$template_found = false;
|
||||
|
||||
foreach ($checkpaths as $path) {
|
||||
if (is_file($path)) {
|
||||
$template_found = true;
|
||||
$f = file_get_contents($path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!($template_found && $f))
|
||||
return $info;
|
||||
|
||||
$f = escape_tags($f);
|
||||
$r = preg_match('|/\*.*\*/|msU', $f, $m);
|
||||
|
||||
if ($r) {
|
||||
$ll = explode("\n", $m[0]);
|
||||
foreach($ll as $l) {
|
||||
$l = trim($l, "\t\n\r */");
|
||||
if ($l != ''){
|
||||
list($k, $v) = array_map('trim', explode(':', $l, 2));
|
||||
$k = strtolower($k);
|
||||
if (in_array($k, ['author', 'maintainer'])){
|
||||
$r = preg_match('|([^<]+)<([^>]+)>|', $v, $m);
|
||||
if ($r) {
|
||||
$info[$k][] = array('name' => $m[1], 'link' => $m[2]);
|
||||
} else {
|
||||
$info[$k][] = array('name' => $v);
|
||||
}
|
||||
}
|
||||
elseif (in_array($k, ['contentregion'])){
|
||||
$info[$k][] = array_map('trim', explode(',', $v));
|
||||
}
|
||||
else {
|
||||
$info[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
function get_pdl($module) {
|
||||
$ret = [
|
||||
'pdl' => null,
|
||||
'modified' => true
|
||||
];
|
||||
|
||||
$pdl_path = 'mod_' . $module . '.pdl';
|
||||
|
||||
$ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl_path);
|
||||
|
||||
if(!$ret['pdl']) {
|
||||
$pdl_path = theme_include($pdl_path);
|
||||
if ($pdl_path) {
|
||||
$ret['pdl'] = file_get_contents($pdl_path);
|
||||
$ret['modified'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -3,49 +3,156 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\AccessList;
|
||||
use Zotlabs\Lib\Permcat;
|
||||
|
||||
class Permcats extends Controller {
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Permission Categories'))
|
||||
if (!local_channel())
|
||||
return;
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/permcats', 'permcats');
|
||||
|
||||
$name = escape_tags(trim($_REQUEST['name']));
|
||||
$is_system_role = isset($_REQUEST['is_system_role']);
|
||||
$return_path = z_root() . '/permcats/' . $_REQUEST['return_path'];
|
||||
$group_hash = $_REQUEST['group_select'] ?? '';
|
||||
$deleted_role = $_REQUEST['deleted_role'] ?? '';
|
||||
$new_role = $_REQUEST['new_role'] ?? '';
|
||||
$contacts = [];
|
||||
|
||||
$all_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
|
||||
$name = escape_tags(trim($_POST['name']));
|
||||
if(! $name) {
|
||||
notice( t('Permission category name is required.') . EOL);
|
||||
if (argv(1) && hex2bin(argv(1)) !== $name) {
|
||||
$return_path = z_root() . '/permcats/' . bin2hex($name);
|
||||
}
|
||||
|
||||
if ($deleted_role && $new_role) {
|
||||
$r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d AND abook_role = '%s' AND abook_self = 0 AND abook_pending = 0",
|
||||
intval(local_channel()),
|
||||
dbesc($deleted_role)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$contacts = ids_to_array($r, 'abook_xchan');
|
||||
}
|
||||
|
||||
if ($contacts) {
|
||||
Permcat::assign($channel, $new_role, $contacts);
|
||||
}
|
||||
|
||||
Permcat::delete(local_channel(), $deleted_role);
|
||||
|
||||
$default_role = get_pconfig(local_channel(), 'system', 'default_permcat', 'default');
|
||||
if ($deleted_role === $default_role) {
|
||||
set_pconfig(local_channel(), 'system', 'default_permcat', $new_role);
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
info(t('Contact role deleted.') . EOL);
|
||||
|
||||
goaway(z_root() . '/permcats/' . bin2hex($new_role));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($group_hash === 'all_contacts') {
|
||||
$r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d and abook_self = 0 and abook_pending = 0",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$pcarr = [];
|
||||
if ($r) {
|
||||
$contacts = ids_to_array($r, 'abook_xchan');
|
||||
}
|
||||
}
|
||||
|
||||
if($all_perms) {
|
||||
foreach($all_perms as $perm => $desc) {
|
||||
if(array_key_exists('perms_' . $perm, $_POST)) {
|
||||
$group = null;
|
||||
if (!$contacts && $group_hash) {
|
||||
$group = AccessList::by_hash(local_channel(), $group_hash);
|
||||
}
|
||||
|
||||
if ($group) {
|
||||
$contacts = AccessList::members_xchan(local_channel(), $group['id']);
|
||||
}
|
||||
|
||||
if (!$name) {
|
||||
notice(t('Permission category name is required.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(), 'system', 'default_permcat', 'default');
|
||||
|
||||
if (isset($_REQUEST['default_role'])) {
|
||||
set_pconfig(local_channel(), 'system', 'default_permcat', $name);
|
||||
}
|
||||
|
||||
if ($is_system_role) {
|
||||
// if we have a system role just set the default and assign if aplicable and be done with it
|
||||
if ($contacts) {
|
||||
Permcat::assign($channel, $name, $contacts);
|
||||
}
|
||||
|
||||
info(t('Contact role saved.') . EOL);
|
||||
Libsync::build_sync_packet();
|
||||
goaway($return_path);
|
||||
return;
|
||||
}
|
||||
|
||||
$pcarr = [];
|
||||
$all_perms = Permissions::Perms();
|
||||
|
||||
if ($all_perms) {
|
||||
foreach ($all_perms as $perm => $desc) {
|
||||
if (array_key_exists('perms_' . $perm, $_POST)) {
|
||||
$pcarr[] = $perm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr);
|
||||
$pcat = new Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$existing_raw_perms = [];
|
||||
|
||||
if ($pcatlist) {
|
||||
foreach ($pcatlist as $pc) {
|
||||
if ($pc['name'] && ($pc['name'] === $name)) {
|
||||
$existing_raw_perms = $pc['raw_perms'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$contacts && array_diff_assoc($existing_raw_perms, Permissions::FilledPerms($pcarr))) {
|
||||
// If we don't have anyone to assign the role to and an existing role has changed,
|
||||
// we will re-assign the changed role to all its members if there are any.
|
||||
|
||||
$r = q("SELECT abook_xchan FROM abook WHERE abook_channel = %d AND abook_role = '%s' AND abook_self = 0 AND abook_pending = 0",
|
||||
intval(local_channel()),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$contacts = ids_to_array($r, 'abook_xchan');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Permcat::update(local_channel(), $name, $pcarr);
|
||||
|
||||
if ($contacts) {
|
||||
Permcat::assign($channel, $name, $contacts);
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
info( t('Permission category saved.') . EOL);
|
||||
info(t('Contact role saved.') . EOL);
|
||||
goaway($return_path);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -53,79 +160,107 @@ class Permcats extends Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
if (!local_channel())
|
||||
return EMPTY_STR;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
$papp = Apps::get_papp('Permission Categories');
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
nav_set_selected('Contact Roles');
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if(argc() > 1)
|
||||
$name = '';
|
||||
if (argc() > 1) {
|
||||
$name = hex2bin(argv(1));
|
||||
|
||||
if(argc() > 2 && argv(2) === 'drop') {
|
||||
\Zotlabs\Lib\Permcat::delete(local_channel(),$name);
|
||||
Libsync::build_sync_packet();
|
||||
json_return_and_die([ 'success' => true ]);
|
||||
}
|
||||
|
||||
$perms = [];
|
||||
$existing = [];
|
||||
$pcat = new Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$is_system_role = false;
|
||||
$delete_role_select_options = [];
|
||||
$is_default_role = (get_pconfig(local_channel(), 'system', 'default_permcat', 'default') === $name);
|
||||
$localname = '';
|
||||
|
||||
$desc = t('Use this form to create permission rules for various classes of people or connections.');
|
||||
|
||||
$existing = [];
|
||||
|
||||
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$permcats = [];
|
||||
if($pcatlist) {
|
||||
foreach($pcatlist as $pc) {
|
||||
if(($pc['name']) && ($name) && ($pc['name'] == $name))
|
||||
if ($pcatlist) {
|
||||
foreach ($pcatlist as $pc) {
|
||||
if ($pc['name'] && $name && ($pc['name'] === $name)) {
|
||||
$existing = $pc['perms'];
|
||||
if(! $pc['system'])
|
||||
$permcats[bin2hex($pc['name'])] = $pc['localname'];
|
||||
if (isset($pc['system']) && intval($pc['system']))
|
||||
$is_system_role = $pc['name'];
|
||||
}
|
||||
|
||||
if ($pc['name'] == $name) {
|
||||
$localname = $pc['localname'];
|
||||
}
|
||||
|
||||
if ($pc['name'] !== $name) {
|
||||
$delete_role_select_options[$pc['name']] = $pc['localname'];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
// select for delete action
|
||||
$delete_role_select = [
|
||||
'new_role',
|
||||
(($is_default_role) ? t('Role to assign affected contacts and default role to') : t('Role to assign affected contacts to')),
|
||||
'',
|
||||
'',
|
||||
$delete_role_select_options
|
||||
];
|
||||
|
||||
foreach($global_perms as $k => $v) {
|
||||
$thisperm = \Zotlabs\Lib\Permcat::find_permcat($existing,$k);
|
||||
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
|
||||
$global_perms = Permissions::Perms();
|
||||
|
||||
if($existing[$k])
|
||||
$thisperm = "1";
|
||||
foreach ($global_perms as $k => $v) {
|
||||
$thisperm = Permcat::find_permcat($existing, $k);
|
||||
$checkinherited = PermissionLimits::Get(local_channel(), $k);
|
||||
|
||||
$perms[] = array('perms_' . $k, $v, '',$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
|
||||
if ($existing[$k])
|
||||
$thisperm = 1;
|
||||
|
||||
$perms[] = [
|
||||
'perms_' . $k,
|
||||
$v,
|
||||
'',
|
||||
$thisperm,
|
||||
1,
|
||||
(($checkinherited & PERMS_SPECIFIC) ? '' : '1'),
|
||||
'',
|
||||
$checkinherited
|
||||
];
|
||||
}
|
||||
|
||||
$group_select_options = [
|
||||
'selected' => '',
|
||||
'form_id' => 'group_select',
|
||||
'label' => t('Assign this role to'),
|
||||
'after' => [
|
||||
'name' => t('All my contacts'),
|
||||
'id' => 'all_contacts',
|
||||
'selected' => false
|
||||
]
|
||||
];
|
||||
|
||||
$group_select = AccessList::select(local_channel(), $group_select_options);
|
||||
|
||||
$tpl = get_markup_template("permcats.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
$o = replace_macros($tpl, [
|
||||
'$form_security_token' => get_form_security_token("permcats"),
|
||||
'$title' => t('Permission Categories'),
|
||||
'$desc' => $desc,
|
||||
'$desc2' => $desc2,
|
||||
'$tokens' => $t,
|
||||
'$permcats' => $permcats,
|
||||
'$atoken' => $atoken,
|
||||
'$url1' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'$url2' => z_root() . '/photos/' . $channel['channel_address'],
|
||||
'$name' => array('name', t('Permission category name') . ' <span class="required">*</span>', (($name) ? $name : ''), ''),
|
||||
'$me' => t('My Settings'),
|
||||
'$perms' => $perms,
|
||||
'$inherited' => t('inherited'),
|
||||
'$notself' => 0,
|
||||
'$self' => 1,
|
||||
'$permlbl' => t('Individual Permissions'),
|
||||
'$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
'$default_role' => ['default_role', t('Automatically assign this role to new contacts'), intval($is_default_role), '', [t('No'), t('Yes')]],
|
||||
'$title' => t('Contact Roles'),
|
||||
'$name' => ['name', t('Role name') . ' <span class="required">*</span>', (($localname) ? $localname : ''), (($is_system_role) ? t('System role - not editable') : ''), '', (($is_system_role) ? 'disabled' : '')],
|
||||
'$delete_label' => t('Deleting') . ' ' . $localname,
|
||||
'$current_role' => $name,
|
||||
'$perms' => $perms,
|
||||
'$inherited' => t('inherited'),
|
||||
'$is_system_role' => $is_system_role,
|
||||
'$permlbl' => t('Role Permissions'),
|
||||
'$permnote' => t('Some permissions may be inherited from your <a href="settings">channel role</a>, which have higher priority than contact role settings.'),
|
||||
'$submit' => t('Submit'),
|
||||
'$return_path' => argv(1),
|
||||
'$group_select' => $group_select,
|
||||
'$delete_role_select' => $delete_role_select,
|
||||
'$delet_role_button' => t('Delete')
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
/*
|
||||
* @file Profile_photo.php
|
||||
@@ -15,109 +19,123 @@ require_once('include/photos.php');
|
||||
require_once('include/channel.php');
|
||||
|
||||
/* @brief Function for sync'ing permissions of profile-photos and their profile
|
||||
*
|
||||
* @param $profileid The id number of the profile to sync
|
||||
* @return void
|
||||
*/
|
||||
*
|
||||
*/
|
||||
class Profile_photo extends Controller {
|
||||
|
||||
|
||||
class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
/* @brief Initalize the profile-photo edit view
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel()) {
|
||||
|
||||
if (!local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
profile_load($channel['channel_address']);
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
$profile = App::$argv[1];
|
||||
|
||||
profile_load($channel['channel_address'], $profile);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* @brief Evaluate posted values
|
||||
*
|
||||
* @param $a Current application
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel()) {
|
||||
|
||||
if (!local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
// Remove cover photo
|
||||
if(isset($_POST['remove'])) {
|
||||
|
||||
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$sync = attach_export_data($channel,$r[0]['resource_id']);
|
||||
if($sync)
|
||||
Libsync:: build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
|
||||
$r = q("select id, profile_guid, is_default, gender from profile where uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$profile_id = intval($_POST['profile']);
|
||||
$default_profile_id = null;
|
||||
$profile = [];
|
||||
|
||||
foreach ($r as $rr) {
|
||||
if ($rr['is_default']) {
|
||||
$default_profile_id = intval($rr['id']);
|
||||
}
|
||||
|
||||
if ($profile_id === intval($rr['id'])) {
|
||||
$profile = $rr;
|
||||
}
|
||||
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
}
|
||||
|
||||
if((array_key_exists('cropfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
|
||||
|
||||
|
||||
$is_default_profile = ($profile_id === $default_profile_id);
|
||||
|
||||
// Remove profile photo
|
||||
if (isset($_POST['remove'])) {
|
||||
|
||||
if ($is_default_profile) {
|
||||
|
||||
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
|
||||
dbesc(z_root() . '/photo/profile/l/' . local_channel()),
|
||||
dbesc(z_root() . '/photo/profile/m/' . local_channel()),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
|
||||
dbesc(z_root() . '/' . get_default_profile_photo(300)),
|
||||
dbesc(z_root() . '/' . get_default_profile_photo(80)),
|
||||
intval($profile_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
$sync = attach_export_data($channel, $r[0]['resource_id']);
|
||||
if ($sync)
|
||||
Libsync:: build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
|
||||
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
||||
goaway(z_root() . '/profiles/' . $profile_id);
|
||||
}
|
||||
|
||||
if ((array_key_exists('cropfinal', $_POST)) && (intval($_POST['cropfinal']) == 1)) {
|
||||
|
||||
// logger('crop: ' . print_r($_POST,true));
|
||||
|
||||
// phase 2 - we have finished cropping
|
||||
|
||||
if(argc() != 2) {
|
||||
notice( t('Image uploaded but image cropping failed.') . EOL );
|
||||
|
||||
if (argc() != 2) {
|
||||
notice(t('Image uploaded but image cropping failed.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$image_id = argv(1);
|
||||
|
||||
if(substr($image_id,-2,1) == '-') {
|
||||
$scale = substr($image_id,-1,1);
|
||||
$image_id = substr($image_id,0,-2);
|
||||
|
||||
if (substr($image_id, -2, 1) == '-') {
|
||||
$scale = substr($image_id, -1, 1);
|
||||
$image_id = substr($image_id, 0, -2);
|
||||
}
|
||||
|
||||
|
||||
// unless proven otherwise
|
||||
$is_default_profile = 1;
|
||||
|
||||
if($_REQUEST['profile']) {
|
||||
$r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
|
||||
intval($_REQUEST['profile']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$profile = $r[0];
|
||||
if(! intval($profile['is_default']))
|
||||
$is_default_profile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$srcX = intval($_POST['xstart']);
|
||||
$srcY = intval($_POST['ystart']);
|
||||
$srcW = intval($_POST['xfinal']) - $srcX;
|
||||
@@ -126,45 +144,45 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1",
|
||||
dbesc($image_id),
|
||||
dbesc(local_channel()),
|
||||
intval($scale));
|
||||
if($r) {
|
||||
|
||||
$base_image = $r[0];
|
||||
intval($scale)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
|
||||
$base_image = $r[0];
|
||||
$base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
|
||||
|
||||
|
||||
$im = photo_factory($base_image['content'], $base_image['mimetype']);
|
||||
if($im->is_valid()) {
|
||||
|
||||
$im->cropImage(300,$srcX,$srcY,$srcW,$srcH);
|
||||
|
||||
if ($im->is_valid()) {
|
||||
|
||||
$im->cropImage(300, $srcX, $srcY, $srcW, $srcH);
|
||||
|
||||
$aid = get_account_id();
|
||||
|
||||
$p = [
|
||||
'aid' => $aid,
|
||||
'uid' => local_channel(),
|
||||
|
||||
$p = [
|
||||
'aid' => $aid,
|
||||
'uid' => local_channel(),
|
||||
'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'],
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Profile Photos'),
|
||||
'os_path' => $base_image['os_path'],
|
||||
'display_path' => $base_image['display_path'],
|
||||
'photo_usage' => PHOTO_PROFILE,
|
||||
'edited' => dbescdate($base_image['edited'])
|
||||
'photo_usage' => (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL),
|
||||
'edited' => dbescdate($base_image['edited'])
|
||||
];
|
||||
|
||||
$p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
|
||||
|
||||
|
||||
$r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300);
|
||||
|
||||
|
||||
$im->scaleImage(80);
|
||||
$r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80);
|
||||
|
||||
|
||||
$im->scaleImage(48);
|
||||
$r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48);
|
||||
|
||||
if($r1 === false || $r2 === false || $r3 === false) {
|
||||
if ($r1 === false || $r2 === false || $r3 === false) {
|
||||
// if one failed, delete them all so we can start over.
|
||||
notice( t('Image resize failed.') . EOL );
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )",
|
||||
notice(t('Image resize failed.') . EOL);
|
||||
q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d )",
|
||||
dbesc($base_image['resource_id']),
|
||||
local_channel(),
|
||||
intval(PHOTO_RES_PROFILE_300),
|
||||
@@ -179,59 +197,55 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
intval(PHOTO_RES_PROFILE_80),
|
||||
intval(PHOTO_RES_PROFILE_48)
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
if ($x) {
|
||||
foreach ($x as $xx) {
|
||||
@unlink(dbunescbin($xx['content']));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If setting for the default profile, unset the profile photo flag from any other photos I own
|
||||
|
||||
if($is_default_profile) {
|
||||
|
||||
$r = q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
|
||||
// If setting for the default profile, unset the profile photo flag from any other photos I own
|
||||
|
||||
if ($is_default_profile) {
|
||||
q("update profile set photo = '%s', thumb = '%s' where is_default = 1 and uid = %d",
|
||||
dbesc(z_root() . '/photo/profile/l/' . local_channel()),
|
||||
dbesc(z_root() . '/photo/profile/m/' . local_channel()),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
$r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d
|
||||
q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d
|
||||
AND resource_id != '%s' AND uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
dbesc($base_image['resource_id']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
send_profile_photo_activity($channel,$base_image,$profile);
|
||||
|
||||
send_profile_photo_activity($channel, $base_image, $profile);
|
||||
}
|
||||
else {
|
||||
$r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
|
||||
q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
|
||||
dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-4'),
|
||||
dbesc(z_root() . '/photo/' . $base_image['resource_id'] . '-5'),
|
||||
intval($_REQUEST['profile']),
|
||||
intval($profile_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
// set $send to false in profiles_build_sync() to return the data
|
||||
// so that we only send one sync packet.
|
||||
|
||||
$sync_profiles = profiles_build_sync(local_channel(),false);
|
||||
|
||||
// set $send to false in profiles_build_sync() to return the data
|
||||
// so that we only send one sync packet.
|
||||
|
||||
$sync_profiles = profiles_build_sync(local_channel(), false);
|
||||
|
||||
// We'll set the updated profile-photo timestamp even if it isn't the default profile,
|
||||
// so that browsers will do a cache update unconditionally
|
||||
// Also set links back to site-specific profile photo url in case it was
|
||||
// changed to a generic URL by a clone operation. Otherwise the new photo may
|
||||
// changed to a generic URL by a clone operation. Otherwise the new photo may
|
||||
// not get pushed to other sites correctly.
|
||||
|
||||
$r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
|
||||
|
||||
q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
|
||||
where xchan_hash = '%s'",
|
||||
dbesc($im->getType()),
|
||||
dbescdate($base_image['edited']),
|
||||
@@ -241,341 +255,372 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
|
||||
photo_profile_setperms(local_channel(),$base_image['resource_id'],$_REQUEST['profile']);
|
||||
photo_profile_setperms(local_channel(), $base_image['resource_id'], $profile_id);
|
||||
|
||||
$sync = attach_export_data($channel,$base_image['resource_id']);
|
||||
if($sync)
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles));
|
||||
$sync = attach_export_data($channel, $base_image['resource_id']);
|
||||
if ($sync)
|
||||
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync], 'profile' => $sync_profiles]);
|
||||
|
||||
|
||||
// Similarly, tell the nav bar to bypass the cache and update the avatar image.
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
||||
info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
|
||||
|
||||
|
||||
info(t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
|
||||
|
||||
// Update directory in background
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
|
||||
|
||||
Master::Summon(['Directory', $channel['channel_id']]);
|
||||
|
||||
}
|
||||
else
|
||||
notice( t('Unable to process image') . EOL);
|
||||
notice(t('Unable to process image') . EOL);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
|
||||
goaway(z_root() . '/profiles/' . $profile_id);
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
// A new photo was uploaded. Store it and save some important details
|
||||
// in App::$data for use in the cropping function
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$importing = false;
|
||||
$smallest = 0;
|
||||
|
||||
|
||||
if($_REQUEST['importfile']) {
|
||||
$hash = $_REQUEST['importfile'];
|
||||
$hash = photo_new_resource();
|
||||
$importing = false;
|
||||
$smallest = 0;
|
||||
|
||||
if ($_REQUEST['importfile']) {
|
||||
$hash = $_REQUEST['importfile'];
|
||||
$importing = true;
|
||||
}
|
||||
else {
|
||||
require_once('include/attach.php');
|
||||
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true));
|
||||
|
||||
logger('attach_store: ' . print_r($res,true));
|
||||
|
||||
$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) {
|
||||
logger('Content-Range: ' . print_r($matches, true));
|
||||
$partial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($partial) {
|
||||
$x = save_chunk($channel, $matches[1], $matches[2], $matches[3]);
|
||||
|
||||
if ($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
json_return_and_die($x);
|
||||
}
|
||||
else {
|
||||
header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
|
||||
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $x['name'],
|
||||
'type' => $x['type'],
|
||||
'tmp_name' => $x['tmp_name'],
|
||||
'error' => $x['error'],
|
||||
'size' => $x['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!array_key_exists('userfile', $_FILES)) {
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $_FILES['files']['name'],
|
||||
'type' => $_FILES['files']['type'],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'],
|
||||
'error' => $_FILES['files']['error'],
|
||||
'size' => $_FILES['files']['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$res = attach_store(App::get_channel(), get_observer_hash(), '', ['album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true, 'source' => 'photos']);
|
||||
|
||||
json_return_and_die(['message' => $hash]);
|
||||
|
||||
}
|
||||
|
||||
if(($res && intval($res['data']['is_photo'])) || $importing) {
|
||||
|
||||
if (($res && intval($res['data']['is_photo'])) || $importing) {
|
||||
$i = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale",
|
||||
dbesc($hash),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if(! $i) {
|
||||
notice( t('Image upload failed.') . EOL );
|
||||
|
||||
if (!$i) {
|
||||
notice(t('Image upload failed.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$os_storage = false;
|
||||
|
||||
foreach($i as $ii) {
|
||||
if(intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
|
||||
foreach ($i as $ii) {
|
||||
if (intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
$os_storage = intval($ii['os_storage']);
|
||||
$imagedata = $ii['content'];
|
||||
$filetype = $ii['mimetype'];
|
||||
$imagedata = $ii['content'];
|
||||
$filetype = $ii['mimetype'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$imagedata = (($os_storage) ? @file_get_contents(dbunescbin($imagedata)) : dbunescbin($imagedata));
|
||||
$ph = photo_factory($imagedata, $filetype);
|
||||
|
||||
if(! $ph->is_valid()) {
|
||||
notice( t('Unable to process image.') . EOL );
|
||||
$ph = photo_factory($imagedata, $filetype);
|
||||
|
||||
if (!$ph->is_valid()) {
|
||||
notice(t('Unable to process image.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
|
||||
|
||||
return $this->profile_photo_crop_ui_head($ph, $hash, $smallest);
|
||||
|
||||
// This will "fall through" to the get() method, and since
|
||||
// App::$data['imagecrop'] is set, it will proceed to cropping
|
||||
// rather than present the upload form
|
||||
// App::$data['imagecrop'] is set, it will proceed to cropping
|
||||
// rather than present the upload form
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* @brief Generate content of profile-photo view
|
||||
*
|
||||
* @param $a Current application
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
|
||||
if (!local_channel()) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
$pf = 0;
|
||||
$newuser = false;
|
||||
|
||||
if(argc() == 2 && argv(1) === 'new')
|
||||
$newuser = true;
|
||||
|
||||
if(argv(1) === 'use') {
|
||||
|
||||
$channel = App::get_channel();
|
||||
$profile_id = (($_REQUEST['profile']) ? intval($_REQUEST['profile']) : intval(argv(1)));
|
||||
$default_profile_id = null;
|
||||
|
||||
$r = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
||||
foreach ($r as $rr) {
|
||||
if ($rr['is_default']) {
|
||||
$default_profile_id = intval($rr['id']);
|
||||
}
|
||||
|
||||
if ($profile_id === intval($rr['id'])) {
|
||||
$profile = $rr;
|
||||
}
|
||||
}
|
||||
|
||||
$is_default_profile = ($profile_id === $default_profile_id);
|
||||
|
||||
if (argv(1) === 'use') {
|
||||
if (argc() < 3) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
$resource_id = argv(2);
|
||||
|
||||
|
||||
$pf = (($_REQUEST['pf']) ? intval($_REQUEST['pf']) : 0);
|
||||
|
||||
$c = q("select id, is_default from profile where uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$multi_profiles = true;
|
||||
|
||||
if(($c) && (count($c) === 1) && (intval($c[0]['is_default']))) {
|
||||
$_REQUEST['profile'] = $c[0]['id'];
|
||||
$multi_profiles = false;
|
||||
}
|
||||
else {
|
||||
$_REQUEST['profile'] = $pf;
|
||||
}
|
||||
|
||||
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC",
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if(! $r) {
|
||||
notice( t('Photo not available.') . EOL );
|
||||
if (!$r) {
|
||||
notice(t('Photo not available.') . EOL);
|
||||
return;
|
||||
}
|
||||
$havescale = false;
|
||||
foreach($r as $rr) {
|
||||
if($rr['imgscale'] == PHOTO_RES_PROFILE_80)
|
||||
foreach ($r as $rr) {
|
||||
if ($rr['imgscale'] == PHOTO_RES_PROFILE_80)
|
||||
$havescale = true;
|
||||
}
|
||||
|
||||
|
||||
// set an already loaded and cropped photo as profile photo
|
||||
|
||||
if($havescale) {
|
||||
// unset any existing profile photos
|
||||
$x = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
|
||||
if ($havescale) {
|
||||
|
||||
if ($is_default_profile) {
|
||||
|
||||
// unset any existing profile photos
|
||||
q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_PROFILE),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$edited = datetime_convert();
|
||||
|
||||
q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
|
||||
intval(PHOTO_PROFILE),
|
||||
dbescdate($edited),
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
|
||||
dbescdate($edited),
|
||||
dbesc($channel['xchan_hash'])
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
|
||||
dbesc(z_root() . '/photo/' . $resource_id . '-4'),
|
||||
dbesc(z_root() . '/photo/' . $resource_id . '-5'),
|
||||
intval($profile_id),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$edited = datetime_convert();
|
||||
|
||||
$x = q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
|
||||
intval(PHOTO_PROFILE),
|
||||
dbescdate($edited),
|
||||
intval(local_channel()),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
$x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
|
||||
dbescdate($edited),
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
|
||||
photo_profile_setperms(local_channel(),$resource_id,$_REQUEST['profile']);
|
||||
photo_profile_setperms(local_channel(), $resource_id, $profile_id);
|
||||
|
||||
$sync = attach_export_data($channel,$resource_id);
|
||||
if($sync)
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
$sync = attach_export_data($channel, $resource_id);
|
||||
if ($sync)
|
||||
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
|
||||
|
||||
$_SESSION['reload_avatar'] = true;
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
|
||||
|
||||
goaway(z_root() . '/profiles');
|
||||
Master::Summon(['Directory', local_channel()]);
|
||||
|
||||
goaway(z_root() . '/profiles/' . $profile_id);
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
|
||||
intval($r[0]['id']),
|
||||
intval(local_channel())
|
||||
|
||||
|
||||
);
|
||||
if(! $r) {
|
||||
notice( t('Photo not available.') . EOL );
|
||||
if (!$r) {
|
||||
notice(t('Photo not available.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(intval($r[0]['os_storage']))
|
||||
|
||||
if (intval($r[0]['os_storage'])) {
|
||||
$data = @file_get_contents(dbunescbin($r[0]['content']));
|
||||
else
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
|
||||
$ph = photo_factory($data, $r[0]['mimetype']);
|
||||
}
|
||||
else {
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
}
|
||||
|
||||
$ph = photo_factory($data, $r[0]['mimetype']);
|
||||
$smallest = 0;
|
||||
if($ph->is_valid()) {
|
||||
|
||||
if ($ph->is_valid()) {
|
||||
|
||||
// go ahead as if we have just uploaded a new photo to crop
|
||||
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d order by imgscale",
|
||||
dbesc($r[0]['resource_id']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($i) {
|
||||
|
||||
if ($i) {
|
||||
$hash = $i[0]['resource_id'];
|
||||
foreach($i as $ii) {
|
||||
if(intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
foreach ($i as $ii) {
|
||||
if (intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($multi_profiles) {
|
||||
\App::$data['importfile'] = $resource_id;
|
||||
}
|
||||
else {
|
||||
$this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
|
||||
}
|
||||
}
|
||||
|
||||
$this->profile_photo_crop_ui_head($ph, $hash, $smallest);
|
||||
|
||||
// falls through with App::$data['imagecrop'] set so we go straight to the cropping section
|
||||
|
||||
}
|
||||
|
||||
|
||||
// present an upload form
|
||||
|
||||
$profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
|
||||
intval(local_channel())
|
||||
);
|
||||
$importing = ((array_key_exists('importfile', App::$data)) ? true : false);
|
||||
|
||||
if($profiles) {
|
||||
for($x = 0; $x < count($profiles); $x ++) {
|
||||
$profiles[$x]['selected'] = false;
|
||||
if($pf && $profiles[$x]['id'] == $pf)
|
||||
$profiles[$x]['selected'] = true;
|
||||
if((! $pf) && $profiles[$x]['is_default'])
|
||||
$profiles[$x]['selected'] = true;
|
||||
}
|
||||
}
|
||||
if (!x(App::$data, 'imagecrop')) {
|
||||
|
||||
$importing = ((array_key_exists('importfile',\App::$data)) ? true : false);
|
||||
|
||||
if(! x(\App::$data,'imagecrop')) {
|
||||
|
||||
$tpl = get_markup_template('profile_photo.tpl');
|
||||
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$user' => \App::$channel['channel_address'],
|
||||
'$info' => ((count($profiles) > 1) ? t('Your default profile photo is visible to anybody on the internet. Profile photos for alternate profiles will inherit the permissions of the profile') : t('Your profile photo is visible to anybody on the internet and may be distributed to other websites.')),
|
||||
'$importfile' => (($importing) ? \App::$data['importfile'] : ''),
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
|
||||
'$submit' => (($importing) ? t('Use') : t('Upload')),
|
||||
'$remove' => t('Remove'),
|
||||
'$profiles' => $profiles,
|
||||
'$single' => ((count($profiles) == 1) ? true : false),
|
||||
'$profile0' => $profiles[0],
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
|
||||
$o = replace_macros($tpl, [
|
||||
'$user' => App::$channel['channel_address'],
|
||||
'$info' => (($is_default_profile) ? t('This profile photo will be visible to anybody on the internet and may be distributed to other websites.') : t('This profile photo will be visible only to channels with permission to view this profile.')),
|
||||
'$importfile' => (($importing) ? App::$data['importfile'] : ''),
|
||||
'$title' => (($importing) ? t('Use Photo for Profile') : t('Change Profile Photo')),
|
||||
'$submit' => t('Upload'),
|
||||
'$remove' => t('Reset to default'),
|
||||
'$profile_id' => $profile_id,
|
||||
'$profile' => $profile,
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalCancel' => t('Cancel'),
|
||||
'$embedPhotosModalOK' => t('OK'),
|
||||
'$modalchooseimages' => t('Choose images to embed'),
|
||||
'$modalchoosealbum' => t('Choose an album'),
|
||||
'$modaldiffalbum' => t('Choose a different album'),
|
||||
'$modalerrorlist' => t('Error getting album list'),
|
||||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$select' => t('Select existing photo'),
|
||||
));
|
||||
|
||||
'$embedPhotosModalOK' => t('OK'),
|
||||
'$modalchooseimages' => t('Choose images to embed'),
|
||||
'$modalchoosealbum' => t('Choose an album'),
|
||||
'$modaldiffalbum' => t('Choose a different album'),
|
||||
'$modalerrorlist' => t('Error getting album list'),
|
||||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$select' => t('Select existing'),
|
||||
]);
|
||||
|
||||
call_hooks('profile_photo_content_end', $o);
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
else {
|
||||
|
||||
// present a cropping form
|
||||
|
||||
$filename = \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'];
|
||||
$resolution = \App::$data['imagecrop_resolution'];
|
||||
$tpl = get_markup_template("cropbody.tpl");
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'],
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
$filename = App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'];
|
||||
$tpl = get_markup_template("cropbody.tpl");
|
||||
|
||||
$o = replace_macros($tpl, [
|
||||
'$filename' => $filename,
|
||||
'$profile' => $profile_id,
|
||||
'$resource' => App::$data['imagecrop'] . '-' . App::$data['imagecrop_resolution'],
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$form_security_token' => get_form_security_token("profile_photo"),
|
||||
'$done' => t('Done Editing')
|
||||
));
|
||||
'$done' => t('Done editing')
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
/* @brief Generate the UI for photo-cropping
|
||||
*
|
||||
* @param $a Current application
|
||||
* @param $ph Photo-Factory
|
||||
* @return void
|
||||
* @param $ph
|
||||
* @param $hash
|
||||
* @param $smallest
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
|
||||
|
||||
$max_length = get_config('system','max_image_length');
|
||||
if(! $max_length)
|
||||
|
||||
|
||||
function profile_photo_crop_ui_head($ph, $hash, $smallest) {
|
||||
|
||||
$max_length = get_config('system', 'max_image_length');
|
||||
|
||||
if (!$max_length) {
|
||||
$max_length = MAX_IMAGE_LENGTH;
|
||||
if($max_length > 0)
|
||||
$ph->scaleImage($max_length);
|
||||
|
||||
\App::$data['width'] = $ph->getWidth();
|
||||
\App::$data['height'] = $ph->getHeight();
|
||||
|
||||
if(\App::$data['width'] < 500 || \App::$data['height'] < 500) {
|
||||
$ph->scaleImageUp(400);
|
||||
\App::$data['width'] = $ph->getWidth();
|
||||
\App::$data['height'] = $ph->getHeight();
|
||||
}
|
||||
|
||||
|
||||
\App::$data['imagecrop'] = $hash;
|
||||
\App::$data['imagecrop_resolution'] = $smallest;
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array());
|
||||
if ($max_length > 0) {
|
||||
$ph->scaleImage($max_length);
|
||||
}
|
||||
|
||||
App::$data['width'] = $ph->getWidth();
|
||||
App::$data['height'] = $ph->getHeight();
|
||||
|
||||
if (App::$data['width'] < 500 || App::$data['height'] < 500) {
|
||||
$ph->scaleImageUp(400);
|
||||
App::$data['width'] = $ph->getWidth();
|
||||
App::$data['height'] = $ph->getHeight();
|
||||
}
|
||||
|
||||
App::$data['imagecrop'] = $hash;
|
||||
App::$data['imagecrop_resolution'] = $smallest;
|
||||
App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -163,35 +163,6 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
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')) {
|
||||
if(feature_enabled(local_channel(),'multi_profiles'))
|
||||
$id = \App::$argv[1];
|
||||
else {
|
||||
$x = q("select id from profile where uid = %d and is_default = 1",
|
||||
intval(local_channel())
|
||||
);
|
||||
if($x)
|
||||
$id = $x[0]['id'];
|
||||
}
|
||||
$r = q("SELECT * FROM profile WHERE id = %d AND uid = %d LIMIT 1",
|
||||
intval($id),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(! count($r)) {
|
||||
notice( t('Profile not found.') . EOL);
|
||||
\App::$error = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
$chan = \App::get_channel();
|
||||
|
||||
profile_load($chan['channel_address'],$r[0]['id']);
|
||||
}
|
||||
}
|
||||
|
||||
function post() {
|
||||
@@ -317,8 +288,6 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$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);
|
||||
|
||||
@@ -514,6 +483,16 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$value = $locality . $comma1 . $region . $comma2 . $country_name;
|
||||
}
|
||||
|
||||
$hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0);
|
||||
|
||||
$suggestme = ((x($_POST, 'suggestme')) ? intval($_POST['suggestme']) : 0);
|
||||
set_pconfig(local_channel(), 'system', 'suggestme', $suggestme);
|
||||
|
||||
$show_presence = (((x($_POST, 'show_presence')) && (intval($_POST['show_presence']) == 1)) ? 1 : 0);
|
||||
set_pconfig(local_channel(), 'system', 'show_online_status', $show_presence);
|
||||
|
||||
$publish = ((x($_POST, 'profile_in_directory') && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0);
|
||||
|
||||
profile_activity($changes,$value);
|
||||
|
||||
}
|
||||
@@ -552,7 +531,8 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
employment = '%s',
|
||||
education = '%s',
|
||||
hide_friends = %d,
|
||||
profile_vcard = '%s'
|
||||
profile_vcard = '%s',
|
||||
publish = %d
|
||||
WHERE id = %d AND uid = %d",
|
||||
dbesc($profile_name),
|
||||
dbesc($name),
|
||||
@@ -588,6 +568,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
dbesc($education),
|
||||
intval($hide_friends),
|
||||
dbesc($profile_vcard),
|
||||
intval($publish),
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
);
|
||||
@@ -598,10 +579,11 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if($namechanged && $is_default) {
|
||||
q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
|
||||
// change name on all associated xchans by matching the url
|
||||
q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
|
||||
dbesc($name),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($channel['xchan_hash'])
|
||||
dbesc(z_root() . '/channel/' . $channel['channel_address'])
|
||||
);
|
||||
q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
|
||||
dbesc($name),
|
||||
@@ -619,8 +601,6 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
if($is_default) {
|
||||
// reload the info for the sidebar widget
|
||||
profile_load($channel['channel_address']);
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
|
||||
}
|
||||
}
|
||||
@@ -631,13 +611,13 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o = '';
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
require_once('include/channel.php');
|
||||
|
||||
$profile_fields_basic = get_profile_fields_basic();
|
||||
@@ -653,15 +633,20 @@ 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())
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
notice( t('Profile not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure we got uptodate data
|
||||
profile_load($channel['channel_address'], $id);
|
||||
|
||||
$editselect = 'none';
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), array(
|
||||
@@ -675,13 +660,43 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
$fields = $profile_fields_basic;
|
||||
|
||||
$hide_friends = array(
|
||||
'hide_friends',
|
||||
t('Hide your connections list from viewers of this profile'),
|
||||
$r[0]['hide_friends'],
|
||||
'',
|
||||
array(t('No'),t('Yes'))
|
||||
);
|
||||
$show_presence = [];
|
||||
$profile_in_dir = '';
|
||||
$suggestme = '';
|
||||
$hide_friends = [];
|
||||
$is_default = (($r[0]['is_default']) ? 1 : 0);
|
||||
|
||||
if ($is_default) {
|
||||
|
||||
$hide_friends = array(
|
||||
'hide_friends',
|
||||
t('Hide my connections from viewers of this profile'),
|
||||
$r[0]['hide_friends'],
|
||||
'',
|
||||
[t('No'), t('Yes')]
|
||||
);
|
||||
|
||||
|
||||
$opt_tpl = get_markup_template("field_checkbox.tpl");
|
||||
if (get_config('system', 'publish_all')) {
|
||||
$profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
|
||||
}
|
||||
else {
|
||||
$profile_in_dir = replace_macros($opt_tpl, [
|
||||
'$field' => ['profile_in_directory', t('Publish my default profile in the network directory'), $r[0]['publish'], '', [t('No'), t('Yes')]],
|
||||
]);
|
||||
}
|
||||
|
||||
$suggestme = get_pconfig(local_channel(), 'system', 'suggestme');
|
||||
$suggestme = (($suggestme === false) ? '0' : $suggestme); // default if not set: 0
|
||||
|
||||
$suggestme = replace_macros($opt_tpl, [
|
||||
'$field' => ['suggestme', t('Suggest me as a potential contact to new members'), $suggestme, '', [t('No'), t('Yes')]],
|
||||
]);
|
||||
|
||||
$show_presence_val = intval(get_pconfig(local_channel(), 'system', 'show_online_status'));
|
||||
$show_presence = ['show_presence', t('Reveal my online status'), $show_presence_val, '', [t('No'), t('Yes')]];
|
||||
}
|
||||
|
||||
$q = q("select * from profdef where true");
|
||||
if($q) {
|
||||
@@ -702,15 +717,15 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
//logger('extra_fields: ' . print_r($extra_fields,true));
|
||||
|
||||
$vc = $r[0]['profile_vcard'];
|
||||
$vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null);
|
||||
$vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] );
|
||||
//$vc = $r[0]['profile_vcard'];
|
||||
//$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(
|
||||
@@ -719,12 +734,12 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$profile_clone_link' => 'profiles/clone/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_clone"),
|
||||
'$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . get_form_security_token("profile_drop"),
|
||||
'$fields' => $fields,
|
||||
'$vcard' => $vcard,
|
||||
//'$vcard' => $vcard,
|
||||
'$guid' => $r[0]['profile_guid'],
|
||||
'$banner' => t('Edit Profile Details'),
|
||||
'$submit' => t('Submit'),
|
||||
'$viewprof' => t('View this profile'),
|
||||
'$editvis' => t('Edit visibility'),
|
||||
'$editvis' => t('Edit visibility'),
|
||||
'$tools_label' => t('Profile Tools'),
|
||||
'$coverpic' => t('Change cover photo'),
|
||||
'$profpic' => t('Change profile photo'),
|
||||
@@ -732,7 +747,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$cl_prof' => t('Clone this profile'),
|
||||
'$del_prof' => t('Delete this profile'),
|
||||
'$addthing' => t('Add profile things'),
|
||||
'$personal' => t('Personal'),
|
||||
'$basic' => t('Basic'),
|
||||
'$location' => t('Location'),
|
||||
'$relation' => t('Relationship'),
|
||||
'$miscellaneous'=> t('Miscellaneous'),
|
||||
@@ -784,23 +799,28 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']),
|
||||
'$channels' => array('channels', t('My other channels'), $r[0]['channels']),
|
||||
'$extra_fields' => $extra_fields,
|
||||
'$comms' => t('Communications'),
|
||||
'$tel_label' => t('Phone'),
|
||||
'$email_label' => t('Email'),
|
||||
'$impp_label' => t('Instant messenger'),
|
||||
'$url_label' => t('Website'),
|
||||
'$adr_label' => t('Address'),
|
||||
'$note_label' => t('Note'),
|
||||
'$mobile' => t('Mobile'),
|
||||
'$home' => t('Home'),
|
||||
'$work' => t('Work'),
|
||||
'$other' => t('Other'),
|
||||
'$add_card' => t('Add Contact'),
|
||||
'$add_field' => t('Add Field'),
|
||||
'$create' => t('Create'),
|
||||
'$update' => t('Update'),
|
||||
'$delete' => t('Delete'),
|
||||
'$cancel' => t('Cancel'),
|
||||
//'$comms' => t('Communications'),
|
||||
//'$tel_label' => t('Phone'),
|
||||
//'$email_label' => t('Email'),
|
||||
//'$impp_label' => t('Instant messenger'),
|
||||
//'$url_label' => t('Website'),
|
||||
//'$adr_label' => t('Address'),
|
||||
//'$note_label' => t('Note'),
|
||||
//'$mobile' => t('Mobile'),
|
||||
//'$home' => t('Home'),
|
||||
//'$work' => t('Work'),
|
||||
//'$other' => t('Other'),
|
||||
//'$add_card' => t('Add Contact'),
|
||||
//'$add_field' => t('Add Field'),
|
||||
//'$create' => t('Create'),
|
||||
//'$update' => t('Update'),
|
||||
//'$delete' => t('Delete'),
|
||||
//'$cancel' => t('Cancel'),
|
||||
|
||||
'$show_presence' => $show_presence,
|
||||
'$suggestme' => $suggestme,
|
||||
'$profile_in_dir' => $profile_in_dir,
|
||||
|
||||
));
|
||||
|
||||
$arr = array('profile' => $r[0], 'entry' => $o);
|
||||
|
||||
@@ -196,7 +196,7 @@ class Regate extends \Zotlabs\Web\Controller {
|
||||
if ($invite_channel) {
|
||||
$f = Connect::connect($new_channel['channel'], $invite_channel['xchan_addr']);
|
||||
if ($f['success']) {
|
||||
$can_view_stream = their_perms_contains($channel_id, $f['abook']['abook_xchan'], 'view_stream');
|
||||
$can_view_stream = intval(get_abconfig($channel_id, $f['abook']['abook_xchan'], 'their_perms', 'view_stream'));
|
||||
// If we can view their stream, pull in some posts
|
||||
if ($can_view_stream) {
|
||||
Master::Summon(['Onepoll', $f['abook']['abook_id']]);
|
||||
|
||||
@@ -57,8 +57,8 @@ class Removeme extends \Zotlabs\Web\Controller {
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$basedir' => z_root(),
|
||||
'$hash' => $hash,
|
||||
'$title' => t('Remove This Channel'),
|
||||
'$desc' => [ t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!') ],
|
||||
'$title' => t('Remove Channel'),
|
||||
'$desc' => [ t('WARNING: '), t('This channel will be permanently removed. '), t('This action can not be undone!') ],
|
||||
'$passwd' => t('Please enter your password for verification:'),
|
||||
// '$global' => [ 'global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), [ t('No'),t('Yes') ] ],
|
||||
'$submit' => t('Remove Channel')
|
||||
|
||||
@@ -7,6 +7,7 @@ use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
|
||||
class Search extends Controller {
|
||||
|
||||
@@ -58,10 +59,26 @@ class Search extends Controller {
|
||||
$o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false));
|
||||
|
||||
if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) {
|
||||
if (strpos($search, 'b64.') !== false) {
|
||||
if (strpos($search, '?') !== false) {
|
||||
$search = strtok($search, '?');
|
||||
}
|
||||
|
||||
$search = unpack_link_id(basename($search));
|
||||
}
|
||||
|
||||
$f = Libzot::fetch_conversation(App::get_channel(), punify($search), true);
|
||||
|
||||
if ($f) {
|
||||
goaway(z_root() . '/hq/' . gen_link_id($f['message_id']));
|
||||
$mid = $f[0]['message_id'];
|
||||
foreach ($f as $m) {
|
||||
if (strpos($search, $m['message_id']) === 0) {
|
||||
$mid = $m['message_id'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/hq/' . gen_link_id($mid));
|
||||
}
|
||||
else {
|
||||
// try other fetch providers (e.g. diaspora, pubcrawl)
|
||||
|
||||
@@ -11,14 +11,14 @@ class Calendar {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -34,14 +34,14 @@ class Calendar {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Calendar Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace Zotlabs\Module\Settings;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\PermissionRoles;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
@@ -10,602 +14,278 @@ require_once('include/selectors.php');
|
||||
|
||||
class Channel {
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings', 'settings');
|
||||
|
||||
call_hooks('settings_post', $_POST);
|
||||
|
||||
$set_perms = '';
|
||||
$channel = App::get_channel();
|
||||
$role = ((x($_POST, 'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
|
||||
$timezone = ((x($_POST, 'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
|
||||
$defloc = ((x($_POST, 'defloc')) ? notags(trim($_POST['defloc'])) : '');
|
||||
$evdays = ((x($_POST, 'evdays')) ? intval($_POST['evdays']) : 3);
|
||||
$photo_path = ((x($_POST, 'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
|
||||
$attach_path = ((x($_POST, 'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
|
||||
$allow_location = (((x($_POST, 'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1 : 0);
|
||||
$post_newfriend = (($_POST['post_newfriend'] == 1) ? 1 : 0);
|
||||
$post_joingroup = (($_POST['post_joingroup'] == 1) ? 1 : 0);
|
||||
$post_profilechange = (($_POST['post_profilechange'] == 1) ? 1 : 0);
|
||||
$adult = (($_POST['adult'] == 1) ? 1 : 0);
|
||||
$mailhost = ((array_key_exists('mailhost', $_POST)) ? notags(trim($_POST['mailhost'])) : '');
|
||||
$pageflags = $channel['channel_pageflags'];
|
||||
$existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
|
||||
$expire = ((x($_POST, 'expire')) ? intval($_POST['expire']) : 0);
|
||||
$incl = ((x($_POST['message_filter_incl'])) ? htmlspecialchars_decode(trim($_POST['message_filter_incl']), ENT_QUOTES) : '');
|
||||
$excl = ((x($_POST['message_filter_excl'])) ? htmlspecialchars_decode(trim($_POST['message_filter_excl']), ENT_QUOTES) : '');
|
||||
|
||||
$role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : '');
|
||||
$oldrole = get_pconfig(local_channel(),'system','permissions_role');
|
||||
|
||||
// This mapping can be removed after 3.4 release
|
||||
if($oldrole === 'social_party') {
|
||||
$oldrole = 'social_federation';
|
||||
}
|
||||
|
||||
if(($role != $oldrole) || ($role === 'custom')) {
|
||||
|
||||
if($role === 'custom') {
|
||||
$hide_presence = (((x($_POST,'hide_presence')) && (intval($_POST['hide_presence']) == 1)) ? 1: 0);
|
||||
$publish = (((x($_POST,'profile_in_directory')) && (intval($_POST['profile_in_directory']) == 1)) ? 1: 0);
|
||||
$def_group = ((x($_POST,'group-selection')) ? notags(trim($_POST['group-selection'])) : '');
|
||||
$r = q("update channel set channel_default_group = '%s' where channel_id = %d",
|
||||
dbesc($def_group),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
|
||||
foreach($global_perms as $k => $v) {
|
||||
\Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,intval($_POST[$k]));
|
||||
}
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$acl->set_from_array($_POST);
|
||||
$x = $acl->get();
|
||||
|
||||
$r = q("update channel set channel_allow_cid = '%s', channel_allow_gid = '%s',
|
||||
channel_deny_cid = '%s', channel_deny_gid = '%s' where channel_id = %d",
|
||||
dbesc($x['allow_cid']),
|
||||
dbesc($x['allow_gid']),
|
||||
dbesc($x['deny_cid']),
|
||||
dbesc($x['deny_gid']),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
else {
|
||||
$role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($_POST['permissions_role']);
|
||||
if(! $role_permissions) {
|
||||
notice('Permissions category could not be found.');
|
||||
return;
|
||||
}
|
||||
$hide_presence = 1 - (intval($role_permissions['online']));
|
||||
if($role_permissions['default_collection']) {
|
||||
$r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc( t('Friends') )
|
||||
);
|
||||
if(! $r) {
|
||||
require_once('include/group.php');
|
||||
group_add(local_channel(), t('Friends'));
|
||||
group_add_member(local_channel(),t('Friends'),$channel['channel_hash']);
|
||||
$r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc( t('Friends') )
|
||||
);
|
||||
}
|
||||
if($r) {
|
||||
q("update channel set channel_default_group = '%s', channel_allow_gid = '%s', channel_allow_cid = '', channel_deny_gid = '', channel_deny_cid = '' where channel_id = %d",
|
||||
dbesc($r[0]['hash']),
|
||||
dbesc('<' . $r[0]['hash'] . '>'),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
else {
|
||||
notice( sprintf('Default privacy group \'%s\' not found. Please create and re-submit permission change.', t('Friends')) . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// no default collection
|
||||
else {
|
||||
q("update channel set channel_default_group = '', channel_allow_gid = '', channel_allow_cid = '', channel_deny_gid = '',
|
||||
channel_deny_cid = '' where channel_id = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
if($role_permissions['perms_connect']) {
|
||||
$x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
|
||||
foreach($x as $k => $v) {
|
||||
set_abconfig(local_channel(),$channel['channel_hash'],'my_perms',$k, $v);
|
||||
if($role_permissions['perms_auto']) {
|
||||
set_pconfig(local_channel(),'autoperms',$k,$v);
|
||||
}
|
||||
else {
|
||||
del_pconfig(local_channel(),'autoperms',$k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($role_permissions['limits']) {
|
||||
foreach($role_permissions['limits'] as $k => $v) {
|
||||
\Zotlabs\Access\PermissionLimits::Set(local_channel(),$k,$v);
|
||||
}
|
||||
}
|
||||
if(array_key_exists('directory_publish',$role_permissions)) {
|
||||
$publish = intval($role_permissions['directory_publish']);
|
||||
}
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(),'system','hide_online_status',$hide_presence);
|
||||
set_pconfig(local_channel(),'system','permissions_role',$role);
|
||||
}
|
||||
|
||||
$username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
|
||||
$timezone = ((x($_POST,'timezone_select')) ? notags(trim($_POST['timezone_select'])) : '');
|
||||
$defloc = ((x($_POST,'defloc')) ? notags(trim($_POST['defloc'])) : '');
|
||||
$openid = ((x($_POST,'openid_url')) ? notags(trim($_POST['openid_url'])) : '');
|
||||
$maxreq = ((x($_POST,'maxreq')) ? intval($_POST['maxreq']) : 0);
|
||||
$expire = ((x($_POST,'expire')) ? intval($_POST['expire']) : 0);
|
||||
$evdays = ((x($_POST,'evdays')) ? intval($_POST['evdays']) : 3);
|
||||
$photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : '');
|
||||
$attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : '');
|
||||
|
||||
$expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0);
|
||||
$expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0);
|
||||
$expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0);
|
||||
$expire_network_only = ((x($_POST,'expire_network_only'))? intval($_POST['expire_network_only']) : 0);
|
||||
|
||||
$allow_location = (((x($_POST,'allow_location')) && (intval($_POST['allow_location']) == 1)) ? 1: 0);
|
||||
|
||||
$blocktags = (((x($_POST,'blocktags')) && (intval($_POST['blocktags']) == 1)) ? 0: 1); // this setting is inverted!
|
||||
$unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0);
|
||||
$cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0);
|
||||
$suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0);
|
||||
$autoperms = ((x($_POST,'autoperms')) ? intval($_POST['autoperms']) : 0);
|
||||
|
||||
$post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0);
|
||||
$post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0);
|
||||
$post_profilechange = (($_POST['post_profilechange'] == 1) ? 1: 0);
|
||||
$adult = (($_POST['adult'] == 1) ? 1 : 0);
|
||||
$defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default');
|
||||
|
||||
$mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : '');
|
||||
|
||||
$pageflags = $channel['channel_pageflags'];
|
||||
$existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0);
|
||||
if($adult != $existing_adult)
|
||||
if ($adult != $existing_adult) {
|
||||
$pageflags = ($pageflags ^ PAGE_ADULT);
|
||||
|
||||
}
|
||||
|
||||
$notify = 0;
|
||||
|
||||
if(x($_POST,'notify1'))
|
||||
if (x($_POST, 'notify1'))
|
||||
$notify += intval($_POST['notify1']);
|
||||
if(x($_POST,'notify2'))
|
||||
if (x($_POST, 'notify2'))
|
||||
$notify += intval($_POST['notify2']);
|
||||
if(x($_POST,'notify3'))
|
||||
if (x($_POST, 'notify3'))
|
||||
$notify += intval($_POST['notify3']);
|
||||
if(x($_POST,'notify4'))
|
||||
if (x($_POST, 'notify4'))
|
||||
$notify += intval($_POST['notify4']);
|
||||
if(x($_POST,'notify5'))
|
||||
if (x($_POST, 'notify5'))
|
||||
$notify += intval($_POST['notify5']);
|
||||
if(x($_POST,'notify6'))
|
||||
if (x($_POST, 'notify6'))
|
||||
$notify += intval($_POST['notify6']);
|
||||
if(x($_POST,'notify7'))
|
||||
if (x($_POST, 'notify7'))
|
||||
$notify += intval($_POST['notify7']);
|
||||
if(x($_POST,'notify8'))
|
||||
if (x($_POST, 'notify8'))
|
||||
$notify += intval($_POST['notify8']);
|
||||
|
||||
|
||||
$vnotify = 0;
|
||||
|
||||
if(x($_POST,'vnotify1'))
|
||||
if (x($_POST, 'vnotify1'))
|
||||
$vnotify += intval($_POST['vnotify1']);
|
||||
if(x($_POST,'vnotify2'))
|
||||
if (x($_POST, 'vnotify2'))
|
||||
$vnotify += intval($_POST['vnotify2']);
|
||||
if(x($_POST,'vnotify3'))
|
||||
if (x($_POST, 'vnotify3'))
|
||||
$vnotify += intval($_POST['vnotify3']);
|
||||
if(x($_POST,'vnotify4'))
|
||||
if (x($_POST, 'vnotify4'))
|
||||
$vnotify += intval($_POST['vnotify4']);
|
||||
if(x($_POST,'vnotify5'))
|
||||
if (x($_POST, 'vnotify5'))
|
||||
$vnotify += intval($_POST['vnotify5']);
|
||||
if(x($_POST,'vnotify6'))
|
||||
if (x($_POST, 'vnotify6'))
|
||||
$vnotify += intval($_POST['vnotify6']);
|
||||
if(x($_POST,'vnotify7'))
|
||||
if (x($_POST, 'vnotify7'))
|
||||
$vnotify += intval($_POST['vnotify7']);
|
||||
if(x($_POST,'vnotify8'))
|
||||
if (x($_POST, 'vnotify8'))
|
||||
$vnotify += intval($_POST['vnotify8']);
|
||||
if(x($_POST,'vnotify9'))
|
||||
if (x($_POST, 'vnotify9'))
|
||||
$vnotify += intval($_POST['vnotify9']);
|
||||
if(x($_POST,'vnotify10'))
|
||||
if (x($_POST, 'vnotify10'))
|
||||
$vnotify += intval($_POST['vnotify10']);
|
||||
if(x($_POST,'vnotify11') && is_site_admin())
|
||||
if (x($_POST, 'vnotify11') && is_site_admin())
|
||||
$vnotify += intval($_POST['vnotify11']);
|
||||
if(x($_POST,'vnotify12'))
|
||||
if (x($_POST, 'vnotify12'))
|
||||
$vnotify += intval($_POST['vnotify12']);
|
||||
if(x($_POST,'vnotify13'))
|
||||
if (x($_POST, 'vnotify13'))
|
||||
$vnotify += intval($_POST['vnotify13']);
|
||||
if(x($_POST,'vnotify14'))
|
||||
if (x($_POST, 'vnotify14'))
|
||||
$vnotify += intval($_POST['vnotify14']);
|
||||
if(x($_POST,'vnotify15'))
|
||||
if (x($_POST, 'vnotify15'))
|
||||
$vnotify += intval($_POST['vnotify15']);
|
||||
|
||||
$always_show_in_notices = x($_POST, 'always_show_in_notices') ? 1 : 0;
|
||||
$update_notices_per_parent = x($_POST, 'update_notices_per_parent') ? 1 : 0;
|
||||
$always_show_in_notices = ((x($_POST, 'always_show_in_notices')) ? 1 : 0);
|
||||
$update_notices_per_parent = ((x($_POST, 'update_notices_per_parent')) ? 1 : 0);
|
||||
|
||||
$err = '';
|
||||
|
||||
$name_change = false;
|
||||
|
||||
if($username != $channel['channel_name']) {
|
||||
$name_change = true;
|
||||
require_once('include/channel.php');
|
||||
$err = validate_channelname($username);
|
||||
if($err) {
|
||||
notice($err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if($timezone != $channel['channel_timezone']) {
|
||||
if(strlen($timezone))
|
||||
if ($timezone !== $channel['channel_timezone']) {
|
||||
if (strlen($timezone))
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(),'system','use_browser_location',$allow_location);
|
||||
set_pconfig(local_channel(),'system','suggestme', $suggestme);
|
||||
set_pconfig(local_channel(),'system','post_newfriend', $post_newfriend);
|
||||
set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup);
|
||||
set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange);
|
||||
set_pconfig(local_channel(),'system','blocktags',$blocktags);
|
||||
set_pconfig(local_channel(),'system','vnotify',$vnotify);
|
||||
set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices);
|
||||
set_pconfig(local_channel(),'system','update_notices_per_parent',$update_notices_per_parent);
|
||||
set_pconfig(local_channel(),'system','evdays',$evdays);
|
||||
set_pconfig(local_channel(),'system','photo_path',$photo_path);
|
||||
set_pconfig(local_channel(),'system','attach_path',$attach_path);
|
||||
set_pconfig(local_channel(),'system','default_permcat',$defpermcat);
|
||||
set_pconfig(local_channel(),'system','email_notify_host',$mailhost);
|
||||
set_pconfig(local_channel(),'system','autoperms',$autoperms);
|
||||
if (!$role) {
|
||||
notice(t('Please select a channel role') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d",
|
||||
dbesc($username),
|
||||
if ($role !== get_pconfig(local_channel(), 'system', 'permissions_role')) {
|
||||
$role_permissions = PermissionRoles::role_perms($_POST['permissions_role']);
|
||||
|
||||
if (isset($role_permissions['limits'])) {
|
||||
foreach ($role_permissions['limits'] as $k => $v) {
|
||||
PermissionLimits::Set(local_channel(), $k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(), 'system', 'group_actor', 0);
|
||||
if (isset($role_permissions['channel_type']) && $role_permissions['channel_type'] === 'group') {
|
||||
set_pconfig(local_channel(), 'system', 'group_actor', 1);
|
||||
}
|
||||
}
|
||||
|
||||
set_pconfig(local_channel(), 'system', 'permissions_role', $role);
|
||||
set_pconfig(local_channel(), 'system', 'use_browser_location', $allow_location);
|
||||
set_pconfig(local_channel(), 'system', 'post_newfriend', $post_newfriend);
|
||||
set_pconfig(local_channel(), 'system', 'post_joingroup', $post_joingroup);
|
||||
set_pconfig(local_channel(), 'system', 'post_profilechange', $post_profilechange);
|
||||
set_pconfig(local_channel(), 'system', 'vnotify', $vnotify);
|
||||
set_pconfig(local_channel(), 'system', 'always_show_in_notices', $always_show_in_notices);
|
||||
set_pconfig(local_channel(), 'system', 'update_notices_per_parent', $update_notices_per_parent);
|
||||
set_pconfig(local_channel(), 'system', 'evdays', $evdays);
|
||||
set_pconfig(local_channel(), 'system', 'photo_path', $photo_path);
|
||||
set_pconfig(local_channel(), 'system', 'attach_path', $attach_path);
|
||||
set_pconfig(local_channel(), 'system', 'email_notify_host', $mailhost);
|
||||
set_pconfig(local_channel(), 'system', 'message_filter_incl', $incl);
|
||||
set_pconfig(local_channel(), 'system', 'message_filter_excl', $excl);
|
||||
|
||||
$r = q("update channel set channel_pageflags = %d, channel_timezone = '%s',
|
||||
channel_location = '%s', channel_notifyflags = %d, channel_expire_days = %d
|
||||
where channel_id = %d",
|
||||
intval($pageflags),
|
||||
dbesc($timezone),
|
||||
dbesc($defloc),
|
||||
intval($notify),
|
||||
intval($unkmail),
|
||||
intval($maxreq),
|
||||
intval($expire),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r)
|
||||
info( t('Settings updated.') . EOL);
|
||||
|
||||
if(! is_null($publish)) {
|
||||
$r = q("UPDATE profile SET publish = %d WHERE is_default = 1 AND uid = %d",
|
||||
intval($publish),
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
|
||||
if($name_change) {
|
||||
// change name on all associated xchans by matching the url
|
||||
$r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_url = '%s'",
|
||||
dbesc($username),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(z_root() . '/channel/' . $channel['channel_address'])
|
||||
);
|
||||
$r = q("update profile set fullname = '%s' where uid = %d and is_default = 1",
|
||||
dbesc($username),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
|
||||
if ($r)
|
||||
info(t('Settings updated.') . EOL);
|
||||
|
||||
Master::Summon(['Directory', local_channel()]);
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
|
||||
if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) {
|
||||
if ($email_changed && App::$config['system']['register_policy'] == REGISTER_VERIFY) {
|
||||
|
||||
// FIXME - set to un-verified, blocked and redirect to logout
|
||||
// Q: Why? Are we verifying people or email addresses?
|
||||
// A: the policy is to verify email addresses
|
||||
}
|
||||
|
||||
goaway(z_root() . '/settings' );
|
||||
goaway(z_root() . '/settings');
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/permissions.php');
|
||||
load_pconfig(local_channel());
|
||||
|
||||
$channel = App::get_channel();
|
||||
$nickname = $channel['channel_address'];
|
||||
$timezone = $channel['channel_timezone'];
|
||||
$notify = $channel['channel_notifyflags'];
|
||||
$defloc = $channel['channel_location'];
|
||||
$adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
|
||||
$post_newfriend = get_pconfig(local_channel(), 'system', 'post_newfriend');
|
||||
$post_newfriend = (($post_newfriend === false) ? '0' : $post_newfriend); // default if not set: 0
|
||||
$post_joingroup = get_pconfig(local_channel(), 'system', 'post_joingroup');
|
||||
$post_joingroup = (($post_joingroup === false) ? '0' : $post_joingroup); // default if not set: 0
|
||||
$post_profilechange = get_pconfig(local_channel(), 'system', 'post_profilechange');
|
||||
$post_profilechange = (($post_profilechange === false) ? '0' : $post_profilechange); // default if not set: 0
|
||||
$subdir = ((strlen(App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
|
||||
$webbie = $nickname . '@' . App::get_hostname();
|
||||
$intl_nickname = unpunify($nickname) . '@' . unpunify(App::get_hostname());
|
||||
$disable_discover_tab = intval(get_config('system', 'disable_discover_tab', 1)) == 1;
|
||||
$site_firehose = intval(get_config('system', 'site_firehose', 0)) == 1;
|
||||
|
||||
$yes_no = array(t('No'),t('Yes'));
|
||||
$expire = $channel['channel_expire_days'];
|
||||
$sys_expire = get_config('system', 'default_expire_days');
|
||||
|
||||
|
||||
$p = q("SELECT * FROM profile WHERE is_default = 1 AND uid = %d LIMIT 1",
|
||||
intval(local_channel())
|
||||
);
|
||||
if(count($p))
|
||||
$profile = $p[0];
|
||||
|
||||
load_pconfig(local_channel(),'expire');
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
|
||||
$permiss = array();
|
||||
|
||||
$perm_opts = array(
|
||||
array( t('Nobody except yourself'), 0),
|
||||
array( t('Only those you specifically allow'), PERMS_SPECIFIC),
|
||||
array( t('Approved connections'), PERMS_CONTACTS),
|
||||
array( t('Any connections'), PERMS_PENDING),
|
||||
array( t('Anybody on this website'), PERMS_SITE),
|
||||
array( t('Anybody in this network'), PERMS_NETWORK),
|
||||
array( t('Anybody authenticated'), PERMS_AUTHED),
|
||||
array( t('Anybody on the internet'), PERMS_PUBLIC)
|
||||
);
|
||||
|
||||
$limits = \Zotlabs\Access\PermissionLimits::Get(local_channel());
|
||||
$anon_comments = get_config('system','anonymous_comments',true);
|
||||
|
||||
foreach($global_perms as $k => $perm) {
|
||||
$options = array();
|
||||
$can_be_public = ((strstr($k,'view') || ($k === 'post_comments' && $anon_comments)) ? true : false);
|
||||
foreach($perm_opts as $opt) {
|
||||
if($opt[1] == PERMS_PUBLIC && (! $can_be_public))
|
||||
continue;
|
||||
$options[$opt[1]] = $opt[0];
|
||||
}
|
||||
$permiss[] = array($k,$perm,$limits[$k],'',$options);
|
||||
}
|
||||
|
||||
// logger('permiss: ' . print_r($permiss,true));
|
||||
|
||||
$username = $channel['channel_name'];
|
||||
$nickname = $channel['channel_address'];
|
||||
$timezone = $channel['channel_timezone'];
|
||||
$notify = $channel['channel_notifyflags'];
|
||||
$defloc = $channel['channel_location'];
|
||||
|
||||
$maxreq = $channel['channel_max_friend_req'];
|
||||
$expire = $channel['channel_expire_days'];
|
||||
$adult_flag = intval($channel['channel_pageflags'] & PAGE_ADULT);
|
||||
$sys_expire = get_config('system','default_expire_days');
|
||||
|
||||
// $unkmail = \App::$user['unkmail'];
|
||||
// $cntunkmail = \App::$user['cntunkmail'];
|
||||
|
||||
$hide_presence = intval(get_pconfig(local_channel(), 'system','hide_online_status'));
|
||||
|
||||
|
||||
$expire_items = get_pconfig(local_channel(), 'expire','items');
|
||||
$expire_items = (($expire_items===false)? '1' : $expire_items); // default if not set: 1
|
||||
|
||||
$expire_notes = get_pconfig(local_channel(), 'expire','notes');
|
||||
$expire_notes = (($expire_notes===false)? '1' : $expire_notes); // default if not set: 1
|
||||
|
||||
$expire_starred = get_pconfig(local_channel(), 'expire','starred');
|
||||
$expire_starred = (($expire_starred===false)? '1' : $expire_starred); // default if not set: 1
|
||||
|
||||
$expire_photos = get_pconfig(local_channel(), 'expire','photos');
|
||||
$expire_photos = (($expire_photos===false)? '0' : $expire_photos); // default if not set: 0
|
||||
|
||||
$expire_network_only = get_pconfig(local_channel(), 'expire','network_only');
|
||||
$expire_network_only = (($expire_network_only===false)? '0' : $expire_network_only); // default if not set: 0
|
||||
|
||||
|
||||
$suggestme = get_pconfig(local_channel(), 'system','suggestme');
|
||||
$suggestme = (($suggestme===false)? '0': $suggestme); // default if not set: 0
|
||||
|
||||
$post_newfriend = get_pconfig(local_channel(), 'system','post_newfriend');
|
||||
$post_newfriend = (($post_newfriend===false)? '0': $post_newfriend); // default if not set: 0
|
||||
|
||||
$post_joingroup = get_pconfig(local_channel(), 'system','post_joingroup');
|
||||
$post_joingroup = (($post_joingroup===false)? '0': $post_joingroup); // default if not set: 0
|
||||
|
||||
$post_profilechange = get_pconfig(local_channel(), 'system','post_profilechange');
|
||||
$post_profilechange = (($post_profilechange===false)? '0': $post_profilechange); // default if not set: 0
|
||||
|
||||
$blocktags = get_pconfig(local_channel(),'system','blocktags');
|
||||
$blocktags = (($blocktags===false) ? '0' : $blocktags);
|
||||
|
||||
$timezone = date_default_timezone_get();
|
||||
|
||||
$opt_tpl = get_markup_template("field_checkbox.tpl");
|
||||
if(get_config('system','publish_all')) {
|
||||
$profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
|
||||
}
|
||||
else {
|
||||
$profile_in_dir = replace_macros($opt_tpl,array(
|
||||
'$field' => array('profile_in_directory', t('Publish your default profile in the network directory'), $profile['publish'], '', $yes_no),
|
||||
));
|
||||
}
|
||||
|
||||
$suggestme = replace_macros($opt_tpl,array(
|
||||
'$field' => array('suggestme', t('Allow us to suggest you as a potential friend to new members?'), $suggestme, '', $yes_no),
|
||||
|
||||
));
|
||||
|
||||
$subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
|
||||
|
||||
$webbie = $nickname . '@' . \App::get_hostname();
|
||||
$intl_nickname = unpunify($nickname) . '@' . unpunify(\App::get_hostname());
|
||||
|
||||
|
||||
$tpl_addr = get_markup_template("settings_nick_set.tpl");
|
||||
|
||||
$prof_addr = replace_macros($tpl_addr,array(
|
||||
'$desc' => t('Your channel address is'),
|
||||
$tpl_addr = get_markup_template("settings_nick_set.tpl");
|
||||
$prof_addr = replace_macros($tpl_addr, [
|
||||
'$desc' => t('Your channel address is'),
|
||||
'$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . ' (' . $webbie . ')'),
|
||||
'$subdir' => $subdir,
|
||||
'$davdesc' => t('Your files/photos are accessible via WebDAV at'),
|
||||
'$davpath' => z_root() . '/dav/' . $nickname,
|
||||
'$basepath' => \App::get_hostname()
|
||||
));
|
||||
'$subdir' => $subdir,
|
||||
'$davdesc' => t('Your files/photos are accessible via WebDAV at'),
|
||||
'$davpath' => z_root() . '/dav/' . $nickname,
|
||||
'$basepath' => App::get_hostname()
|
||||
]);
|
||||
|
||||
|
||||
|
||||
$pcat = new \Zotlabs\Lib\Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$permcats = [];
|
||||
if($pcatlist) {
|
||||
foreach($pcatlist as $pc) {
|
||||
$permcats[$pc['name']] = $pc['localname'];
|
||||
}
|
||||
}
|
||||
|
||||
$default_permcat = get_pconfig(local_channel(),'system','default_permcat','default');
|
||||
|
||||
|
||||
$stpl = get_markup_template('settings.tpl');
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$perm_defaults = $acl->get();
|
||||
|
||||
require_once('include/group.php');
|
||||
$group_select = mini_group_select(local_channel(),$channel['channel_default_group']);
|
||||
|
||||
$evdays = get_pconfig(local_channel(),'system','evdays');
|
||||
if(! $evdays)
|
||||
$evdays = get_pconfig(local_channel(), 'system', 'evdays');
|
||||
if (!$evdays)
|
||||
$evdays = 3;
|
||||
|
||||
$permissions_role = get_pconfig(local_channel(),'system','permissions_role');
|
||||
if(! $permissions_role)
|
||||
$permissions_role = 'custom';
|
||||
// compatibility mapping - can be removed after 3.4 release
|
||||
if($permissions_role === 'social_party')
|
||||
$permissions_role = 'social_federation';
|
||||
|
||||
if(in_array($permissions_role,['forum','repository']))
|
||||
$autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [
|
||||
'$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]);
|
||||
else
|
||||
$autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />';
|
||||
|
||||
$permissions_set = (($permissions_role != 'custom') ? true : false);
|
||||
|
||||
$perm_roles = \Zotlabs\Access\PermissionRoles::roles();
|
||||
|
||||
$always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices');
|
||||
$always_show_in_notices = get_pconfig(local_channel(), 'system', 'always_show_in_notices');
|
||||
$update_notices_per_parent = get_pconfig(local_channel(), 'system', 'update_notices_per_parent', 1);
|
||||
$vnotify = get_pconfig(local_channel(),'system','vnotify');
|
||||
|
||||
if($vnotify === false)
|
||||
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
|
||||
if ($vnotify === false)
|
||||
$vnotify = (-1);
|
||||
|
||||
$plugin = [ 'basic' => '', 'security' => '', 'notify' => '' ];
|
||||
call_hooks('channel_settings',$plugin);
|
||||
$perm_roles = PermissionRoles::channel_roles();
|
||||
$permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role');
|
||||
|
||||
$disable_discover_tab = intval(get_config('system','disable_discover_tab',1)) == 1;
|
||||
$site_firehose = intval(get_config('system','site_firehose',0)) == 1;
|
||||
if (!in_array($permissions_role, ['public', 'personal', 'group', 'custom'])) {
|
||||
notice(t('Please select a channel role') . EOL);
|
||||
array_unshift($perm_roles , '');
|
||||
}
|
||||
|
||||
$plugin = ['basic' => '', 'notify' => ''];
|
||||
call_hooks('channel_settings', $plugin);
|
||||
|
||||
$o .= replace_macros($stpl,array(
|
||||
'$ptitle' => t('Channel Settings'),
|
||||
$yes_no = [t('No'), t('Yes')];
|
||||
|
||||
'$submit' => t('Submit'),
|
||||
'$baseurl' => z_root(),
|
||||
'$uid' => local_channel(),
|
||||
'$form_security_token' => get_form_security_token("settings"),
|
||||
'$nickname_block' => $prof_addr,
|
||||
'$h_basic' => t('Basic Settings'),
|
||||
'$username' => array('username', t('Full Name:'), $username,''),
|
||||
'$email' => array('email', t('Email Address:'), $email, ''),
|
||||
'$timezone' => array('timezone_select' , t('Your Timezone:'), $timezone, '', get_timezones()),
|
||||
'$defloc' => array('defloc', t('Default Post Location:'), $defloc, t('Geographical location to display on your posts')),
|
||||
'$allowloc' => array('allow_location', t('Use Browser Location:'), ((get_pconfig(local_channel(),'system','use_browser_location')) ? 1 : ''), '', $yes_no),
|
||||
|
||||
'$adult' => array('adult', t('Adult Content'), $adult_flag, t('This channel frequently or regularly publishes adult content. (Please tag any adult material and/or nudity with #NSFW)'), $yes_no),
|
||||
|
||||
'$h_prv' => t('Security and Privacy Settings'),
|
||||
'$permissions_set' => $permissions_set,
|
||||
'$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'),
|
||||
|
||||
'$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no),
|
||||
|
||||
'$lbl_pmacro' => t('Simple Privacy Settings:'),
|
||||
'$pmacro3' => t('Very Public - <em>extremely permissive (should be used with caution)</em>'),
|
||||
'$pmacro2' => t('Typical - <em>default public, privacy when desired (similar to social network permissions but with improved privacy)</em>'),
|
||||
'$pmacro1' => t('Private - <em>default private, never open or public</em>'),
|
||||
'$pmacro0' => t('Blocked - <em>default blocked to/from everybody</em>'),
|
||||
'$permiss_arr' => $permiss,
|
||||
'$blocktags' => array('blocktags',t('Allow others to tag your posts'), 1-$blocktags, t('Often used by the community to retro-actively flag inappropriate content'), $yes_no),
|
||||
|
||||
'$lbl_p2macro' => t('Channel Permission Limits'),
|
||||
|
||||
'$expire' => array('expire',t('Expire other channel content after this many days'),$expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf( t('This website expires after %d days.'),intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')),
|
||||
'$maxreq' => array('maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']) , t('May reduce spam activity')),
|
||||
'$permissions' => t('Default Privacy Group'),
|
||||
'$permdesc' => t("\x28click to open/close\x29"),
|
||||
'$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))),
|
||||
|
||||
'$allow_cid' => acl2json($perm_defaults['allow_cid']),
|
||||
'$allow_gid' => acl2json($perm_defaults['allow_gid']),
|
||||
'$deny_cid' => acl2json($perm_defaults['deny_cid']),
|
||||
'$deny_gid' => acl2json($perm_defaults['deny_gid']),
|
||||
'$suggestme' => $suggestme,
|
||||
'$group_select' => $group_select,
|
||||
'$role' => array('permissions_role' , t('Channel role and privacy'), $permissions_role, '', $perm_roles),
|
||||
'$defpermcat' => [ 'defpermcat', t('Default permissions category'), $default_permcat, '', $permcats ],
|
||||
'$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
|
||||
'$profile_in_dir' => $profile_in_dir,
|
||||
'$hide_friends' => $hide_friends,
|
||||
'$hide_wall' => $hide_wall,
|
||||
'$unkmail' => $unkmail,
|
||||
'$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")),
|
||||
|
||||
'$autoperms' => $autoperms,
|
||||
'$h_not' => t('Notification Settings'),
|
||||
'$activity_options' => t('By default post a status message when:'),
|
||||
'$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no),
|
||||
'$post_joingroup' => array('post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no),
|
||||
'$post_profilechange' => array('post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no),
|
||||
'$lbl_not' => t('Send a notification email when:'),
|
||||
'$notify1' => array('notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no),
|
||||
'$notify2' => array('notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no),
|
||||
'$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no),
|
||||
'$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no),
|
||||
'$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no),
|
||||
'$notify6' => array('notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no),
|
||||
'$notify7' => array('notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no),
|
||||
'$notify8' => array('notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no),
|
||||
|
||||
'$notify9' => array('notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no),
|
||||
|
||||
|
||||
'$lbl_vnot' => t('Show visual notifications including:'),
|
||||
|
||||
'$vnotify1' => array('vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no),
|
||||
'$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no),
|
||||
'$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no),
|
||||
'$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no),
|
||||
'$vnotify5' => array('vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no),
|
||||
'$vnotify6' => array('vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no),
|
||||
'$vnotify7' => array('vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no),
|
||||
'$vnotify8' => array('vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no),
|
||||
'$vnotify9' => array('vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no),
|
||||
'$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no),
|
||||
'$vnotify11' => ((is_site_admin()) ? array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no) : array()),
|
||||
'$vnotify12' => array('vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no),
|
||||
'$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? array() : array('vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)),
|
||||
'$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no),
|
||||
'$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no),
|
||||
'$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ],
|
||||
'$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no),
|
||||
'$update_notices_per_parent' => array('update_notices_per_parent', t('Mark all notices of the thread read if a notice is clicked'), $update_notices_per_parent, 1, t('If no, only the clicked notice will be marked read'), $yes_no),
|
||||
'$desktop_notifications_info' => t('Desktop notifications are unavailable because the required browser permission has not been granted'),
|
||||
$stpl = get_markup_template('settings.tpl');
|
||||
$o = replace_macros($stpl, [
|
||||
'$ptitle' => t('Channel Settings'),
|
||||
'$submit' => t('Submit'),
|
||||
'$baseurl' => z_root(),
|
||||
'$uid' => local_channel(),
|
||||
'$form_security_token' => get_form_security_token("settings"),
|
||||
'$role' => ['permissions_role', t('Channel role'), $permissions_role, '', $perm_roles],
|
||||
'$nickname_block' => $prof_addr,
|
||||
'$h_basic' => t('Basic Settings'),
|
||||
'$timezone' => ['timezone_select', t('Channel timezone:'), $timezone, '', get_timezones()],
|
||||
'$defloc' => ['defloc', t('Default post location:'), $defloc, t('Geographical location to display on your posts')],
|
||||
'$allowloc' => ['allow_location', t('Use browser location'), ((get_pconfig(local_channel(), 'system', 'use_browser_location')) ? 1 : ''), '', $yes_no],
|
||||
'$adult' => ['adult', t('Adult content'), $adult_flag, t('This channel frequently or regularly publishes adult content'), $yes_no],
|
||||
'$maxreq' => ['maxreq', t('Maximum Friend Requests/Day:'), intval($channel['channel_max_friend_req']), t('May reduce spam activity')],
|
||||
'$h_not' => t('Notification Settings'),
|
||||
'$activity_options' => t('By default post a status message when:'),
|
||||
'$post_newfriend' => ['post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no],
|
||||
'$post_joingroup' => ['post_joingroup', t('joining a forum/community'), $post_joingroup, '', $yes_no],
|
||||
'$post_profilechange' => ['post_profilechange', t('making an <em>interesting</em> profile change'), $post_profilechange, '', $yes_no],
|
||||
'$lbl_not' => t('Send a notification email when:'),
|
||||
'$notify1' => ['notify1', t('You receive a connection request'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, '', $yes_no],
|
||||
'$notify2' => ['notify2', t('Your connections are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, '', $yes_no],
|
||||
'$notify3' => ['notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, '', $yes_no],
|
||||
'$notify4' => ['notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, '', $yes_no],
|
||||
'$notify5' => ['notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, '', $yes_no],
|
||||
'$notify6' => ['notify6', t('You receive a friend suggestion'), ($notify & NOTIFY_SUGGEST), NOTIFY_SUGGEST, '', $yes_no],
|
||||
'$notify7' => ['notify7', t('You are tagged in a post'), ($notify & NOTIFY_TAGSELF), NOTIFY_TAGSELF, '', $yes_no],
|
||||
'$notify8' => ['notify8', t('You are poked/prodded/etc. in a post'), ($notify & NOTIFY_POKE), NOTIFY_POKE, '', $yes_no],
|
||||
'$notify9' => ['notify9', t('Someone likes your post/comment'), ($notify & NOTIFY_LIKE), NOTIFY_LIKE, '', $yes_no],
|
||||
'$lbl_vnot' => t('Show visual notifications including:'),
|
||||
'$vnotify1' => ['vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no],
|
||||
'$vnotify2' => ['vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no],
|
||||
'$vnotify3' => ['vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no],
|
||||
'$vnotify4' => ['vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no],
|
||||
'$vnotify5' => ['vnotify5', t('Events today'), ($vnotify & VNOTIFY_EVENTTODAY), VNOTIFY_EVENTTODAY, '', $yes_no],
|
||||
'$vnotify6' => ['vnotify6', t('Upcoming birthdays'), ($vnotify & VNOTIFY_BIRTHDAY), VNOTIFY_BIRTHDAY, t('Not available in all themes'), $yes_no],
|
||||
'$vnotify7' => ['vnotify7', t('System (personal) notifications'), ($vnotify & VNOTIFY_SYSTEM), VNOTIFY_SYSTEM, '', $yes_no],
|
||||
'$vnotify8' => ['vnotify8', t('System info messages'), ($vnotify & VNOTIFY_INFO), VNOTIFY_INFO, t('Recommended'), $yes_no],
|
||||
'$vnotify9' => ['vnotify9', t('System critical alerts'), ($vnotify & VNOTIFY_ALERT), VNOTIFY_ALERT, t('Recommended'), $yes_no],
|
||||
'$vnotify10' => ['vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no],
|
||||
'$vnotify11' => ((is_site_admin()) ? ['vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no] : []),
|
||||
'$vnotify12' => ['vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no],
|
||||
'$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? [] : ['vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no]),
|
||||
'$vnotify14' => ['vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no],
|
||||
'$vnotify15' => ['vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no],
|
||||
'$mailhost' => ['mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(), 'system', 'email_notify_host', App::get_hostname()), sprintf(t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'), App::get_hostname())],
|
||||
'$always_show_in_notices' => ['always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no],
|
||||
'$update_notices_per_parent' => ['update_notices_per_parent', t('Mark all notices of the thread read if a notice is clicked'), $update_notices_per_parent, 1, t('If no, only the clicked notice will be marked read'), $yes_no],
|
||||
'$desktop_notifications_info' => t('Desktop notifications are unavailable because the required browser permission has not been granted'),
|
||||
'$desktop_notifications_request' => t('Grant permission'),
|
||||
'$evdays' => array('evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')),
|
||||
'$basic_addon' => $plugin['basic'],
|
||||
'$sec_addon' => $plugin['security'],
|
||||
'$notify_addon' => $plugin['notify'],
|
||||
'$evdays' => ['evdays', t('Notify me of events this many days in advance'), $evdays, t('Must be greater than 0')],
|
||||
'$basic_addon' => $plugin['basic'],
|
||||
'$notify_addon' => $plugin['notify'],
|
||||
'$photo_path' => ['photo_path', t('Default photo upload folder'), get_pconfig(local_channel(), 'system', 'photo_path'), t('%Y - current year, %m - current month')],
|
||||
'$attach_path' => ['attach_path', t('Default file upload folder'), get_pconfig(local_channel(), 'system', 'attach_path'), t('%Y - current year, %m - current month')],
|
||||
'$removeme' => t('Remove Channel'),
|
||||
'$removechannel' => t('Remove this channel.'),
|
||||
'$expire' => ['expire', t('Expire other channel content after this many days'), $expire, t('0 or blank to use the website limit.') . ' ' . ((intval($sys_expire)) ? sprintf(t('This website expires after %d days.'), intval($sys_expire)) : t('This website does not expire imported content.')) . ' ' . t('The website limit takes precedence if lower than your limit.')],
|
||||
'$message_filter_excl' => ['message_filter_excl', t('Do not import posts with this text'), get_pconfig(local_channel(), 'system', 'message_filter_excl', ''), t('Words one per line or #tags, $categories, /patterns/, lang=xx, lang!=xx - leave blank to import all posts')],
|
||||
'$message_filter_incl' => ['message_filter_incl', t('Only import posts with this text'), get_pconfig(local_channel(), 'system', 'message_filter_incl', ''), t('Words one per line or #tags, $categories, /patterns/, lang=xx, lang!=xx - leave blank to import all posts')]
|
||||
]);
|
||||
|
||||
'$h_advn' => t('Advanced Account/Page Type Settings'),
|
||||
'$h_descadvn' => t('Change the behaviour of this account for special situations'),
|
||||
'$pagetype' => $pagetype,
|
||||
'$lbl_misc' => t('Miscellaneous Settings'),
|
||||
'$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')),
|
||||
'$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')),
|
||||
'$removeme' => t('Remove Channel'),
|
||||
'$removechannel' => t('Remove this channel.'),
|
||||
));
|
||||
|
||||
call_hooks('settings_form',$o);
|
||||
|
||||
//$o .= '</form>' . "\r\n";
|
||||
call_hooks('settings_form', $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class Channel_home {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
@@ -25,10 +25,10 @@ class Channel_home {
|
||||
|
||||
$channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : '');
|
||||
set_pconfig(local_channel(),'system','channel_menu',$channel_menu);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -82,7 +82,7 @@ class Channel_home {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Channel Home Settings'),
|
||||
@@ -90,7 +90,7 @@ class Channel_home {
|
||||
'$extra_settings_html' => $extra_settings_html,
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ class Connections {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -34,14 +34,14 @@ class Connections {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Connections Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ class Directory {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -34,14 +34,14 @@ class Directory {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Directory Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ class Editor {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -34,14 +34,14 @@ class Editor {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Editor Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ class Events {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -34,14 +34,14 @@ class Events {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Events Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ class Manage {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -35,14 +35,14 @@ class Manage {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Channel Manager Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ class Network {
|
||||
$network_divmore_height = 50;
|
||||
|
||||
set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -53,7 +53,7 @@ class Network {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Stream Settings'),
|
||||
@@ -61,7 +61,7 @@ class Network {
|
||||
'$extra_settings_html' => $extra_settings_html,
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,18 @@ use Zotlabs\Lib\Libsync;
|
||||
class Photos {
|
||||
|
||||
function post() {
|
||||
|
||||
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -34,14 +34,14 @@ class Photos {
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Photos Settings'),
|
||||
'$features' => process_module_features_get(local_channel(), $features),
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
127
Zotlabs/Module/Settings/Privacy.php
Normal file
127
Zotlabs/Module/Settings/Privacy.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module\Settings;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Group;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Privacy {
|
||||
|
||||
function post() {
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/privacy', 'settings');
|
||||
call_hooks('settings_post', $_POST);
|
||||
|
||||
$index_opt_out = (((x($_POST, 'index_opt_out')) && (intval($_POST['index_opt_out']) == 1)) ? 1 : 0);
|
||||
set_pconfig(local_channel(), 'system', 'index_opt_out', $index_opt_out);
|
||||
|
||||
$autoperms = (((x($_POST, 'autoperms')) && (intval($_POST['autoperms']) == 1)) ? 1 : 0);
|
||||
set_pconfig(local_channel(), 'system', 'autoperms', $autoperms);
|
||||
|
||||
$role = get_pconfig(local_channel(), 'system', 'permissions_role');
|
||||
if ($role === 'custom') {
|
||||
|
||||
$global_perms = Permissions::Perms();
|
||||
|
||||
foreach ($global_perms as $k => $v) {
|
||||
PermissionLimits::Set(local_channel(), $k, intval($_POST[$k]));
|
||||
}
|
||||
|
||||
$group_actor = (((x($_POST, 'group_actor')) && (intval($_POST['group_actor']) == 1)) ? 1 : 0);
|
||||
set_pconfig(local_channel(), 'system', 'group_actor', $group_actor);
|
||||
|
||||
}
|
||||
|
||||
info(t('Privacy settings updated.') . EOL);
|
||||
Master::Summon(['Directory', local_channel()]);
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
goaway(z_root() . '/settings/privacy');
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
load_pconfig(local_channel());
|
||||
|
||||
$channel = App::get_channel();
|
||||
$global_perms = Permissions::Perms();
|
||||
$permiss = [];
|
||||
|
||||
$perm_opts = [
|
||||
[t('Only me'), 0],
|
||||
[t('Only those you specifically allow'), PERMS_SPECIFIC],
|
||||
[t('Approved connections'), PERMS_CONTACTS],
|
||||
[t('Any connections'), PERMS_PENDING],
|
||||
[t('Anybody on this website'), PERMS_SITE],
|
||||
[t('Anybody in this network'), PERMS_NETWORK],
|
||||
[t('Anybody authenticated'), PERMS_AUTHED],
|
||||
[t('Anybody on the internet'), PERMS_PUBLIC]
|
||||
];
|
||||
|
||||
$help = [
|
||||
'view_stream',
|
||||
'view_wiki',
|
||||
'view_pages',
|
||||
'view_storage'
|
||||
];
|
||||
|
||||
$help_txt = t('Advise: set to "Anybody on the internet" and use privacy groups to restrict access');
|
||||
$limits = PermissionLimits::Get(local_channel());
|
||||
$anon_comments = get_config('system', 'anonymous_comments', true);
|
||||
|
||||
foreach ($global_perms as $k => $perm) {
|
||||
$options = [];
|
||||
$can_be_public = (strstr($k, 'view') || ($k === 'post_comments' && $anon_comments));
|
||||
|
||||
foreach ($perm_opts as $opt) {
|
||||
if ($opt[1] == PERMS_PUBLIC && (!$can_be_public))
|
||||
continue;
|
||||
|
||||
$options[$opt[1]] = $opt[0];
|
||||
}
|
||||
|
||||
$permiss[] = [
|
||||
$k,
|
||||
$perm,
|
||||
$limits[$k],
|
||||
((in_array($k, $help)) ? $help_txt : ''),
|
||||
$options
|
||||
];
|
||||
}
|
||||
|
||||
//logger('permiss: ' . print_r($permiss,true));
|
||||
|
||||
$autoperms = get_pconfig(local_channel(), 'system', 'autoperms');
|
||||
$index_opt_out = get_pconfig(local_channel(), 'system', 'index_opt_out');
|
||||
$group_actor = get_pconfig(local_channel(), 'system', 'group_actor');
|
||||
|
||||
$permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role', 'custom');
|
||||
$permission_limits = ($permissions_role === 'custom');
|
||||
|
||||
$stpl = get_markup_template('settings_privacy.tpl');
|
||||
|
||||
$o = replace_macros($stpl, [
|
||||
'$ptitle' => t('Privacy Settings'),
|
||||
'$submit' => t('Submit'),
|
||||
'$form_security_token' => get_form_security_token("settings"),
|
||||
'$permission_limits' => $permission_limits,
|
||||
'$permiss_arr' => $permiss,
|
||||
'$permission_limits_label' => t('Advanced configuration'),
|
||||
'$permission_limits_warning' => [
|
||||
t('Proceed with caution'),
|
||||
t('Changing advanced configuration settings can impact your, and your contacts channels functionality and security.'),
|
||||
t('Accept the risk and continue')
|
||||
],
|
||||
'$autoperms' => ['autoperms', t('Automatically approve new contacts'), $autoperms, '', [t('No'), t('Yes')]],
|
||||
'$index_opt_out' => ['index_opt_out', t('Opt-out of search engine indexing'), $index_opt_out, '', [t('No'), t('Yes')]],
|
||||
'$group_actor' => ['group_actor', t('Group actor'), $group_actor, t('Allow this channel to act as a forum'), [t('No'), t('Yes')]]
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,17 @@ class Profiles {
|
||||
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
|
||||
|
||||
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
|
||||
|
||||
|
||||
$features = get_module_features($module);
|
||||
|
||||
process_module_features_post(local_channel(), $features, $_POST);
|
||||
|
||||
$profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : '');
|
||||
set_pconfig(local_channel(),'system','profile_assign',$profile_assign);
|
||||
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
if($_POST['rpath'])
|
||||
if(isset($_POST['rpath']) && is_local_url($_POST['rpath']))
|
||||
goaway($_POST['rpath']);
|
||||
|
||||
return;
|
||||
@@ -38,12 +38,12 @@ class Profiles {
|
||||
|
||||
$extra_settings_html = '';
|
||||
if(feature_enabled(local_channel(),'multi_profiles'))
|
||||
$extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign',''));
|
||||
$extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign',''), t('Default profile for new contacts'));
|
||||
|
||||
$tpl = get_markup_template("settings_module.tpl");
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$rpath' => $rpath,
|
||||
'$rpath' => escape_url($rpath),
|
||||
'$action_url' => 'settings/' . $module,
|
||||
'$form_security_token' => get_form_security_token('settings_' . $module),
|
||||
'$title' => t('Profiles Settings'),
|
||||
@@ -51,7 +51,7 @@ class Profiles {
|
||||
'$extra_settings_html' => $extra_settings_html,
|
||||
'$submit' => t('Submit')
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,17 +69,22 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$dbpass = ((isset($_POST['dbpass'])) ? trim($_POST['dbpass']) : '');
|
||||
$dbdata = ((isset($_POST['dbdata'])) ? trim($_POST['dbdata']) : '');
|
||||
$dbtype = ((isset($_POST['dbtype'])) ? intval(trim($_POST['dbtype'])) : 0);
|
||||
|
||||
$phpath = ((isset($_POST['phpath'])) ? trim($_POST['phpath']) : '');
|
||||
$adminmail = ((isset($_POST['adminmail'])) ? trim($_POST['adminmail']) : '');
|
||||
$siteurl = ((isset($_POST['siteurl'])) ? trim($_POST['siteurl']) : '');
|
||||
|
||||
if (empty($db_charset)) {
|
||||
$db_charset = ((intval($dbtype) === 0) ? 'utf8mb4' : 'UTF8');
|
||||
}
|
||||
|
||||
// $siteurl should not have a trailing slash
|
||||
|
||||
$siteurl = rtrim($siteurl,'/');
|
||||
|
||||
require_once('include/dba/dba_driver.php');
|
||||
|
||||
$db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
|
||||
$db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, $db_charset, true);
|
||||
|
||||
if(! \DBA::$dba->connected) {
|
||||
echo 'Database Connect failed: ' . \DBA::$dba->error;
|
||||
@@ -94,11 +99,16 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$dbpass = ((isset($_POST['dbpass'])) ? trim($_POST['dbpass']) : '');
|
||||
$dbdata = ((isset($_POST['dbdata'])) ? trim($_POST['dbdata']) : '');
|
||||
$dbtype = ((isset($_POST['dbtype'])) ? intval(trim($_POST['dbtype'])) : 0);
|
||||
|
||||
$phpath = ((isset($_POST['phpath'])) ? trim($_POST['phpath']) : '');
|
||||
$timezone = ((isset($_POST['timezone'])) ? trim($_POST['timezone']) : '');
|
||||
$adminmail = ((isset($_POST['adminmail'])) ? trim($_POST['adminmail']) : '');
|
||||
$siteurl = ((isset($_POST['siteurl'])) ? trim($_POST['siteurl']) : '');
|
||||
|
||||
if (empty($db_charset)) {
|
||||
$db_charset = ((intval($dbtype) === 0) ? 'utf8mb4' : 'UTF8');
|
||||
}
|
||||
|
||||
if($siteurl != z_root()) {
|
||||
$test = z_fetch_url($siteurl."/setup/testrewrite");
|
||||
if((! $test['success']) || ($test['body'] != 'ok')) {
|
||||
@@ -112,7 +122,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
if(! isset(\DBA::$dba->connected)) {
|
||||
// connect to db
|
||||
$db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, true);
|
||||
$db = \DBA::dba_factory($dbhost, $dbport, $dbuser, $dbpass, $dbdata, $dbtype, $db_charset, true);
|
||||
}
|
||||
|
||||
if(! isset(\DBA::$dba->connected)) {
|
||||
|
||||
@@ -124,7 +124,7 @@ class Sse_bs extends Controller {
|
||||
$str = '';
|
||||
|
||||
foreach($arr as $a) {
|
||||
$mids[] = '\'' . dbesc(@base64url_decode(substr($a,4))) . '\'';
|
||||
$mids[] = '\'' . dbesc(unpack_link_id($a)) . '\'';
|
||||
}
|
||||
|
||||
$str = implode(',', $mids);
|
||||
|
||||
@@ -5,6 +5,11 @@ namespace Zotlabs\Module;
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\AccessList;
|
||||
use Zotlabs\Lib\Permcat;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/security.php');
|
||||
|
||||
class Tokens extends Controller {
|
||||
|
||||
@@ -13,15 +18,65 @@ class Tokens extends Controller {
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Guest Access'))
|
||||
return;
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if(! Apps::system_app_installed($channel['channel_id'], 'Guest Access'))
|
||||
return;
|
||||
|
||||
check_form_security_token_redirectOnErr('tokens', 'tokens');
|
||||
|
||||
if(isset($_POST['delete'])) {
|
||||
$r = q("select * from atoken where atoken_id = %d and atoken_uid = %d",
|
||||
intval($_POST['atoken_id']),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$atoken = $r[0];
|
||||
$atoken_xchan = substr($channel['channel_hash'], 0, 16) . '.' . $atoken['atoken_guid'];
|
||||
|
||||
$atoken['deleted'] = true;
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($atoken_xchan)
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$clone = $r[0];
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
$clone['deleted'] = true;
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if ($abconfig) {
|
||||
$clone['abconfig'] = $abconfig;
|
||||
}
|
||||
|
||||
atoken_delete($atoken['atoken_id']);
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ], 'atoken' => [ $atoken ] ], true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$token_errs = 0;
|
||||
if(array_key_exists('token',$_POST)) {
|
||||
$atoken_id = (($_POST['atoken_id']) ? intval($_POST['atoken_id']) : 0);
|
||||
|
||||
if (! $atoken_id) {
|
||||
$atoken_guid = new_uuid();
|
||||
}
|
||||
|
||||
$name = trim(escape_tags($_POST['name']));
|
||||
$token = trim($_POST['token']);
|
||||
if((! $name) || (! $token))
|
||||
@@ -30,10 +85,10 @@ class Tokens extends Controller {
|
||||
$expires = datetime_convert(date_default_timezone_get(),'UTC',$_POST['expires']);
|
||||
else
|
||||
$expires = NULL_DATE;
|
||||
$max_atokens = service_class_fetch(local_channel(),'access_tokens');
|
||||
$max_atokens = service_class_fetch($channel['channel_id'],'access_tokens');
|
||||
if($max_atokens) {
|
||||
$r = q("select count(atoken_id) as total where atoken_uid = %d",
|
||||
intval(local_channel())
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r && intval($r[0]['total']) >= $max_tokens) {
|
||||
notice( sprintf( t('This channel is limited to %d tokens'), $max_tokens) . EOL);
|
||||
@@ -45,6 +100,17 @@ class Tokens extends Controller {
|
||||
notice( t('Name and Password are required.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$old_atok = q("select * from atoken where atoken_uid = %d and atoken_name = '%s'",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
if ($old_atok) {
|
||||
$old_atok = $old_atok[0];
|
||||
$old_xchan = atoken_xchan($old_atok);
|
||||
}
|
||||
|
||||
if($atoken_id) {
|
||||
$r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s'
|
||||
where atoken_id = %d and atoken_uid = %d",
|
||||
@@ -56,8 +122,9 @@ class Tokens extends Controller {
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )
|
||||
values ( %d, %d, '%s', '%s', '%s' ) ",
|
||||
$r = q("insert into atoken (atoken_guid, atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires )
|
||||
values ('%s', %d, %d, '%s', '%s', '%s' ) ",
|
||||
dbesc($atoken_guid),
|
||||
intval($channel['channel_account_id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name),
|
||||
@@ -66,21 +133,84 @@ class Tokens extends Controller {
|
||||
);
|
||||
}
|
||||
|
||||
$atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $name;
|
||||
$atok = q("select * from atoken where atoken_uid = %d and atoken_name = '%s'",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
$all_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
if ($atok) {
|
||||
$xchan = atoken_xchan($atok[0]);
|
||||
atoken_create_xchan($xchan);
|
||||
$atoken_xchan = $xchan['xchan_hash'];
|
||||
if ($old_atok && $old_xchan) {
|
||||
$r = q("update xchan set xchan_name = '%s' where xchan_hash = '%s'",
|
||||
dbesc($xchan['xchan_name']),
|
||||
dbesc($old_xchan['xchan_hash'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if($all_perms) {
|
||||
foreach($all_perms as $perm => $desc) {
|
||||
if(array_key_exists('perms_' . $perm, $_POST)) {
|
||||
set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,intval($_POST['perms_' . $perm]));
|
||||
}
|
||||
else {
|
||||
set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,0);
|
||||
|
||||
if (! $atoken_id) {
|
||||
|
||||
// If this is a new token, create a new abook record
|
||||
|
||||
$closeness = get_pconfig($channel['channel_id'], 'system', 'new_abook_closeness',80);
|
||||
$profile_assign = get_pconfig($channel['channel_id'], 'system', 'profile_assign', '');
|
||||
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
'abook_account' => $channel['channel_account_id'],
|
||||
'abook_channel' => $channel['channel_id'],
|
||||
'abook_closeness' => intval($closeness),
|
||||
'abook_xchan' => $atoken_xchan,
|
||||
'abook_profile' => $profile_assign,
|
||||
'abook_feed' => 0,
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_instance' => z_root(),
|
||||
]
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
logger('abook creation failed');
|
||||
}
|
||||
|
||||
/** If there is a default group for this channel, add this connection to it */
|
||||
if ($channel['channel_default_group']) {
|
||||
$g = AccessList::by_hash($channel['channel_id'], $channel['channel_default_group']);
|
||||
if ($g) {
|
||||
AccessList::member_add($channel['channel_id'], '', $atoken_xchan,$g['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$role = ((array_key_exists('permcat', $_POST)) ? escape_tags($_POST['permcat']) : '');
|
||||
\Zotlabs\Lib\Permcat::assign($channel, $role, [$atoken_xchan]);
|
||||
|
||||
$r = q("SELECT abook.*, xchan.*
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
|
||||
intval($channel['chnnel_id']),
|
||||
dbesc($atoken_xchan)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$clone = $r[0];
|
||||
|
||||
unset($clone['abook_id']);
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if ($abconfig) {
|
||||
$clone['abconfig'] = $abconfig;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => [ $clone ], 'atoken' => $atok ], true);
|
||||
|
||||
info( t('Token saved.') . EOL);
|
||||
return;
|
||||
@@ -99,10 +229,13 @@ class Tokens extends Controller {
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
|
||||
nav_set_selected('Guest Access');
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$atoken = null;
|
||||
$atoken_xchan = '';
|
||||
$atoken_abook = [];
|
||||
|
||||
if(argc() > 1) {
|
||||
$id = argv(1);
|
||||
@@ -114,76 +247,52 @@ class Tokens extends Controller {
|
||||
|
||||
if($atoken) {
|
||||
$atoken = $atoken[0];
|
||||
$atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name'];
|
||||
}
|
||||
$atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_guid'];
|
||||
|
||||
if($atoken && argc() > 2 && argv(2) === 'drop') {
|
||||
atoken_delete($id);
|
||||
$atoken = null;
|
||||
$atoken_xchan = '';
|
||||
$atoken_abook = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
intval(local_channel()),
|
||||
dbesc($atoken_xchan)
|
||||
);
|
||||
|
||||
$atoken_abook = $atoken_abook[0];
|
||||
}
|
||||
}
|
||||
|
||||
$t = q("select * from atoken where atoken_uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
$desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in privacy groups and visitors may login using these credentials to access private content.');
|
||||
|
||||
$desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.');
|
||||
$pcat = new Permcat(local_channel());
|
||||
$pcatlist = $pcat->listing();
|
||||
$default_role = get_pconfig(local_channel(), 'system', 'default_permcat');
|
||||
$current_permcat = (($atoken_abook) ? $atoken_abook['abook_role'] : $default_role);
|
||||
|
||||
$desc2 = t('You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:');
|
||||
$roles_dict = [];
|
||||
foreach ($pcatlist as $role) {
|
||||
$roles_dict[$role['name']] = $role['localname'];
|
||||
}
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
$their_perms = [];
|
||||
if (!$current_permcat) {
|
||||
notice(t('Please select a role for this guest!') . EOL);
|
||||
$permcats[] = '';
|
||||
}
|
||||
|
||||
$existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : ''),false);
|
||||
|
||||
if($atoken_xchan) {
|
||||
$theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'",
|
||||
intval(local_channel()),
|
||||
dbesc($atoken_xchan)
|
||||
);
|
||||
if($theirs) {
|
||||
foreach($theirs as $t) {
|
||||
$their_perms[$t['k']] = $t['v'];
|
||||
}
|
||||
if ($pcatlist) {
|
||||
foreach ($pcatlist as $pc) {
|
||||
$permcats[$pc['name']] = $pc['localname'];
|
||||
}
|
||||
}
|
||||
foreach($global_perms as $k => $v) {
|
||||
$thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k);
|
||||
//fixme
|
||||
|
||||
$checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k);
|
||||
|
||||
if($existing[$k])
|
||||
$thisperm = "1";
|
||||
|
||||
$perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$tpl = get_markup_template("tokens.tpl");
|
||||
$o .= replace_macros($tpl, array(
|
||||
'$form_security_token' => get_form_security_token("tokens"),
|
||||
'$title' => t('Guest Access Tokens'),
|
||||
'$desc' => $desc,
|
||||
'$desc2' => $desc2,
|
||||
'$tokens' => $t,
|
||||
'$form_security_token' => get_form_security_token('tokens'),
|
||||
'$permcat' => ['permcat', t('Select a role for this guest'), $current_permcat, '', $permcats],
|
||||
'$title' => t('Guest Access'),
|
||||
'$desc' => $desc,
|
||||
'$atoken' => $atoken,
|
||||
'$url1' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'$url2' => z_root() . '/photos/' . $channel['channel_address'],
|
||||
'$name' => array('name', t('Login Name') . ' <span class="required">*</span>', (($atoken) ? $atoken['atoken_name'] : ''),''),
|
||||
'$token'=> array('token', t('Login Password') . ' <span class="required">*</span>',(($atoken) ? $atoken['atoken_token'] : autoname(8)), ''),
|
||||
'$token'=> array('token', t('Login Password') . ' <span class="required">*</span>',(($atoken) ? $atoken['atoken_token'] : new_token()), ''),
|
||||
'$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), (($atoken['atoken_expires'] && $atoken['atoken_expires'] > NULL_DATE) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''),
|
||||
'$them' => t('Their Settings'),
|
||||
'$me' => t('My Settings'),
|
||||
'$perms' => $perms,
|
||||
'$inherited' => t('inherited'),
|
||||
'$notself' => 1,
|
||||
'$self' => 0,
|
||||
'$permlbl' => t('Individual Permissions'),
|
||||
'$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'),
|
||||
'$submit' => t('Submit')
|
||||
'$submit' => t('Submit'),
|
||||
'$delete' => t('Delete')
|
||||
));
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -143,6 +143,10 @@ class Uexport extends Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Channel Export')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
|
||||
@@ -6,7 +6,7 @@ require_once('include/selectors.php');
|
||||
class Viewconnections extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
if(observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
@@ -16,58 +16,58 @@ class Viewconnections extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
|
||||
if(observer_prohibited()) {
|
||||
notice( t('Public access denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(((! count(\App::$profile)) || (\App::$profile['hide_friends']))) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(! perm_is_allowed(\App::$profile['uid'], get_observer_hash(),'view_contacts')) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(! $_REQUEST['aj'])
|
||||
$_SESSION['return_url'] = \App::$query_string;
|
||||
|
||||
|
||||
|
||||
|
||||
$is_owner = ((local_channel() && local_channel() == \App::$profile['uid']) ? true : false);
|
||||
|
||||
$abook_flags = " and abook_pending = 0 and abook_self = 0 ";
|
||||
|
||||
$abook_flags = " and abook_pending = 0 and abook_self = 0 and abook_blocked = 0 and abook_ignored = 0 ";
|
||||
$sql_extra = '';
|
||||
|
||||
|
||||
if(! $is_owner) {
|
||||
$abook_flags .= " and abook_hidden = 0 ";
|
||||
$sql_extra = " and xchan_hidden = 0 ";
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT count(*) as total FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra ",
|
||||
intval(\App::$profile['uid'])
|
||||
);
|
||||
if($r) {
|
||||
\App::set_pager_total($r[0]['total']);
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d $abook_flags and xchan_orphan = 0 and xchan_deleted = 0 $sql_extra order by xchan_name LIMIT %d OFFSET %d ",
|
||||
intval(\App::$profile['uid']),
|
||||
intval(\App::$pager['itemspage']),
|
||||
intval(\App::$pager['start'])
|
||||
);
|
||||
|
||||
|
||||
if((! $r) && (! $_REQUEST['aj'])) {
|
||||
info( t('No connections.') . EOL );
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
$contacts = array();
|
||||
|
||||
|
||||
foreach($r as $rr) {
|
||||
|
||||
$oneway = false;
|
||||
@@ -103,7 +103,7 @@ class Viewconnections extends \Zotlabs\Web\Controller {
|
||||
'id' => $rr['abook_id'],
|
||||
'archived' => (intval($rr['abook_archived']) ? true : false),
|
||||
'img_hover' => sprintf( t('Visit %s\'s profile [%s]'), $rr['xchan_name'], $rr['xchan_url']),
|
||||
'thumb' => $rr['xchan_photo_m'],
|
||||
'thumb' => $rr['xchan_photo_m'],
|
||||
'name' => substr($rr['xchan_name'],0,20),
|
||||
'username' => $rr['xchan_addr'],
|
||||
'link' => $url,
|
||||
@@ -137,11 +137,11 @@ class Viewconnections extends \Zotlabs\Web\Controller {
|
||||
// '$paginate' => paginate($a),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
if(! $contacts)
|
||||
$o .= '<div id="content-complete"></div>';
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class Vote extends Controller {
|
||||
$fetch = null;
|
||||
$id = argv(1);
|
||||
$response = $_REQUEST['answer'];
|
||||
|
||||
|
||||
if ($id) {
|
||||
$fetch = q("select * from item where id = %d limit 1",
|
||||
intval($id)
|
||||
@@ -42,7 +42,7 @@ class Vote extends Controller {
|
||||
}
|
||||
|
||||
$valid = false;
|
||||
|
||||
|
||||
if ($obj['oneOf']) {
|
||||
foreach($obj['oneOf'] as $selection) {
|
||||
// logger('selection: ' . $selection);
|
||||
@@ -80,7 +80,6 @@ class Vote extends Controller {
|
||||
|
||||
$item = [];
|
||||
|
||||
|
||||
$item['aid'] = $channel['channel_account_id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
$item['item_origin'] = 1;
|
||||
@@ -95,11 +94,8 @@ class Vote extends Controller {
|
||||
$item['owner_xchan'] = $fetch[0]['author_xchan'];
|
||||
$item['allow_cid'] = '<' . $fetch[0]['author_xchan'] . '>';
|
||||
$item['item_private'] = 1;
|
||||
|
||||
|
||||
$item['obj_type'] = 'Note';
|
||||
$item['author'] = channelx_by_n($channel['channel_id']);
|
||||
|
||||
$item['obj'] = Activity::encode_item($item);
|
||||
|
||||
// now reset the placeholders
|
||||
@@ -108,17 +104,15 @@ class Vote extends Controller {
|
||||
$item['obj_type'] = 'Answer';
|
||||
unset($item['author']);
|
||||
|
||||
|
||||
$x = item_store($item);
|
||||
|
||||
|
||||
retain_item($fetch[0]['id']);
|
||||
|
||||
if($x['success']) {
|
||||
$itemid = $x['item_id'];
|
||||
Master::Summon( [ 'Notifier', 'like', $itemid ] );
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($itemid)
|
||||
);
|
||||
@@ -128,6 +122,7 @@ class Vote extends Controller {
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
|
||||
}
|
||||
}
|
||||
|
||||
$ret['success'] = true;
|
||||
$ret['message'] = t('Response submitted. Updates may not appear instantly.');
|
||||
json_return_and_die($ret);
|
||||
|
||||
@@ -126,7 +126,7 @@ class Wfinger extends \Zotlabs\Web\Controller {
|
||||
'http://webfinger.net/ns/name' => $r['channel_name'],
|
||||
'http://xmlns.com/foaf/0.1/name' => $r['channel_name'],
|
||||
'https://w3id.org/security/v1#publicKeyPem' => $r['xchan_pubkey'],
|
||||
'http://purl.org/zot/federation' => 'zot6,zot'
|
||||
'http://purl.org/zot/federation' => 'zot6'
|
||||
];
|
||||
|
||||
foreach($aliases as $alias)
|
||||
@@ -183,12 +183,6 @@ class Wfinger extends \Zotlabs\Web\Controller {
|
||||
'href' => z_root() . '/profile/' . $r['channel_address'],
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'http://schemas.google.com/g/2010#updates-from',
|
||||
'type' => 'application/atom+xml',
|
||||
'href' => z_root() . '/ofeed/' . $r['channel_address']
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'http://webfinger.net/rel/blog',
|
||||
'href' => z_root() . '/channel/' . $r['channel_address'],
|
||||
@@ -205,11 +199,6 @@ class Wfinger extends \Zotlabs\Web\Controller {
|
||||
'href' => channel_url($r)
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'http://purl.org/zot/protocol',
|
||||
'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r['xchan_addr'],
|
||||
],
|
||||
|
||||
[
|
||||
'rel' => 'http://purl.org/openwebauth/v1',
|
||||
'type' => 'application/x-zot+json',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Photo;
|
||||
|
||||
use Zotlabs\Lib\Hashpath;
|
||||
use Zotlabs\Lib\Hashpath;
|
||||
|
||||
/**
|
||||
* @brief Abstract photo driver class.
|
||||
@@ -494,11 +494,11 @@ abstract class PhotoDriver {
|
||||
( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires, profile )
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($p['profile']));
|
||||
}
|
||||
logger('Photo save imgscale ' . $p['imgscale'] . ' returned ' . intval($r));
|
||||
logger('Photo save imgscale ' . $p['imgscale'] . ' returned: ' . (($r) ? 1 : 0));
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stores thumbnail to database or filesystem.
|
||||
*
|
||||
@@ -530,13 +530,13 @@ abstract class PhotoDriver {
|
||||
}
|
||||
else
|
||||
$arr['os_storage'] = 0;
|
||||
|
||||
|
||||
if(! $this->save($arr)) {
|
||||
if(array_key_exists('os_syspath', $arr))
|
||||
@unlink($arr['os_syspath']);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ class Comanche {
|
||||
require_once('widget/' . trim($name) . '.php');
|
||||
elseif(file_exists('widget/' . trim($name) . '/' . trim($name) . '.php'))
|
||||
require_once('widget/' . trim($name) . '/' . trim($name) . '.php');
|
||||
|
||||
|
||||
if(! function_exists($func)) {
|
||||
$theme_widget = $func . '.php';
|
||||
if(theme_include($theme_widget)) {
|
||||
@@ -640,7 +640,8 @@ class Comanche {
|
||||
$cnt = preg_match_all("/\[widget=(.*?)\](.*?)\[\/widget\]/ism", $s, $matches, PREG_SET_ORDER);
|
||||
if($cnt) {
|
||||
foreach($matches as $mtch) {
|
||||
$s = str_replace($mtch[0],$this->widget(trim($mtch[1]),$mtch[2]),$s);
|
||||
|
||||
$s = str_replace((string)$mtch[0], (string)$this->widget(trim((string)$mtch[1]), (string)$mtch[2]), $s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,14 +60,16 @@ class Theme {
|
||||
|
||||
// Allow theme selection of the form 'theme_name:schema_name'
|
||||
$themepair = explode(':', $chosen_theme);
|
||||
|
||||
// Check if $chosen_theme is compatible with core. If not fall back to default
|
||||
$info = get_theme_info($themepair[0]);
|
||||
|
||||
$compatible = check_plugin_versions($info);
|
||||
if(!$compatible) {
|
||||
$chosen_theme = '';
|
||||
}
|
||||
|
||||
App::$theme_info = $info;
|
||||
|
||||
if($chosen_theme && (file_exists('view/theme/' . $themepair[0] . '/css/style.css') || file_exists('view/theme/' . $themepair[0] . '/php/style.php'))) {
|
||||
return($themepair);
|
||||
}
|
||||
|
||||
31
Zotlabs/Update/_1249.php
Normal file
31
Zotlabs/Update/_1249.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1249 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = dbq("ALTER TABLE abook ADD abook_role TEXT NOT NULL DEFAULT ''");
|
||||
$r2 = dbq("CREATE INDEX \"abook_role\" ON abook (\"abook_role\")");
|
||||
$r = ($r1 && $r2);
|
||||
}
|
||||
else {
|
||||
$r = dbq("ALTER TABLE `abook` ADD `abook_role` CHAR(191) NOT NULL DEFAULT '' ,
|
||||
ADD INDEX `abook_role` (`abook_role`)");
|
||||
}
|
||||
|
||||
if($r) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
31
Zotlabs/Update/_1250.php
Normal file
31
Zotlabs/Update/_1250.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1250 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = dbq("ALTER TABLE atoken ADD atoken_guid VARCHAR(255) NOT NULL DEFAULT ''");
|
||||
$r2 = dbq("CREATE INDEX \"atoken_guid\" ON atoken (\"atoken_guid\")");
|
||||
$r = ($r1 && $r2);
|
||||
}
|
||||
else {
|
||||
$r = dbq("ALTER TABLE `atoken` ADD `atoken_guid` CHAR(191) NOT NULL DEFAULT '' ,
|
||||
ADD INDEX `atoken_guid` (`atoken_guid`)");
|
||||
}
|
||||
|
||||
if($r) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
23
Zotlabs/Update/_1251.php
Normal file
23
Zotlabs/Update/_1251.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1251 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
$r = dbq("DELETE FROM app WHERE (app_name = 'Channel Home' OR app_name = 'Permission Categories') AND app_system = 1");
|
||||
|
||||
if($r) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
23
Zotlabs/Update/_1252.php
Normal file
23
Zotlabs/Update/_1252.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1252 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
$r = dbq("DELETE FROM app WHERE app_plugin = 'mail' AND app_system = 1");
|
||||
|
||||
if($r) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -127,6 +127,7 @@ class HTTPSig {
|
||||
if (array_key_exists($h, $headers)) {
|
||||
$signed_data .= $h . ': ' . $headers[$h] . "\n";
|
||||
}
|
||||
|
||||
if ($h === 'date') {
|
||||
$d = new DateTime($headers[$h]);
|
||||
$d->setTimeZone(new DateTimeZone('UTC'));
|
||||
@@ -142,20 +143,35 @@ class HTTPSig {
|
||||
$signed_data = rtrim($signed_data, "\n");
|
||||
|
||||
$algorithm = null;
|
||||
|
||||
if ($sig_block['algorithm'] === 'rsa-sha256') {
|
||||
$algorithm = 'sha256';
|
||||
}
|
||||
|
||||
if ($sig_block['algorithm'] === 'rsa-sha512') {
|
||||
$algorithm = 'sha512';
|
||||
}
|
||||
|
||||
if (!array_key_exists('keyId', $sig_block))
|
||||
if (!array_key_exists('keyId', $sig_block)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result['signer'] = $sig_block['keyId'];
|
||||
|
||||
$cached_key = self::get_key($key, $keytype, $result['signer']);
|
||||
|
||||
if ($sig_block['algorithm'] === 'hs2019') {
|
||||
if (isset($cached_key['algorithm'])) {
|
||||
if (strpos($cached_key['algorithm'], 'rsa-sha256') !== false) {
|
||||
$algorithm = 'sha256';
|
||||
}
|
||||
|
||||
if (strpos($cached_key['algorithm'], 'rsa-sha512') !== false) {
|
||||
$algorithm = 'sha512';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!($cached_key && $cached_key['public_key'])) {
|
||||
return $result;
|
||||
}
|
||||
@@ -243,7 +259,12 @@ class HTTPSig {
|
||||
}
|
||||
}
|
||||
|
||||
$key = self::get_activitystreams_key($id, $force);
|
||||
$delete = false;
|
||||
if ($keytype === 'delete') {
|
||||
$delete = true;
|
||||
}
|
||||
|
||||
$key = self::get_activitystreams_key($id, $force, $delete);
|
||||
|
||||
return $key;
|
||||
|
||||
@@ -274,7 +295,7 @@ class HTTPSig {
|
||||
* false if no pub key found, otherwise return an array with the pub key
|
||||
*/
|
||||
|
||||
static function get_activitystreams_key($id, $force = false) {
|
||||
static function get_activitystreams_key($id, $force = false, $delete = false) {
|
||||
|
||||
// Check the local cache first, but remove any fragments like #main-key since these won't be present in our cached data
|
||||
$url = ((strpos($id, '#')) ? substr($id, 0, strpos($id, '#')) : $id);
|
||||
@@ -290,18 +311,50 @@ class HTTPSig {
|
||||
$best = Libzot::zot_record_preferred($x);
|
||||
}
|
||||
if ($best && $best['xchan_pubkey']) {
|
||||
return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'hubloc' => $best];
|
||||
return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'algorithm' => get_xconfig($best['xchan_hash'], 'system', 'signing_algorithm'), 'hubloc' => $best];
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete) {
|
||||
// If we received a delete and we do not have the record cached,
|
||||
// we probably never saw this actor. Do not try to fetch it now.
|
||||
return false;
|
||||
}
|
||||
|
||||
// The record wasn't in cache. Fetch it now.
|
||||
$r = ActivityStreams::fetch($id);
|
||||
$signatureAlgorithm = EMPTY_STR;
|
||||
|
||||
if ($r) {
|
||||
if (array_key_exists('publicKey', $r) && array_key_exists('publicKeyPem', $r['publicKey']) && array_key_exists('id', $r['publicKey'])) {
|
||||
if ($r['publicKey']['id'] === $id || $r['id'] === $id) {
|
||||
$portable_id = ((array_key_exists('owner', $r['publicKey'])) ? $r['publicKey']['owner'] : EMPTY_STR);
|
||||
return ['public_key' => self::convertKey($r['publicKey']['publicKeyPem']), 'portable_id' => $portable_id, 'hubloc' => []];
|
||||
|
||||
// the w3c sec context has conflicting names and no defined values for this property except
|
||||
// "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
|
||||
|
||||
// Since the names conflict, it could mess up LD-signatures but we will accept both, and at this
|
||||
// time we will only look for the substrings 'rsa-sha256' and 'rsa-sha512' within those properties.
|
||||
// We will also accept a toplevel 'sigAlgorithm' regardless of namespace with the same constraints.
|
||||
// Default to rsa-sha256 if we can't figure out. If they're sending 'hs2019' we have to
|
||||
// look for something.
|
||||
|
||||
if (isset($r['publicKey']['signingAlgorithm'])) {
|
||||
$signatureAlgorithm = $r['publicKey']['signingAlgorithm'];
|
||||
set_xconfig($portable_id, 'system', 'signing_algorithm', $signatureAlgorithm);
|
||||
}
|
||||
|
||||
if (isset($r['publicKey']['signatureAlgorithm'])) {
|
||||
$signatureAlgorithm = $r['publicKey']['signatureAlgorithm'];
|
||||
set_xconfig($portable_id, 'system', 'signing_algorithm', $signatureAlgorithm);
|
||||
}
|
||||
|
||||
if (isset($r['sigAlgorithm'])) {
|
||||
$signatureAlgorithm = $r['sigAlgorithm'];
|
||||
set_xconfig($portable_id, 'system', 'signing_algorithm', $signatureAlgorithm);
|
||||
}
|
||||
|
||||
return ['public_key' => self::convertKey($r['publicKey']['publicKeyPem']), 'portable_id' => $portable_id, 'algorithm' => (($signatureAlgorithm) ? $signatureAlgorithm : 'rsa-sha256'), 'hubloc' => []];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -331,7 +384,7 @@ class HTTPSig {
|
||||
}
|
||||
|
||||
if ($best && $best['xchan_pubkey']) {
|
||||
return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'hubloc' => $best];
|
||||
return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'algorithm' => get_xconfig($best['xchan_hash'], 'system', 'signing_algorithm'), 'hubloc' => $best];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +430,7 @@ class HTTPSig {
|
||||
}
|
||||
|
||||
if ($best && $best['xchan_pubkey']) {
|
||||
return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'hubloc' => $best];
|
||||
return ['portable_id' => $best['xchan_hash'], 'public_key' => $best['xchan_pubkey'], 'algorithm' => get_xconfig($best['xchan_hash'], 'system', 'signing_algorithm'), 'hubloc' => $best];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,6 +502,9 @@ class HTTPSig {
|
||||
|
||||
$x = self::sign($head, $prvkey, $alg);
|
||||
|
||||
// TODO: should we default to hs2019?
|
||||
// $headerval = 'keyId="' . $keyid . '",algorithm="' . (($algorithm === 'rsa-sha256') ? 'hs2019' : $algorithm) . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
|
||||
|
||||
$headerval = 'keyId="' . $keyid . '",algorithm="' . $algorithm . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
|
||||
|
||||
if ($encryption) {
|
||||
@@ -516,11 +572,14 @@ class HTTPSig {
|
||||
|
||||
if ($head) {
|
||||
foreach ($head as $k => $v) {
|
||||
$headers .= strtolower($k) . ': ' . trim($v) . "\n";
|
||||
$k = strtolower($k);
|
||||
$v = (($v) ? trim($v) : '');
|
||||
|
||||
$headers .= $k . ': ' . $v . "\n";
|
||||
if ($fields)
|
||||
$fields .= ' ';
|
||||
|
||||
$fields .= strtolower($k);
|
||||
$fields .= $k;
|
||||
}
|
||||
// strip the trailing linefeed
|
||||
$headers = rtrim($headers, "\n");
|
||||
|
||||
@@ -6,71 +6,108 @@ namespace Zotlabs\Web;
|
||||
class HttpMeta {
|
||||
|
||||
private $vars = null;
|
||||
private $og = null;
|
||||
private $og = null;
|
||||
|
||||
function __construct() {
|
||||
|
||||
$this->vars = array();
|
||||
$this->og = array();
|
||||
$this->vars = [];
|
||||
$this->og = [];
|
||||
$this->ogproperties = [];
|
||||
|
||||
}
|
||||
|
||||
function set($property,$value) {
|
||||
if(strpos($property,'og:') === 0)
|
||||
$this->og[$property] = $value;
|
||||
else
|
||||
//Set Meta Value
|
||||
// Mode:
|
||||
// 0 = Default - set if no value currently exists
|
||||
// 1 = Overwrite - replace existing value(s)
|
||||
// 2 = Multi - append to the array of values
|
||||
function set($property,$value,$mode=0) {
|
||||
$ogallowsmulti = ['image','audio','video'];
|
||||
if (strpos($property,'og:') === 0) {
|
||||
$count = 0;
|
||||
foreach ($this->og as $ogk => $ogdata) {
|
||||
if (strpos($ogdata['property'],$property) === 0) {
|
||||
if ($mode == 1) {
|
||||
unset($this->og[$ogk]);
|
||||
unset($this->ogproperties[$property]);
|
||||
}
|
||||
elseif ($mode == 0) {
|
||||
return;
|
||||
}
|
||||
elseif ($value == $ogdata['value']) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($value !== null) {
|
||||
//mode = 1 with value === null will delete the property entirely.
|
||||
$components = explode(':',$property);
|
||||
$ogp=$components[1];
|
||||
|
||||
if (!$count || in_array($ogp,$ogallowsmulti)) {
|
||||
$this->og[]=['property'=>$property,'value'=>$value];
|
||||
$this->ogproperties[$property] = $property;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->vars[$property] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
function check_required() {
|
||||
if(
|
||||
($this->og)
|
||||
&& array_key_exists('og:title',$this->og)
|
||||
&& array_key_exists('og:type', $this->og)
|
||||
&& array_key_exists('og:image',$this->og)
|
||||
&& array_key_exists('og:url', $this->og)
|
||||
)
|
||||
if (
|
||||
in_array('og:title',$this->ogproperties)
|
||||
&& in_array('og:type', $this->ogproperties)
|
||||
&& (in_array('og:image',$this->ogproperties)
|
||||
|| in_array('og:image:url',$this->ogproperties))
|
||||
&& (array_key_exists('og:url', $this->ogproperties)
|
||||
|| array_key_exists('og:url:secure_url', $this->ogproperties))
|
||||
&& array_key_exists('og:description', $this->ogproperties)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_field($field) {
|
||||
if(strpos($field,'og:') === 0)
|
||||
$arr = $this->og;
|
||||
else
|
||||
if (strpos($field,'og:') === 0) {
|
||||
foreach ($this->og as $ogdata) {
|
||||
if (strpos($ogdata['property'],$field) === 0) {
|
||||
$arr[$field][] = $ogdata['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$arr = $this->vars;
|
||||
}
|
||||
|
||||
if($arr && array_key_exists($field,$arr) && $arr[$field])
|
||||
if (isset($arr) && is_array($arr) && array_key_exists($field,$arr) && $arr[$field]) {
|
||||
return $arr[$field];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
// use 'name' for most meta fields, and 'property' for opengraph properties
|
||||
$o = '';
|
||||
if($this->vars) {
|
||||
foreach($this->vars as $k => $v) {
|
||||
$o .= '<meta property="' . $k . '" content="' . urlencode($v) . '" />' . "\r\n" ;
|
||||
if ($this->vars) {
|
||||
foreach ($this->vars as $k => $v) {
|
||||
$o .= '<meta name="' . htmlspecialchars($k,ENT_COMPAT,'UTF-8',false) . '" content="' . htmlspecialchars($v,ENT_COMPAT,'UTF-8',false) . '" />' . "\r\n" ;
|
||||
}
|
||||
}
|
||||
if($this->check_required()) {
|
||||
$arrayproperties = [ 'og:image' ];
|
||||
foreach($this->og as $k => $v) {
|
||||
if (in_array($k,$arrayproperties)) {
|
||||
if (is_array($v)) {
|
||||
foreach ($v as $v2) {
|
||||
$o .= '<meta property="' . $k . '" content="' . $v2 . '" />' . "\r\n" ;
|
||||
}
|
||||
} else {
|
||||
$o .= '<meta property="' . $k . '" content="' . $v . '" />' . "\r\n" ;
|
||||
}
|
||||
} else {
|
||||
$o .= '<meta property="' . $k . '" content="' . $v . '" />' . "\r\n" ;
|
||||
}
|
||||
if ($this->check_required()) {
|
||||
foreach ($this->og as $ogdata) {
|
||||
$o .= '<meta property="' . htmlspecialchars($ogdata['property'],ENT_COMPAT,'UTF-8',false) . '" content="' . htmlspecialchars($ogdata['value'],ENT_COMPAT,'UTF-8',false) . '" />' . "\r\n" ;
|
||||
}
|
||||
}
|
||||
if($o)
|
||||
if ($o) {
|
||||
return "\r\n" . $o;
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class Session {
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
|
||||
$this->custom_handler = boolval(get_config('system', 'session_custom', false));
|
||||
|
||||
|
||||
/*
|
||||
* Set our session storage functions.
|
||||
*/
|
||||
@@ -67,23 +67,24 @@ class Session {
|
||||
}
|
||||
|
||||
|
||||
// Force cookies to be secure (https only) if this site is SSL enabled.
|
||||
// Force cookies to be secure (https only) if this site is SSL enabled.
|
||||
// Must be done before session_start().
|
||||
|
||||
|
||||
$arr = session_get_cookie_params();
|
||||
|
||||
|
||||
// Note when setting cookies: set the domain to false which creates a single domain
|
||||
// cookie. If you use a hostname it will create a .domain.com wildcard which will
|
||||
// have some nasty side effects if you have any other subdomains running hubzilla.
|
||||
// have some nasty side effects if you have any other subdomains running hubzilla.
|
||||
|
||||
session_set_cookie_params(
|
||||
((isset($arr['lifetime'])) ? $arr['lifetime'] : 0),
|
||||
((isset($arr['path'])) ? $arr['path'] : '/'),
|
||||
(($arr['domain']) ? $arr['domain'] : false),
|
||||
((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
|
||||
((isset($arr['httponly'])) ? $arr['httponly'] : true)
|
||||
);
|
||||
session_set_cookie_params([
|
||||
'lifetime' => ((isset($arr['lifetime'])) ? $arr['lifetime'] : 0),
|
||||
'path' => ((isset($arr['path'])) ? $arr['path'] : '/'),
|
||||
'domain' => (($arr['domain']) ? $arr['domain'] : false),
|
||||
'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
|
||||
'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
|
||||
'samesite' => 'None'
|
||||
]);
|
||||
|
||||
register_shutdown_function('session_write_close');
|
||||
|
||||
@@ -127,13 +128,36 @@ class Session {
|
||||
$this->handler->read(session_id());
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
logger('no session handler');
|
||||
|
||||
if (x($_COOKIE, 'jsdisabled')) {
|
||||
setcookie('jsdisabled', $_COOKIE['jsdisabled'], $newxtime, '/', false,((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),((isset($arr['httponly'])) ? $arr['httponly'] : true));
|
||||
setcookie(
|
||||
'jsdisabled',
|
||||
$_COOKIE['jsdisabled'],
|
||||
[
|
||||
'expires' => $newxtime,
|
||||
'path' => '/',
|
||||
'domain' => false,
|
||||
'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
|
||||
'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
|
||||
'samesite' => 'None'
|
||||
]
|
||||
);
|
||||
}
|
||||
setcookie(session_name(),session_id(),$newxtime, '/', false,((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),((isset($arr['httponly'])) ? $arr['httponly'] : true));
|
||||
|
||||
setcookie(
|
||||
session_name(),
|
||||
session_id(),
|
||||
[
|
||||
'expires' => $newxtime,
|
||||
'path' => '/',
|
||||
'domain' => false,
|
||||
'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
|
||||
'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
|
||||
'samesite' => 'None'
|
||||
]
|
||||
);
|
||||
|
||||
$arr = array('expire' => $xtime);
|
||||
call_hooks('new_cookie', $arr);
|
||||
@@ -148,8 +172,21 @@ class Session {
|
||||
|
||||
$xtime = (($_SESSION['remember_me']) ? (60 * 60 * 24 * 365) : 0 );
|
||||
|
||||
if($xtime)
|
||||
setcookie(session_name(),session_id(),(time() + $xtime), '/', false,((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),((isset($arr['httponly'])) ? $arr['httponly'] : true));
|
||||
if($xtime) {
|
||||
setcookie(
|
||||
session_name(),
|
||||
session_id(),
|
||||
[
|
||||
'expires' => time() + $xtime,
|
||||
'path' => '/',
|
||||
'domain' => false,
|
||||
'secure' => ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false),
|
||||
'httponly' => ((isset($arr['httponly'])) ? $arr['httponly'] : true),
|
||||
'samesite' => 'None'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$arr = array('expire' => $xtime);
|
||||
call_hooks('extend_cookie', $arr);
|
||||
|
||||
@@ -169,8 +206,8 @@ class Session {
|
||||
if($_SESSION['addr'] && $_SESSION['addr'] != $_SERVER['REMOTE_ADDR']) {
|
||||
logger('SECURITY: Session IP address changed: ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
$partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.'));
|
||||
$partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.'));
|
||||
$partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.'));
|
||||
$partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.'));
|
||||
|
||||
$paranoia = intval(get_pconfig($_SESSION['uid'], 'system', 'paranoia'));
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Zotlabs\Web;
|
||||
class SessionHandler implements \SessionHandlerInterface {
|
||||
|
||||
|
||||
function open ($s, $n) {
|
||||
function open ($s, $n) : bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class SessionHandler implements \SessionHandlerInterface {
|
||||
// some which call read explicitly and some that do not. So we call it explicitly
|
||||
// just after sid regeneration to force a record to exist.
|
||||
|
||||
function read ($id) {
|
||||
function read ($id) : string {
|
||||
|
||||
if($id) {
|
||||
$r = q("SELECT sess_data FROM session WHERE sid= '%s'", dbesc($id));
|
||||
@@ -36,7 +36,7 @@ class SessionHandler implements \SessionHandlerInterface {
|
||||
}
|
||||
|
||||
|
||||
function write ($id, $data) {
|
||||
function write ($id, $data) : bool {
|
||||
|
||||
// Pretend everything is hunky-dory, even though it isn't.
|
||||
// There probably isn't anything we can do about it in any event.
|
||||
@@ -49,9 +49,9 @@ class SessionHandler implements \SessionHandlerInterface {
|
||||
|
||||
// Unless we authenticate somehow, only keep a session for 5 minutes
|
||||
// The viewer can extend this by performing any web action using the
|
||||
// original cookie, but this allows us to cleanup the hundreds or
|
||||
// original cookie, but this allows us to cleanup the hundreds or
|
||||
// thousands of empty sessions left around from web crawlers which are
|
||||
// assigned cookies on each page that they never use.
|
||||
// assigned cookies on each page that they never use.
|
||||
|
||||
$expire = time() + 300;
|
||||
|
||||
@@ -74,19 +74,19 @@ class SessionHandler implements \SessionHandlerInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function close() {
|
||||
|
||||
function close() : bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function destroy ($id) {
|
||||
function destroy ($id) : bool {
|
||||
q("DELETE FROM session WHERE sid = '%s'", dbesc($id));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function gc($expire) {
|
||||
function gc($expire) : int {
|
||||
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@ class WebServer {
|
||||
|
||||
$Router->Dispatch();
|
||||
|
||||
$this->set_homebase();
|
||||
// TODO: this is not used for anything atm and messes up comanche templates by adding some javascript
|
||||
//$this->set_homebase();
|
||||
|
||||
// now that we've been through the module content, see if the page reported
|
||||
// a permission problem and if so, a 403 response would seem to be in order.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Activity
|
||||
* * Description: Shows the unseen activity count per contact
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
class Activity {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Activity filters
|
||||
* * Description: Filters for the network stream
|
||||
* * Requires: network
|
||||
*/
|
||||
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use App;
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
/**
|
||||
* * Name: Activity order
|
||||
* * Description: Order the network stream by posted date, last commented or by date unthreaded
|
||||
* * Requires: network
|
||||
*/
|
||||
|
||||
class Activity_order {
|
||||
|
||||
function widget($arr) {
|
||||
@@ -22,7 +28,7 @@ class Activity_order {
|
||||
switch($_GET['order']){
|
||||
case 'post':
|
||||
$postord_active = 'active';
|
||||
set_pconfig(local_channel(), 'mod_network', 'order', 1);
|
||||
set_pconfig(local_channel(), 'mod_network', 'order', 1);
|
||||
break;
|
||||
case 'comment':
|
||||
$commentord_active = 'active';
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Admin menu
|
||||
* * Requires: admin
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
class Admin {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Affinity Tool
|
||||
* * Description: Filter the network stream by affinity, requires the Affinity Tool App
|
||||
* * Requires: network
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use Zotlabs\Lib\Apps;
|
||||
@@ -13,7 +19,7 @@ class Affinity {
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(),'Affinity Tool'))
|
||||
return;
|
||||
|
||||
|
||||
$default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0);
|
||||
$default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99);
|
||||
|
||||
@@ -54,7 +60,7 @@ class Affinity {
|
||||
'$refresh' => t('Refresh'),
|
||||
'$labels' => $label_str,
|
||||
));
|
||||
|
||||
|
||||
$arr = array('html' => $x);
|
||||
call_hooks('main_slider',$arr);
|
||||
|
||||
@@ -63,4 +69,4 @@ class Affinity {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Album
|
||||
* * Description: Displays an album with a title which can be defined via the 'album' and 'title' variable
|
||||
* * Requires: channel, articles, cards, wiki
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
require_once('include/attach.php');
|
||||
@@ -99,7 +105,7 @@ class Album {
|
||||
'$upload_form' => $upload_form,
|
||||
'$usage' => $usage_message
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: App categories
|
||||
* * Description: Shows a menu with various app categories
|
||||
* * Requires: apps
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
class Appcategories {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: App cloud
|
||||
* * Description: Shows a cloud with various app categories
|
||||
* * Requires: apps
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
class Appcloud {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: App store menu
|
||||
* * Description: Shows a menu with links to installed and available apps
|
||||
* * Requires: apps
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Archive
|
||||
* * Description: A menu with links to content sorted by years and months
|
||||
* * Requires: channel, articles, cards
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Bookmarked chats
|
||||
* * Description: A menu with bookmarked chats
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
class Bookmarkedchats {
|
||||
|
||||
function widget($arr) {
|
||||
|
||||
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat'))
|
||||
return '';
|
||||
|
||||
$h = get_observer_hash();
|
||||
if(! $h)
|
||||
return;
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
/**
|
||||
* * Name: Category cloud
|
||||
* * Description: Display category links in a cloud
|
||||
* * Requires: channel, cards, articles
|
||||
*/
|
||||
|
||||
|
||||
class Catcloud {
|
||||
|
||||
function widget($arr) {
|
||||
@@ -22,7 +29,7 @@ class Catcloud {
|
||||
return card_catblock(\App::$profile['profile_uid'], $limit, '', \App::$profile['channel_hash']);
|
||||
|
||||
case 'articles':
|
||||
|
||||
|
||||
if(! perm_is_allowed(\App::$profile['profile_uid'], get_observer_hash(), 'view_pages'))
|
||||
return '';
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Category cloud wall
|
||||
* * Description: Display category links in a cloud restricted to wall posts
|
||||
* * Requires: channel
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
class Catcloud_wall {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* * Name: Categories
|
||||
* * Description: Display a menu with links to categories
|
||||
* * Requires: channel, articles, cards, cloud
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use App;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user