Compare commits
392 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aeb05628b | ||
|
|
b464fae3bf | ||
|
|
a34ce0732d | ||
|
|
f457b6623d | ||
|
|
01ebd51fb2 | ||
|
|
cb25fc031b | ||
|
|
6c6fc82f43 | ||
|
|
990017b588 | ||
|
|
192ab22cda | ||
|
|
5e5a0d7c91 | ||
|
|
2dc1adf091 | ||
|
|
371b8440c3 | ||
|
|
49509e7347 | ||
|
|
66f5b34c07 | ||
|
|
6a3d372050 | ||
|
|
c95359024c | ||
|
|
edf898d7b7 | ||
|
|
ee0060619d | ||
|
|
4f8ede35bd | ||
|
|
9d9c102da8 | ||
|
|
3de8f5e7de | ||
|
|
a18e873d08 | ||
|
|
b3c260a145 | ||
|
|
1097bcdaf9 | ||
|
|
cfde1be097 | ||
|
|
6df4da5313 | ||
|
|
f910de849f | ||
|
|
d6eaeba239 | ||
|
|
5c2e10c01e | ||
|
|
8754f72e63 | ||
|
|
569f243ebd | ||
|
|
651a3f8380 | ||
|
|
40714ecdd0 | ||
|
|
d4b1bcd641 | ||
|
|
acc1834b0d | ||
|
|
e237cf226a | ||
|
|
7c5a0887cc | ||
|
|
0745d0616a | ||
|
|
9cbb9a4874 | ||
|
|
14f3b72c82 | ||
|
|
b05845f495 | ||
|
|
2114779037 | ||
|
|
937b6d360e | ||
|
|
0d30eed4a7 | ||
|
|
39d4f67417 | ||
|
|
68d989c79e | ||
|
|
9600789d6b | ||
|
|
ea7559c158 | ||
|
|
baa12b7497 | ||
|
|
ac4aa6a9ea | ||
|
|
732dbfd6f5 | ||
|
|
5860abf46f | ||
|
|
2874d3e1e1 | ||
|
|
42b0205ad0 | ||
|
|
36778850ee | ||
|
|
19c0e97658 | ||
|
|
fe018d646a | ||
|
|
24132e56d9 | ||
|
|
8fc0210428 | ||
|
|
64560cbca9 | ||
|
|
6e97c97920 | ||
|
|
916edcb45e | ||
|
|
8873c10364 | ||
|
|
77e1220cf9 | ||
|
|
f402baffd3 | ||
|
|
216f3755fc | ||
|
|
d846cefade | ||
|
|
f3efdbf230 | ||
|
|
826ef11247 | ||
|
|
b68ddc4cd3 | ||
|
|
41f909c415 | ||
|
|
0b4e086376 | ||
|
|
5af3c35778 | ||
|
|
dddcddc453 | ||
|
|
754d90a676 | ||
|
|
8b0dce56ad | ||
|
|
42696606e3 | ||
|
|
b645ede168 | ||
|
|
6e12b5ec08 | ||
|
|
fbf36992be | ||
|
|
e0de813700 | ||
|
|
39448a0871 | ||
|
|
4fb37ef6f3 | ||
|
|
a9d4adaf23 | ||
|
|
70dfce356b | ||
|
|
10fbfa06e9 | ||
|
|
6315757967 | ||
|
|
9ddd840897 | ||
|
|
6c5627ac0e | ||
|
|
c2d6d376a4 | ||
|
|
55532c7cb1 | ||
|
|
a93fed5ae2 | ||
|
|
ba1b48f177 | ||
|
|
898762dd95 | ||
|
|
81ce67df94 | ||
|
|
55097c47c5 | ||
|
|
97b82fc77b | ||
|
|
b7bda0b87d | ||
|
|
6bf61dfa6b | ||
|
|
0e59cfb839 | ||
|
|
328ce0a837 | ||
|
|
34e24ea5e9 | ||
|
|
907426af5e | ||
|
|
360713c689 | ||
|
|
ee8aba3221 | ||
|
|
ae657754b0 | ||
|
|
0a730935f5 | ||
|
|
d285da09fe | ||
|
|
b291f1bad3 | ||
|
|
e1b660bfa3 | ||
|
|
0036c0cde9 | ||
|
|
49c1833a46 | ||
|
|
46fa26502b | ||
|
|
ba1e705c61 | ||
|
|
043e2ff58b | ||
|
|
deba1863f5 | ||
|
|
0e27f010f9 | ||
|
|
45b1be8962 | ||
|
|
fe9ca30c5e | ||
|
|
9e8ba5f6e2 | ||
|
|
5207e1e774 | ||
|
|
c1228d6b6d | ||
|
|
6262d351b7 | ||
|
|
27e57ff7aa | ||
|
|
74fc7508f3 | ||
|
|
3eea4f475c | ||
|
|
37b22fe542 | ||
|
|
b5b8106e7a | ||
|
|
b77100ff6d | ||
|
|
5eb6572277 | ||
|
|
69bed9c889 | ||
|
|
3c88c5e66a | ||
|
|
d40d62ac4f | ||
|
|
d23ed6b11f | ||
|
|
1e2a4a57b6 | ||
|
|
7892eeb2d2 | ||
|
|
d7ceb977da | ||
|
|
36d0594b8e | ||
|
|
3f32a5239d | ||
|
|
15a7d2d4de | ||
|
|
80ed2ff89a | ||
|
|
37a0343163 | ||
|
|
8529e2f14e | ||
|
|
b73401bd7f | ||
|
|
af839a0589 | ||
|
|
4bbeb224f6 | ||
|
|
8435d9eb13 | ||
|
|
d97df1859f | ||
|
|
46f67eaa1e | ||
|
|
54451851bb | ||
|
|
5b7387459c | ||
|
|
5d64a9c90f | ||
|
|
ffaa985339 | ||
|
|
291e12574a | ||
|
|
fc5b5ba021 | ||
|
|
056c55a963 | ||
|
|
02a0af3eef | ||
|
|
96e8316633 | ||
|
|
37878bf0a3 | ||
|
|
b4f079c4b5 | ||
|
|
18abfb11ef | ||
|
|
25dbc8a9f6 | ||
|
|
c639704f3c | ||
|
|
3dd7394247 | ||
|
|
b860b730a9 | ||
|
|
17e2877c91 | ||
|
|
b7bc28c333 | ||
|
|
fb5a52cbde | ||
|
|
6d125d02d8 | ||
|
|
0b18b35f5f | ||
|
|
9859008271 | ||
|
|
423c36f67b | ||
|
|
1e0195e439 | ||
|
|
30271bb32f | ||
|
|
e2b1670d6c | ||
|
|
2bfdfbe3cc | ||
|
|
9a85421a0e | ||
|
|
1fa59df6f3 | ||
|
|
2c93294eea | ||
|
|
316829269a | ||
|
|
55236f86e0 | ||
|
|
060210e930 | ||
|
|
9291622885 | ||
|
|
07978a061e | ||
|
|
08b2356ed1 | ||
|
|
d17934ed80 | ||
|
|
94f17f0dae | ||
|
|
7ccb2a2615 | ||
|
|
067a66b927 | ||
|
|
096fad5e8c | ||
|
|
e21e4c7127 | ||
|
|
5754ea828d | ||
|
|
5fbc203367 | ||
|
|
08884c44fb | ||
|
|
bd04ca21a4 | ||
|
|
19ae8cfdfc | ||
|
|
86e953f495 | ||
|
|
4bc4f5b2a6 | ||
|
|
5f2e808497 | ||
|
|
4f69e02768 | ||
|
|
e6ce2885c0 | ||
|
|
ec19ee9d82 | ||
|
|
983f063d33 | ||
|
|
eb6a143fff | ||
|
|
1881029040 | ||
|
|
209651705d | ||
|
|
fab3c92a7c | ||
|
|
8ad7376865 | ||
|
|
c41831aff9 | ||
|
|
8515aa6966 | ||
|
|
691de5bf2e | ||
|
|
2e155892fe | ||
|
|
6680c2faf3 | ||
|
|
decc8f2162 | ||
|
|
7d7a0c160f | ||
|
|
e89563eb4c | ||
|
|
dd204ec34f | ||
|
|
b3a5dd8aa8 | ||
|
|
26ee56f39c | ||
|
|
300b0e27bd | ||
|
|
29489f62cf | ||
|
|
09465619e5 | ||
|
|
390af7722d | ||
|
|
e18157f818 | ||
|
|
5435d2881c | ||
|
|
2e8f3d1869 | ||
|
|
3ad1cab006 | ||
|
|
b806a3ccc2 | ||
|
|
5e780ba089 | ||
|
|
c0a7dfe2f6 | ||
|
|
fe50d78a0f | ||
|
|
e513950cb5 | ||
|
|
adc6390a22 | ||
|
|
9449e8bd61 | ||
|
|
f13af0f60b | ||
|
|
acdb773f89 | ||
|
|
651a288148 | ||
|
|
b0664f7349 | ||
|
|
51586037e1 | ||
|
|
f573c1772a | ||
|
|
f08e91e19d | ||
|
|
8cd9fff26a | ||
|
|
d489a2854e | ||
|
|
9cfd1c2318 | ||
|
|
2dd0677d23 | ||
|
|
00d403e729 | ||
|
|
d83e2daf36 | ||
|
|
8fe6aede03 | ||
|
|
fa4ab45692 | ||
|
|
f57fbaa5dd | ||
|
|
aba8002170 | ||
|
|
9cc85adf47 | ||
|
|
01ed001041 | ||
|
|
403539919a | ||
|
|
52ea2fa33e | ||
|
|
ecd4754f6d | ||
|
|
f71033b30d | ||
|
|
885068834f | ||
|
|
c4c4ab2f3d | ||
|
|
aec3247952 | ||
|
|
b05b756148 | ||
|
|
03819abb22 | ||
|
|
d074e2aba0 | ||
|
|
2bbecfe8dd | ||
|
|
e078e13325 | ||
|
|
9d3b852d38 | ||
|
|
fadb0a5bf2 | ||
|
|
fa7aa6cedb | ||
|
|
6df98f2fad | ||
|
|
c597017402 | ||
|
|
9cb95f6065 | ||
|
|
477b1535a2 | ||
|
|
1d652cfcbd | ||
|
|
28b604c7c7 | ||
|
|
8c11be07cd | ||
|
|
e8dd2c28ff | ||
|
|
0bdffc4a2d | ||
|
|
94b1fe4a8b | ||
|
|
11ed445319 | ||
|
|
400dfb4e6b | ||
|
|
6b951734ce | ||
|
|
000fcfd1ac | ||
|
|
051e2ed6cd | ||
|
|
aac406a245 | ||
|
|
ef2952b5fd | ||
|
|
ffdf54b097 | ||
|
|
58593d7da6 | ||
|
|
3d13f36ce2 | ||
|
|
8c843ec6d0 | ||
|
|
232c7f5301 | ||
|
|
16cd8caef3 | ||
|
|
43dabee53d | ||
|
|
f016760851 | ||
|
|
99b5166f21 | ||
|
|
4aa29db7aa | ||
|
|
f5b8b18c8e | ||
|
|
6e5566f9c8 | ||
|
|
ca216ae819 | ||
|
|
4713241444 | ||
|
|
4917170a0d | ||
|
|
87775ae37a | ||
|
|
eaa244a2a3 | ||
|
|
db91d66d1a | ||
|
|
4d64481564 | ||
|
|
0a31fc176c | ||
|
|
659a8c967c | ||
|
|
626887a792 | ||
|
|
256b66de41 | ||
|
|
5ee4f37b8d | ||
|
|
3dc122db84 | ||
|
|
99c5a4e2f8 | ||
|
|
f922a92ffa | ||
|
|
a36de8ba1a | ||
|
|
e3d30763da | ||
|
|
c73518d8ec | ||
|
|
ed0d2fed66 | ||
|
|
960bcb6b53 | ||
|
|
6252340804 | ||
|
|
517d67b2e0 | ||
|
|
e95b7ca3a0 | ||
|
|
c771d7c31a | ||
|
|
ce0e8d7497 | ||
|
|
852678e238 | ||
|
|
16e6eec3fb | ||
|
|
afe8552be6 | ||
|
|
cd0e50da24 | ||
|
|
85001c034b | ||
|
|
a56f6576e2 | ||
|
|
d3e5d05026 | ||
|
|
322b619a71 | ||
|
|
dff906ca69 | ||
|
|
515d1d5e63 | ||
|
|
bb6ed22594 | ||
|
|
d655e1d765 | ||
|
|
db70ed006d | ||
|
|
ce1dd5c632 | ||
|
|
9e2a253dda | ||
|
|
95c645865d | ||
|
|
ceb510bbf5 | ||
|
|
2590e3c99b | ||
|
|
f2f9cfaf28 | ||
|
|
62db8c3969 | ||
|
|
ae3db366e5 | ||
|
|
57570c144a | ||
|
|
c3a235242e | ||
|
|
b629eb5657 | ||
|
|
2e674cd0b3 | ||
|
|
3330e9a19a | ||
|
|
c5f6208396 | ||
|
|
c0d93bbcf4 | ||
|
|
db941e7007 | ||
|
|
4761857157 | ||
|
|
3aefe23184 | ||
|
|
6f852814fd | ||
|
|
b15e521b0e | ||
|
|
63c401e6d6 | ||
|
|
e59750e8de | ||
|
|
9c184ddfd0 | ||
|
|
9df6e821d8 | ||
|
|
9551dc5ecd | ||
|
|
d372daff60 | ||
|
|
f742e6e394 | ||
|
|
414b2b0e4c | ||
|
|
603c5692ae | ||
|
|
b35e994d1b | ||
|
|
abe2ab229a | ||
|
|
5ad9939bcf | ||
|
|
ce451128ba | ||
|
|
70470016cc | ||
|
|
2122ea77e1 | ||
|
|
69266cd6c6 | ||
|
|
062d61567e | ||
|
|
d6120fc908 | ||
|
|
91f8e7a07b | ||
|
|
f57d89245c | ||
|
|
c307a71f53 | ||
|
|
1e4e59bb57 | ||
|
|
f62d16d274 | ||
|
|
f175712d4b | ||
|
|
5f942d78e6 | ||
|
|
538c8885ad | ||
|
|
c8158c3d62 | ||
|
|
1f4762060f | ||
|
|
81c3682781 | ||
|
|
2e6e1fdd55 | ||
|
|
1a09cd560b | ||
|
|
8c9d2bc6f6 | ||
|
|
78ad5ca713 | ||
|
|
43c2e71b25 | ||
|
|
5b9f32fade | ||
|
|
76a1a6da34 | ||
|
|
a2b0abc90d |
33
.gitignore
vendored
@@ -49,6 +49,8 @@ doc/html/
|
||||
# external repositories for themes/addons
|
||||
extend/
|
||||
# files generated by phpunit
|
||||
tests/.cache
|
||||
tests/.phpunit.result.cache
|
||||
tests/results/
|
||||
|
||||
## exclude IDE files
|
||||
@@ -78,5 +80,36 @@ composer.phar
|
||||
vendor/**/tests/
|
||||
vendor/**/Test/
|
||||
vendor/sabre/*/examples/
|
||||
|
||||
# Exclude dev dependencies
|
||||
vendor/bin/pdepend
|
||||
vendor/bin/php-parse
|
||||
vendor/bin/phpcbf
|
||||
vendor/bin/phpcs
|
||||
vendor/bin/phpmd
|
||||
vendor/bin/phpunit
|
||||
vendor/composer/pcre/
|
||||
vendor/composer/xdebug-handler/
|
||||
vendor/dms/
|
||||
vendor/doctrine/
|
||||
vendor/myclabs/
|
||||
vendor/nikic/
|
||||
vendor/pdepend/
|
||||
vendor/phar-io/
|
||||
vendor/php-mock/
|
||||
vendor/phpmd/
|
||||
vendor/phpunit/
|
||||
vendor/psr/container/
|
||||
vendor/sebastian/
|
||||
vendor/squizlabs/
|
||||
vendor/symfony/config/
|
||||
vendor/symfony/dependency-injection/
|
||||
vendor/symfony/deprecation-contracts/
|
||||
vendor/symfony/filesystem/
|
||||
vendor/symfony/polyfill-ctype/
|
||||
vendor/symfony/polyfill-mbstring/
|
||||
vendor/symfony/polyfill-php80/
|
||||
vendor/symfony/service-contracts/
|
||||
vendor/theseer/
|
||||
# /info is a directory containing site-specific HTML documents
|
||||
/info/
|
||||
|
||||
177
.gitlab-ci.yml
@@ -1,10 +1,3 @@
|
||||
# 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: php:8.1
|
||||
|
||||
stages:
|
||||
- test
|
||||
- deploy
|
||||
@@ -24,6 +17,7 @@ variables:
|
||||
# Ignore a Composer warning
|
||||
COMPOSER_ALLOW_SUPERUSER: 1
|
||||
# Configure MySQL/MariaDB service (https://hub.docker.com/_/mysql/, https://hub.docker.com/_/mariadb/)
|
||||
DB_HOST: mysql
|
||||
MYSQL_DATABASE: hello_world_test
|
||||
MYSQL_ROOT_PASSWORD: mysql
|
||||
# Configure PostgreSQL service (https://hub.docker.com/_/postgres/)
|
||||
@@ -33,58 +27,69 @@ variables:
|
||||
|
||||
|
||||
before_script:
|
||||
# pecl and composer do not work with PHP production restrictions (from Hubzilla Docker image)
|
||||
- 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
|
||||
- php ./composer.phar install --no-progress
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for PHP
|
||||
.job_template_php: &job_definition_php
|
||||
stage: test
|
||||
script:
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||
# Install & enable Xdebug for code coverage reports
|
||||
- apt-get update
|
||||
- apt-get install -yqq libicu-dev libjpeg-dev libpng-dev libpq-dev libyaml-dev libzip-dev mariadb-client postgresql-client unzip zip
|
||||
- pecl install xdebug yaml
|
||||
- docker-php-ext-enable xdebug yaml
|
||||
- docker-php-ext-install gd bcmath intl pdo_mysql pdo_pgsql zip
|
||||
|
||||
# Install composer
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
# Install dev libraries from composer
|
||||
- php ./composer.phar install --no-progress
|
||||
# php.ini settings
|
||||
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
|
||||
|
||||
# hidden job definition with template for MySQL/MariaDB
|
||||
#.job_template_mysql: &job_definition_mysql
|
||||
# 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
|
||||
.job_template_mysql: &job_definition_mysql
|
||||
stage: test
|
||||
variables:
|
||||
HZ_TEST_DB_HOST: $DB_HOST
|
||||
HZ_TEST_DB_TYPE: mysql
|
||||
HZ_TEST_DB_USER: root
|
||||
HZ_TEST_DB_PASS: $MYSQL_ROOT_PASSWORD
|
||||
HZ_TEST_DB_DATABASE: $MYSQL_DATABASE
|
||||
script:
|
||||
# Import hubzilla's DB schema
|
||||
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
|
||||
# Run the actual tests
|
||||
- touch dbfail.out
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --verbose --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
|
||||
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
|
||||
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
|
||||
|
||||
|
||||
# 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();"
|
||||
# Import hubzilla's DB schema
|
||||
# - psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
# - vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
|
||||
.job_template_postgres: &job_definition_postgres
|
||||
stage: test
|
||||
variables:
|
||||
HZ_TEST_DB_HOST: postgres
|
||||
HZ_TEST_DB_TYPE: postgres
|
||||
HZ_TEST_DB_USER: $POSTGRES_USER
|
||||
HZ_TEST_DB_PASS: $POSTGRES_PASSWORD
|
||||
HZ_TEST_DB_DATABASE: $POSTGRES_DB
|
||||
script:
|
||||
- export PGPASSWORD=$POSTGRES_PASSWORD
|
||||
- psql --version
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||
# Import hubzilla's DB schema
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||
# Show databases and relations/tables of hubzilla's database
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||
# Run the actual tests
|
||||
- touch dbfail.out
|
||||
- vendor/bin/phpunit --configuration tests/phpunit.xml --verbose --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
|
||||
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
|
||||
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
|
||||
|
||||
# hidden job definition with artifacts config template
|
||||
.artifacts_template:
|
||||
artifacts: &artifacts_template
|
||||
.artifacts_template: &artifacts_template
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
# Gitlab should show the results, but has problems parsing PHPUnit's junit file.
|
||||
reports:
|
||||
@@ -95,54 +100,30 @@ before_script:
|
||||
- tests/results/
|
||||
|
||||
|
||||
# PHP8.1
|
||||
php8.1:
|
||||
<<: *job_definition_php
|
||||
# PHP8.1 with MySQL 8.0
|
||||
php8.1_mysql8.0.22:
|
||||
image: php:8.1
|
||||
services:
|
||||
- mysql:8.0
|
||||
<<: *job_definition_mysql
|
||||
<<: *artifacts_template
|
||||
|
||||
# PHP8.0 with MySQL 5.7
|
||||
#php8.0_mysql5.7:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - mysql:5.7
|
||||
# PHP8.1 with MariaDB 10.6
|
||||
php8.1_mariadb10.6:
|
||||
image: php:8.1
|
||||
services:
|
||||
- name: mariadb:10.6
|
||||
alias: mysql
|
||||
<<: *job_definition_mysql
|
||||
<<: *artifacts_template
|
||||
|
||||
|
||||
# PHP8.0 with MySQL 8 (latest)
|
||||
#php8.0_mysql8:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - name: mysql:8
|
||||
# command: ["--default-authentication-plugin=mysql_native_password"]
|
||||
|
||||
|
||||
# PHP8.0 with MariaDB 10.2
|
||||
#php8.0_mariadb10.2:
|
||||
# <<: *job_definition_mysql
|
||||
# services:
|
||||
# - name: mariadb:10.2
|
||||
# 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)
|
||||
#php7.3_postgres11:
|
||||
# <<: *job_definition_postgres
|
||||
# artifacts: *artifacts_template
|
||||
|
||||
|
||||
# PHP7.3 with PostgreSQL latest (11)
|
||||
#php7.3_postgres11:
|
||||
# <<: *job_definition_postgres
|
||||
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||
# artifacts: *artifacts_template
|
||||
# PHP8.1 with PostgreSQL 12
|
||||
php8.1_postgres12:
|
||||
image: php:8.1
|
||||
services:
|
||||
- postgres:12-alpine
|
||||
<<: *job_definition_postgres
|
||||
<<: *artifacts_template
|
||||
|
||||
|
||||
# Generate Doxygen API Documentation and deploy it as GitLab pages
|
||||
|
||||
@@ -25,10 +25,10 @@ AddType audio/ogg .oga
|
||||
# in CGI mode.
|
||||
|
||||
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
|
||||
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
|
||||
</IfModule>
|
||||
|
||||
|
||||
138
CHANGELOG
@@ -1,3 +1,139 @@
|
||||
Hubzilla 9.0 (2024-03-22)
|
||||
- Refactor browser to browser encryption based on sodium plus library
|
||||
- Added developer docs for the refactored test system
|
||||
- Move escape_tags() to Lib/Text::escape_tags() and add test
|
||||
- Messages are now sent as articles instead of notes - this can be configured for activitypub
|
||||
- Implement support for custom emojis
|
||||
- Add test for Lib/Activity::get_textfield()
|
||||
- Refactor mod things to be AS2 compliant
|
||||
- Implement basic bbcode tests and minor refactor
|
||||
- Refactor profile activities to be AS2 complient
|
||||
- Removed poke and moods app
|
||||
- Cleanup deprecated/unused activity types
|
||||
- Update doxygen config for generating online API docs
|
||||
- Make DBA driver transaction aware
|
||||
- Deprecate internal usage of ActivityStreams1 in favor of ActivityStreams2
|
||||
- Introduce Lib/Activity::get_actor() force flag to omit cache
|
||||
- Refactor mod contactedit refresh
|
||||
- Require intl PHP extension
|
||||
- Improved checks in Web/HTTPSig::find_headers()
|
||||
- Implement custom sass bootstrap builds for channels and site
|
||||
- Mark items verified in zot delivery if either JSalmon, LDSignature or EddsaSignature verified
|
||||
- Added support for code blocks with language in markdown and html
|
||||
- Improved conversation item design
|
||||
- Start using uuid for internal reference instead of base64 encoded mid
|
||||
- Store seen mids in session instead of cache
|
||||
- Increase sess_data DB column to medium text
|
||||
- Introduce Lib/Activity::init_background_fetch()
|
||||
- Refactor zotconvo daemon
|
||||
- Implement short time object cache to reduce network calls (performance)
|
||||
- Refactor Lib/Activity::fetch_and_store_parents()
|
||||
- Introduce the fetchparents daemon
|
||||
- Refactor Libzot::process_delivery()
|
||||
- Start processing source xchan in xchan_query()
|
||||
- Added CI job for MariaDB 10.6
|
||||
- Store the original announce actor (the one that pushed the item into our stream first) in source_xchan instead of owner_xchan to preserve the original owner
|
||||
- Added optional circle person avatar
|
||||
- Added min supported DB backends to administrator docs: MySql v >= 8.0.22, MariaDB v >= 10.6, PostgreSql v >= 12
|
||||
- Added CI job for MySql 8.0
|
||||
- Improved validate_email()
|
||||
- Implement fep-8b32 - object integrity proofs
|
||||
- Implement native repeats
|
||||
- Updated spanish strings
|
||||
- Add tests for check_account_email()
|
||||
- Vastly improved unit tests including the database
|
||||
- Require sodium PHP extension
|
||||
- Require bcmath or gmp PHP extension
|
||||
- Deprecate simplepie idna_convert()
|
||||
- Update apache rewite rule to fix issue with recent apache versions - issue #1822
|
||||
- Display selected mid in an open state - issue #1425
|
||||
- Add bookmark and category to AP schema
|
||||
|
||||
Bugfixes
|
||||
- Fix cover photos not uploaded into folder due to missing source option
|
||||
- Fix regression where config returned default value in some cases
|
||||
- Fix attachments listed in reverse order
|
||||
- Fix unterminated entity reference error when dealing with domxpath and add a test
|
||||
- Fix obsolete system language selector in admin/site
|
||||
- Fix imagick readImageBlob() exception not handled
|
||||
- Fix content not moved to new location if folder was renamed via webdav
|
||||
- Fix bootstrap namespaces not up-to-date in htmlpurifier
|
||||
- Fix inReplyTo field in Lib/Activity not dealing with arrays
|
||||
- Fix round buttons not being round
|
||||
- Fix import from ical if timezone was not set in the source data
|
||||
- Fix hard linebreaks from markdown and html not preserved in bbcode conversion
|
||||
- Fix indentation from markdown and html not preserved in bbcode conversion
|
||||
- Fix images with alt text from markdown and not preserved in bbcode conversion
|
||||
- Fix custom emoji reactions arriving from pleroma
|
||||
- Fix issue where if an item is created and deleted again before the notifier has completed the queueworker will dismiss the delete because it looks like a duplicate entry
|
||||
- Fix handling HTML entities via mbstring is deprecated
|
||||
- Fix various PHP deprecation warnings
|
||||
- Fix apache rewite rule to fix issue with recent apache versions - issue #1822
|
||||
- Fix display selected mid in an open state - issue #1425
|
||||
|
||||
Addons
|
||||
- Removed smileybutton addon
|
||||
- Removed smiley_pack addon
|
||||
- Pubcrawl: refactor presentation of encrypted messages
|
||||
- Removed deprecated cryptojs addon
|
||||
- Removed emojione addon
|
||||
- New addon emoji which can provide different emoji sets via config.system.emoji_set variable - emojitwo (default), openmoji, mutant are currently supported
|
||||
- Removed addon moremoods
|
||||
- Removed addon morepokes
|
||||
- Pubcrawl: implement actor_refetch hook
|
||||
- Diaspora: implement actor_refetch hook
|
||||
- Navbanner_options: fix PHP warnings
|
||||
- Pubcrawl: add assertionMethod to encode_person()
|
||||
- Socialauth: cleanup unused files
|
||||
- Openstreetmap: adjust URLs
|
||||
|
||||
|
||||
Hubzilla 8.8.8 (2024-02-29)
|
||||
- Streams compatibility fixes
|
||||
|
||||
|
||||
Hubzilla 8.8.7 (2024-01-19)
|
||||
- Fix regression in Activity::actor_store()
|
||||
|
||||
|
||||
Hubzilla 8.8.6 (2024-01-11)
|
||||
- Provide more builtin jsonld files
|
||||
- Development branch compatibility in Libsync
|
||||
|
||||
|
||||
Hubzilla 8.8.5 (2024-01-01)
|
||||
- Fix possible loop if DB is not reachable (introduced in 8.8.3)
|
||||
- Fix some errors and deprecation warnings with PHP 8.2
|
||||
- Deprecate simplepie idna_convert in favor of PHP native function
|
||||
- Fix double processed quoted strings in get_tags()
|
||||
|
||||
|
||||
Hubzilla 8.8.4 (2023-12-20)
|
||||
- Fix regression introduced in version 8.8.3
|
||||
- Add test for Lib/Config
|
||||
- Add active addons and blocked sites to siteinfo
|
||||
|
||||
|
||||
Hubzilla 8.8.3 (2023-12-17)
|
||||
- Check return from Config::Load() and retry on failure
|
||||
- Libzot::import() do not prozess items where we could not fetch the author
|
||||
- Translation updates for Norwegian Bokmål (nb_NO)
|
||||
- Add the app terms before syncing, otherwise the terms will be reset at the other end
|
||||
- Addon statistics: deprecate nodeinfo 1.0 and implement nodeinfo 2.1
|
||||
- Addon cards: fix PHP error
|
||||
|
||||
|
||||
Hubzilla 8.8.2 (2023-12-06)
|
||||
- Fix missing includes - issue #1820
|
||||
- Addon logger_stats: improved performance reading big log files
|
||||
|
||||
|
||||
Hubzilla 8.8.1 (2023-11-27)
|
||||
- Fix error in cards addon
|
||||
- Fix error in articles addon
|
||||
- Fix double left and right template css
|
||||
|
||||
|
||||
Hubzilla 8.8 (2023-11-25)
|
||||
- Add additional observer and channel info for nav templates
|
||||
- Do not provide confidential channel info for templates
|
||||
@@ -30,7 +166,6 @@ Hubzilla 8.8 (2023-11-25)
|
||||
- Transparent background for colorbox controls icons
|
||||
- Use body background color for colorboxes in redbasic
|
||||
|
||||
|
||||
Bugfixes
|
||||
- Remove fragment from actor urls
|
||||
- HTTPsig case insensitive digest algorithm
|
||||
@@ -45,7 +180,6 @@ Hubzilla 8.8 (2023-11-25)
|
||||
- Fix sabre/dav caldav php warnings
|
||||
- Fix public stream comments/reactions not allowed if item_fetched is set
|
||||
|
||||
|
||||
Addons
|
||||
- Superblock: fix php warnings
|
||||
- Pubcrawl: restrict mod ap_probe to admin and add checkbox for signed requests
|
||||
|
||||
@@ -124,13 +124,13 @@ class Cron {
|
||||
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
if ($r) {
|
||||
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||
intval(PHOTO_CACHE),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
foreach ($r as $rr) {
|
||||
$file = dbunescbin($rr['content']);
|
||||
|
||||
@@ -65,10 +65,10 @@ class Cron_daily {
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up emdedded content cache
|
||||
// Clean up cache
|
||||
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
|
||||
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
|
||||
);
|
||||
|
||||
//update statistics in config
|
||||
|
||||
@@ -43,8 +43,8 @@ class Expire {
|
||||
|
||||
logger('expire: start with pid ' . $pid, LOGGER_DEBUG);
|
||||
|
||||
$site_expire = intval(get_config('system', 'default_expire_days'));
|
||||
$commented_days = intval(get_config('system', 'active_expire_days'));
|
||||
$site_expire = intval(get_config('system', 'default_expire_days', 30));
|
||||
$commented_days = intval(get_config('system', 'active_expire_days', 7));
|
||||
|
||||
logger('site_expire: ' . $site_expire);
|
||||
|
||||
|
||||
42
Zotlabs/Daemon/Fetchparents.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
class Fetchparents {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
logger('Fetchparents invoked: ' . print_r($argv, true));
|
||||
|
||||
if ($argc < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channels = explode(',', $argv[1]);
|
||||
if (!$channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
$observer_hash = $argv[2];
|
||||
if (!$observer_hash) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mid = $argv[3];
|
||||
if (!$mid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$force = $argv[4] ?? false;
|
||||
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
Activity::fetch_and_store_parents($channel, $observer_hash, $mid, null, $force);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ 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');
|
||||
@@ -271,14 +270,13 @@ class Notifier {
|
||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||
|
||||
if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
|
||||
intval($target_item['item_blocked']) ||
|
||||
(intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
|
||||
intval($target_item['item_blocked']) || intval($target_item['item_hidden'])) {
|
||||
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
// follow/unfollow is for internal use only
|
||||
if (in_array($target_item['verb'], [ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
|
||||
if (in_array($target_item['verb'], ['Follow', 'Ignore', ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
|
||||
logger('not fowarding follow/unfollow note activity');
|
||||
return;
|
||||
}
|
||||
@@ -342,14 +340,7 @@ 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);
|
||||
self::$encoded_item = Activity::build_packet(Activity::encode_activity($target_item), self::$channel, false);
|
||||
}
|
||||
|
||||
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
|
||||
@@ -382,7 +373,8 @@ class Notifier {
|
||||
|
||||
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
|
||||
logger('notifier: followup relay', LOGGER_DEBUG);
|
||||
$sendto = (($uplink) ? $parent_item['source_xchan'] : (($parent_item['verb'] === ACTIVITY_SHARE) ? $parent_item['author_xchan'] : $parent_item['owner_xchan']));
|
||||
// If the Parent item is an Announce the real owner is the parent author
|
||||
$sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
|
||||
self::$recipients = [$sendto];
|
||||
self::$private = true;
|
||||
$upstream = true;
|
||||
|
||||
@@ -10,7 +10,12 @@ class Zotconvo {
|
||||
|
||||
logger('Zotconvo invoked: ' . print_r($argv, true));
|
||||
|
||||
if ($argc != 3) {
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channels = explode(',', $argv[1]);
|
||||
if (!$channels) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,12 +24,12 @@ class Zotconvo {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = channelx_by_n(intval($argv[1]));
|
||||
if (!$channel) {
|
||||
return;
|
||||
}
|
||||
$force = $argv[3] ?? false;
|
||||
|
||||
Libzot::fetch_conversation($channel, $mid);
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
Libzot::fetch_conversation($channel, $mid, $force);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
||||
33
Zotlabs/Lib/ASCache.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* A wrapper for the cache api
|
||||
*/
|
||||
|
||||
class ASCache {
|
||||
public static function isEnabled() {
|
||||
return Config::Get('system', 'as_object_cache_enabled', true);
|
||||
}
|
||||
|
||||
public static function getAge() {
|
||||
return Config::Get('system', 'as_object_cache_time', '10 MINUTE');
|
||||
}
|
||||
|
||||
public static function Get($key) {
|
||||
if (!self::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Cache::get($key, self::getAge());
|
||||
}
|
||||
|
||||
public static function Set($key, $value) {
|
||||
if (!self::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cache::set($key, $value);
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,11 @@ class ActivityStreams {
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
public $saved_recips = null;
|
||||
|
||||
/**
|
||||
* @brief Constructor for ActivityStreams.
|
||||
@@ -88,7 +89,16 @@ class ActivityStreams {
|
||||
|
||||
// Attempt to assemble an Activity from what we were given.
|
||||
if ($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->id = $this->get_property_obj('id');
|
||||
|
||||
if (!$this->id) {
|
||||
logger('Data with mmissing id: ' . print_r($this->data, true));
|
||||
return;
|
||||
}
|
||||
|
||||
// cache for future use
|
||||
ASCache::Set($this->id, 'json:' . $this->raw);
|
||||
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor', '', '');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
@@ -96,11 +106,19 @@ class ActivityStreams {
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if ($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']);
|
||||
$this->sig = $this->get_compound_property('proof');
|
||||
if ($this->sig) {
|
||||
$this->checkEddsaSignature(); // will set signer and sigok if everything works out
|
||||
}
|
||||
|
||||
// Try LDSignatures if edsig failed
|
||||
if (!$this->sigok) {
|
||||
$this->sig = $this->get_compound_property('signature');
|
||||
if ($this->sig) {
|
||||
$this->signer = $this->get_actor('creator', $this->sig);
|
||||
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']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,24 +130,31 @@ class ActivityStreams {
|
||||
}
|
||||
}
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
// Fetch recursive or embedded activities
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property('object', $this->obj);
|
||||
}
|
||||
|
||||
if ($this->obj && is_array($this->obj) && isset($this->obj['actor']))
|
||||
// Enumerate and store actors in referenced objects
|
||||
|
||||
if ($this->obj && is_array($this->obj) && isset($this->obj['actor'])) {
|
||||
$this->obj['actor'] = $this->get_actor('actor', $this->obj);
|
||||
if ($this->tgt && is_array($this->tgt) && isset($this->tgt['actor']))
|
||||
}
|
||||
|
||||
if ($this->tgt && is_array($this->tgt) && isset($this->tgt['actor'])) {
|
||||
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
|
||||
}
|
||||
|
||||
// Determine if this is a followup or response activity
|
||||
|
||||
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||
|
||||
if (!$this->parent_id && is_array($this->obj) && isset($this->obj['inReplyTo'])) {
|
||||
$this->parent_id = $this->obj['inReplyTo'];
|
||||
if (!$this->parent_id && isset($this->obj['inReplyTo'])) {
|
||||
$this->parent_id = ((is_array($this->obj['inReplyTo'])) ? $this->obj['inReplyTo']['id'] : $this->obj['inReplyTo']);
|
||||
}
|
||||
|
||||
if (!$this->parent_id && is_array($this->obj) && isset($this->obj['id'])) {
|
||||
if (!$this->parent_id && isset($this->obj['id'])) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
|
||||
@@ -318,9 +343,10 @@ class ActivityStreams {
|
||||
if ($x === null && strpos($url, '/channel/')) {
|
||||
// look for other nomadic channels which might be alive
|
||||
$zf = Zotfinger::exec($url, $channel);
|
||||
|
||||
$url = $zf['signature']['signer'];
|
||||
$x = Activity::fetch($url, $channel);
|
||||
if ($zf) {
|
||||
$url = $zf['signature']['signer'];
|
||||
$x = Activity::fetch($url, $channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +361,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, ['Announce', 'Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,12 +410,24 @@ class ActivityStreams {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
|
||||
if ($this->is_url($x)) {
|
||||
$y = $this->fetch_property($x);
|
||||
$cached = ASCache::Get($x);
|
||||
if ($cached) {
|
||||
// logger('AS cached: ' . $x);
|
||||
$y = unserialise($cached);
|
||||
}
|
||||
else {
|
||||
// logger('AS fetching: ' . $x);
|
||||
$y = $this->fetch_property($x);
|
||||
if ($y) {
|
||||
ASCache::Set($x, serialise($y));
|
||||
}
|
||||
}
|
||||
if (is_array($y)) {
|
||||
$x = $y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
|
||||
if (is_array($x) && array_key_exists('signed', $x)) {
|
||||
@@ -489,4 +527,58 @@ class ActivityStreams {
|
||||
|
||||
}
|
||||
|
||||
public function checkEddsaSignature() {
|
||||
$signer = $this->get_property_obj('verificationMethod', $this->sig);
|
||||
|
||||
$parseUrl = parse_url($signer);
|
||||
|
||||
if (isset($parseUrl['fragment'])) {
|
||||
if (str_starts_with($parseUrl['fragment'], 'z6Mk')) {
|
||||
$publicKey = $parseUrl['fragment'];
|
||||
}
|
||||
unset($parseUrl['fragment']);
|
||||
}
|
||||
|
||||
if (isset($parseUrl['query'])) {
|
||||
unset($parseUrl['query']);
|
||||
}
|
||||
|
||||
$url = unparse_url($parseUrl);
|
||||
|
||||
$hublocs = Activity::get_actor_hublocs($url);
|
||||
|
||||
$hasStoredKey = false;
|
||||
if ($hublocs) {
|
||||
foreach ($hublocs as $hubloc) {
|
||||
if ($publicKey && $hubloc['xchan_epubkey'] === $publicKey) {
|
||||
$hasStoredKey = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasStoredKey) {
|
||||
$this->signer = Activity::get_actor($url);
|
||||
|
||||
if (isset($this->signer['assertionMethod'])) {
|
||||
if (!isset($this->signer['assertionMethod'][0])) {
|
||||
$this->signer['assertionMethod'] = [$this->signer['assertionMethod']];
|
||||
}
|
||||
|
||||
foreach($this->signer['assertionMethod'] as $am) {
|
||||
if ($url === $am['controller'] &&
|
||||
$am['type'] === 'Multikey' &&
|
||||
str_starts_with($am['publicKeyMultibase'], 'z6Mk')
|
||||
) {
|
||||
$publicKey = $am['publicKeyMultibase'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($publicKey) {
|
||||
$this->sigok = (new JcsEddsa2022)->verify($this->data, $publicKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -352,8 +352,6 @@ class Apps {
|
||||
'Directory' => t('Directory'),
|
||||
'Help' => t('Help'),
|
||||
'Mail' => t('Mail'),
|
||||
'Mood' => t('Mood'),
|
||||
'Poke' => t('Poke'),
|
||||
'Chat' => t('Chat'),
|
||||
'Search' => t('Search'),
|
||||
'Probe' => t('Probe'),
|
||||
|
||||
@@ -17,8 +17,8 @@ class Cache {
|
||||
*/
|
||||
|
||||
public static function get($key, $age = '') {
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
// $hash = hash('whirlpool',$key);
|
||||
$hash = uuid_from_url($key);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' AND updated > %s - INTERVAL %s LIMIT 1",
|
||||
dbesc($hash),
|
||||
@@ -32,23 +32,25 @@ class Cache {
|
||||
}
|
||||
|
||||
public static function set($key,$value) {
|
||||
// $hash = hash('whirlpool',$key);
|
||||
$hash = uuid_from_url($key);
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' LIMIT 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($hash));
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache (k, v, updated) VALUES ('%s', '%s', '%s')",
|
||||
dbesc($hash),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
class Config {
|
||||
|
||||
@@ -14,20 +15,41 @@ class Config {
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
*/
|
||||
static public function Load($family) {
|
||||
if(! array_key_exists($family, \App::$config))
|
||||
\App::$config[$family] = array();
|
||||
public static function Load($family, $recursionCounter = 0) {
|
||||
if (! array_key_exists($family, App::$config)) {
|
||||
App::$config[$family] = [];
|
||||
}
|
||||
|
||||
if(! array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
// We typically continue when presented with minor DB issues,
|
||||
// but loading the site configuration is more important.
|
||||
|
||||
// Check for query returning false and give it approx 30 seconds
|
||||
// to recover if there's a problem. This is intended to fix a
|
||||
// rare issue on Galera where temporary sync issues were causing
|
||||
// the site encryption keys to be regenerated, which was causing
|
||||
// communication issues for members.
|
||||
|
||||
// This code probably belongs at the database layer, but we don't
|
||||
// necessarily want to shut the site down for problematic queries
|
||||
// caused by bad data. That could be used in a denial of service
|
||||
// attack. Those do need to be (and they are) logged.
|
||||
|
||||
if (! array_key_exists('config_loaded', App::$config[$family])) {
|
||||
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
|
||||
if($r !== false) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
\App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
if ($r === false && !App::$install) {
|
||||
sleep(3);
|
||||
$recursionCounter ++;
|
||||
if ($recursionCounter > 10) {
|
||||
system_unavailable();
|
||||
}
|
||||
\App::$config[$family]['config_loaded'] = true;
|
||||
self::Load($family, $recursionCounter);
|
||||
}
|
||||
elseif (is_array($r)) {
|
||||
foreach ($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,19 +68,19 @@ class Config {
|
||||
* @return mixed
|
||||
* Return the set value, or false if the database update failed
|
||||
*/
|
||||
static public function Set($family, $key, $value) {
|
||||
public static function Set($family, $key, $value) {
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_array($value)) ? 'json:' . json_encode($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
if (self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
@@ -70,8 +92,8 @@ class Config {
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
|
||||
@@ -96,18 +118,34 @@ class Config {
|
||||
* @param string $default (optional) default false
|
||||
* @return mixed Return value or false on error or if not set
|
||||
*/
|
||||
static public function Get($family, $key, $default = false) {
|
||||
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
|
||||
self::Load($family);
|
||||
public static function Get($family, $key, $default = false) {
|
||||
|
||||
if(array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
if(! array_key_exists($key, \App::$config[$family])) {
|
||||
if ((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family]))) {
|
||||
self::Load($family);
|
||||
}
|
||||
|
||||
if (array_key_exists('config_loaded', App::$config[$family])) {
|
||||
if (! array_key_exists($key, App::$config[$family])) {
|
||||
return $default;
|
||||
}
|
||||
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
|
||||
? unserialize(\App::$config[$family][$key])
|
||||
: \App::$config[$family][$key]
|
||||
);
|
||||
|
||||
$value = App::$config[$family][$key];
|
||||
|
||||
if (! is_array($value)) {
|
||||
if (substr($value, 0, 5) == 'json:') {
|
||||
return json_decode(substr($value, 5), true);
|
||||
} else if (preg_match('|^a:[0-9]+:{.*}$|s', $value)) {
|
||||
// Unserialize in inherently unsafe. Try to mitigate by not
|
||||
// allowing unserializing objects. Only kept for backwards
|
||||
// compatibility. JSON serialization should be prefered.
|
||||
return unserialize($value, array('allowed_classes' => false));
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
@@ -125,12 +163,13 @@ class Config {
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($family, $key) {
|
||||
public static function Delete($family, $key) {
|
||||
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
|
||||
unset(\App::$config[$family][$key]);
|
||||
if (array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family])) {
|
||||
unset(App::$config[$family][$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
@@ -153,7 +192,7 @@ class Config {
|
||||
* The configuration key to query
|
||||
* @return mixed
|
||||
*/
|
||||
static private function get_from_storage($family,$key) {
|
||||
private static function get_from_storage($family, $key) {
|
||||
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@@ -161,5 +200,4 @@ class Config {
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,23 +6,26 @@ class DReport {
|
||||
private $location;
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $name;
|
||||
private $message_id;
|
||||
private $message_uuid;
|
||||
private $status;
|
||||
private $date;
|
||||
|
||||
function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
function __construct($location, $sender, $recipient, $message_id, $message_uuid = '', $status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->message_uuid = $message_uuid;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function update($status) {
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function set_name($name) {
|
||||
@@ -35,24 +38,26 @@ class DReport {
|
||||
|
||||
|
||||
function set($arr) {
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->message_uuid = $arr['message_uuid'] ?? '';
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
}
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'message_uuid' => $this->message_uuid,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ class Enotify {
|
||||
|
||||
if(array_key_exists('item',$params)) {
|
||||
|
||||
if(in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
if(in_array($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_SHARE])) {
|
||||
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
@@ -157,12 +157,15 @@ class Enotify {
|
||||
return;
|
||||
}
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_LIKE))
|
||||
if(activity_match($params['verb'], ['Like', ACTIVITY_LIKE]))
|
||||
$action = (($moderated) ? t('requested to like') : t('liked'));
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
|
||||
if(activity_match($params['verb'], ['Dislike', ACTIVITY_DISLIKE]))
|
||||
$action = (($moderated) ? t('requested to dislike') : t('disliked'));
|
||||
|
||||
if(activity_match($params['verb'], ACTIVITY_SHARE))
|
||||
$action = t('repeated');
|
||||
|
||||
}
|
||||
|
||||
if($params['item']['obj_type'] === 'Answer')
|
||||
@@ -259,7 +262,7 @@ class Enotify {
|
||||
|
||||
$itemlink = $params['link'];
|
||||
|
||||
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ACTIVITY_LIKE) || activity_match($params['item']['verb'], ACTIVITY_DISLIKE))) {
|
||||
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]))) {
|
||||
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE) || !feature_enabled($recip['channel_id'], 'dislike')) {
|
||||
logger('notification: not a visible activity. Ignoring.');
|
||||
pop_lang();
|
||||
@@ -310,10 +313,10 @@ class Enotify {
|
||||
//$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
|
||||
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
|
||||
|
||||
if(activity_match($params['item']['verb'], ACTIVITY_LIKE))
|
||||
if(activity_match($params['item']['verb'], ['Like', ACTIVITY_LIKE]))
|
||||
$verb = (($moderated) ? t('requested to like') : t('liked'));
|
||||
|
||||
if(activity_match($params['item']['verb'], ACTIVITY_DISLIKE))
|
||||
if(activity_match($params['item']['verb'], ['Dislike', ACTIVITY_DISLIKE]))
|
||||
$verb = (($moderated) ? t('requested to dislike') : t('disliked'));
|
||||
|
||||
// "your post"
|
||||
@@ -483,6 +486,8 @@ class Enotify {
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
|
||||
/*
|
||||
|
||||
do {
|
||||
$dups = false;
|
||||
$hash = random_string();
|
||||
@@ -491,10 +496,12 @@ class Enotify {
|
||||
if ($r)
|
||||
$dups = true;
|
||||
} while ($dups === true);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
$datarray = [];
|
||||
$datarray['hash'] = $hash;
|
||||
$datarray['hash'] = $params['item']['uuid'] ?? new_uuid();
|
||||
$datarray['sender_hash'] = $sender['xchan_hash'];
|
||||
$datarray['xname'] = $sender['xchan_name'];
|
||||
$datarray['url'] = $sender['xchan_url'];
|
||||
@@ -505,7 +512,7 @@ class Enotify {
|
||||
$datarray['link'] = $itemlink;
|
||||
$datarray['parent'] = $parent_mid;
|
||||
$datarray['parent_item'] = $parent_item;
|
||||
$datarray['ntype'] = $params['type'] ?? '';
|
||||
$datarray['ntype'] = $params['type'] ?? 0;
|
||||
$datarray['verb'] = $params['verb'] ?? '';
|
||||
$datarray['otype'] = $params['otype'] ?? '';
|
||||
$datarray['abort'] = false;
|
||||
@@ -553,8 +560,9 @@ class Enotify {
|
||||
dbesc($datarray['otype'])
|
||||
);
|
||||
|
||||
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($hash),
|
||||
$r = q("select id from notify where hash = '%s' and ntype = %d and uid = %d limit 1",
|
||||
dbesc($datarray['hash']),
|
||||
intval($datarray['ntype']),
|
||||
intval($recip['channel_id'])
|
||||
);
|
||||
if ($r) {
|
||||
@@ -835,18 +843,6 @@ class Enotify {
|
||||
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('commented on %s\'s post'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
|
||||
);
|
||||
|
||||
if($item['verb'] === ACTIVITY_SHARE && empty($item['owner']['xchan_pubforum'])) {
|
||||
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if($item['verb'] === ACTIVITY_LIKE) {
|
||||
$itemem_text = sprintf( t('liked %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if($item['verb'] === ACTIVITY_DISLIKE) {
|
||||
$itemem_text = sprintf( t('disliked %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
|
||||
}
|
||||
|
||||
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
|
||||
$itemem_text = t('shared a file with you');
|
||||
}
|
||||
@@ -867,7 +863,6 @@ class Enotify {
|
||||
|
||||
// convert this logic into a json array just like the system notifications
|
||||
|
||||
$who = (($item['verb'] === ACTIVITY_SHARE && empty($item['owner']['xchan_pubforum'])) ? 'owner' : 'author');
|
||||
$body = html2plain(bbcode($item['body'], ['drop_media' => true, 'tryoembed' => false]), 75, true);
|
||||
if ($body) {
|
||||
$body = htmlentities($body, ENT_QUOTES, 'UTF-8', false);
|
||||
@@ -875,19 +870,20 @@ class Enotify {
|
||||
|
||||
$x = array(
|
||||
'notify_link' => $item['llink'],
|
||||
'name' => $item[$who]['xchan_name'],
|
||||
'addr' => $item[$who]['xchan_addr'] ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url'],
|
||||
'url' => $item[$who]['xchan_url'],
|
||||
'photo' => $item[$who]['xchan_photo_s'],
|
||||
'name' => $item['author']['xchan_name'],
|
||||
'addr' => $item['author']['xchan_addr'] ? $item['author']['xchan_addr'] : $item['author']['xchan_url'],
|
||||
'url' => $item['author']['xchan_url'],
|
||||
'photo' => $item['author']['xchan_photo_s'],
|
||||
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
|
||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||
'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
|
||||
// 'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
|
||||
'b64mid' => (($item['uuid']) ? $item['uuid'] : ''),
|
||||
//'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' => $body,
|
||||
// these are for the superblock addon
|
||||
'hash' => $item[$who]['xchan_hash'],
|
||||
'hash' => $item['author']['xchan_hash'],
|
||||
'uid' => $item['uid'],
|
||||
'display' => true
|
||||
);
|
||||
@@ -907,9 +903,6 @@ class Enotify {
|
||||
if(strpos($message, $tt['xname']) === 0)
|
||||
$message = substr($message, strlen($tt['xname']) + 1);
|
||||
|
||||
$mid = basename($tt['link']);
|
||||
|
||||
$b64mid = gen_link_id($mid);
|
||||
$x = [
|
||||
'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
|
||||
'name' => $tt['xname'],
|
||||
@@ -917,7 +910,7 @@ class Enotify {
|
||||
'photo' => $tt['photo'],
|
||||
'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
|
||||
'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $b64mid : ''),
|
||||
'b64mid' => (($tt['otype'] == 'item') ? $tt['hash'] : ''),
|
||||
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : ''),
|
||||
'message' => $message
|
||||
];
|
||||
|
||||
92
Zotlabs/Lib/JcsEddsa2022.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Mmccook\JsonCanonicalizator\JsonCanonicalizatorFactory;
|
||||
use StephenHill\Base58;
|
||||
|
||||
class JcsEddsa2022 {
|
||||
|
||||
public function __construct() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sign($data, $channel): array {
|
||||
$base58 = new Base58();
|
||||
$pubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
$options = [
|
||||
'type' => 'DataIntegrityProof',
|
||||
'cryptosuite' => 'eddsa-jcs-2022',
|
||||
'created' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME),
|
||||
'verificationMethod' => channel_url($channel) . '#' . $pubkey,
|
||||
'proofPurpose' => 'assertionMethod',
|
||||
];
|
||||
|
||||
$optionsHash = $this->hash($this->signableOptions($options), true);
|
||||
$dataHash = $this->hash($this->signableData($data), true);
|
||||
|
||||
$options['proofValue'] = 'z' . $base58->encode(sodium_crypto_sign_detached($optionsHash . $dataHash,
|
||||
sodium_base642bin($channel['channel_eprvkey'], SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING)));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function verify($data, $publicKey) {
|
||||
$base58 = new Base58();
|
||||
$encodedSignature = $data['proof']['proofValue'] ?? '';
|
||||
if (!str_starts_with($encodedSignature,'z')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$encodedSignature = substr($encodedSignature, 1);
|
||||
$optionsHash = $this->hash($this->signableOptions($data['proof']), true);
|
||||
$dataHash = $this->hash($this->signableData($data),true);
|
||||
|
||||
try {
|
||||
$result = sodium_crypto_sign_verify_detached($base58->decode($encodedSignature), $optionsHash . $dataHash,
|
||||
(new Multibase())->decode($publicKey, true));
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
logger('verify exception:' . $e->getMessage());
|
||||
}
|
||||
|
||||
logger('SignatureVerify (eddsa-jcs-2022) ' . (($result) ? 'true' : 'false'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function signableData($data) {
|
||||
$signableData = [];
|
||||
if ($data) {
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, ['proof', 'signature'])) {
|
||||
$signableData[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $signableData;
|
||||
}
|
||||
|
||||
public function signableOptions($options) {
|
||||
$signableOptions = [];
|
||||
|
||||
if ($options) {
|
||||
foreach ($options as $k => $v) {
|
||||
if ($k !== 'proofValue') {
|
||||
$signableOptions[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $signableOptions;
|
||||
}
|
||||
|
||||
public function hash($obj, $binary = false) {
|
||||
return hash('sha256', $this->canonicalize($obj), $binary);
|
||||
}
|
||||
|
||||
public function canonicalize($data) {
|
||||
$canonicalization = JsonCanonicalizatorFactory::getInstance();
|
||||
return $canonicalization->canonicalize($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -325,9 +325,6 @@ class Libsync {
|
||||
|
||||
if (array_key_exists('channel', $arr) && is_array($arr['channel']) && count($arr['channel'])) {
|
||||
|
||||
$remote_channel = $arr['channel'];
|
||||
$remote_channel['channel_id'] = $channel['channel_id'];
|
||||
|
||||
if (array_key_exists('channel_pageflags', $arr['channel'])) {
|
||||
|
||||
// Several pageflags are site-specific and cannot be sync'd.
|
||||
@@ -339,6 +336,8 @@ class Libsync {
|
||||
|
||||
}
|
||||
|
||||
$columns = db_columns('channel');
|
||||
|
||||
$disallowed = [
|
||||
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
|
||||
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
|
||||
@@ -349,16 +348,21 @@ class Libsync {
|
||||
'channel_a_delegate'
|
||||
];
|
||||
|
||||
$clean = [];
|
||||
foreach ($arr['channel'] as $k => $v) {
|
||||
if (in_array($k, $disallowed))
|
||||
continue;
|
||||
$clean[$k] = $v;
|
||||
if (empty($channel['channel_epubkey']) && empty($channel['channel_eprvkey'])) {
|
||||
$eckey = sodium_crypto_sign_keypair();
|
||||
$channel['channel_epubkey'] = sodium_bin2base64(sodium_crypto_sign_publickey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
$channel['channel_eprvkey'] = sodium_bin2base64(sodium_crypto_sign_secretkey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
}
|
||||
if (count($clean)) {
|
||||
foreach ($clean as $k => $v) {
|
||||
dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id']));
|
||||
|
||||
foreach ($arr['channel'] as $k => $v) {
|
||||
if (in_array($k, $disallowed)) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
}
|
||||
$r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v)
|
||||
. "' where channel_id = " . intval($channel['channel_id']));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
@@ -759,12 +760,13 @@ class Libzot {
|
||||
|| ($r[0]['xchan_connurl'] != $arr['primary_location']['connections_url'])
|
||||
|| ($r[0]['xchan_addr'] != $arr['primary_location']['address'])
|
||||
|| ($r[0]['xchan_follow'] != $arr['primary_location']['follow_url'])
|
||||
|| (isset($arr['ed25519_key']) && $r[0]['xchan_epubkey'] != $arr['ed25519_key'])
|
||||
|| ($r[0]['xchan_connpage'] != $arr['connect_url'])
|
||||
|| ($r[0]['xchan_url'] != $arr['primary_location']['url'])
|
||||
|| $hidden_changed || $adult_changed || $deleted_changed || $pubforum_changed) {
|
||||
$rup = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s',
|
||||
xchan_connpage = '%s', xchan_hidden = %d, xchan_selfcensored = %d, xchan_deleted = %d, xchan_pubforum = %d,
|
||||
xchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s'",
|
||||
xchan_addr = '%s', xchan_url = '%s', xchan_epubkey = '%s' where xchan_hash = '%s'",
|
||||
dbesc(($arr['name']) ? escape_tags($arr['name']) : '-'),
|
||||
dbesc($arr['name_updated']),
|
||||
dbesc($arr['primary_location']['connections_url']),
|
||||
@@ -776,6 +778,7 @@ class Libzot {
|
||||
intval($arr['public_forum']),
|
||||
dbesc(escape_tags($arr['primary_location']['address'])),
|
||||
dbesc(escape_tags($arr['primary_location']['url'])),
|
||||
dbesc($arr['ed25519_key'] ?? ''),
|
||||
dbesc($xchan_hash)
|
||||
);
|
||||
|
||||
@@ -799,6 +802,7 @@ class Libzot {
|
||||
'xchan_guid' => $arr['id'],
|
||||
'xchan_guid_sig' => $arr['id_sig'],
|
||||
'xchan_pubkey' => $arr['public_key'],
|
||||
'xchan_epubkey' => $arr['xchan_epubkey'] ?? '',
|
||||
'xchan_photo_mimetype' => $arr['photo']['type'],
|
||||
'xchan_photo_l' => $arr['photo']['url'],
|
||||
'xchan_addr' => escape_tags($arr['primary_location']['address']),
|
||||
@@ -1139,7 +1143,6 @@ class Libzot {
|
||||
if ($env['encoding'] === 'activitystreams') {
|
||||
|
||||
$AS = new ActivityStreams($data);
|
||||
|
||||
if (!$AS->is_valid()) {
|
||||
logger('Activity rejected: ' . print_r($data, true));
|
||||
return;
|
||||
@@ -1154,7 +1157,6 @@ class Libzot {
|
||||
else {
|
||||
$item = [];
|
||||
}
|
||||
|
||||
logger($AS->debug(), LOGGER_DATA);
|
||||
|
||||
}
|
||||
@@ -1201,7 +1203,6 @@ class Libzot {
|
||||
// @fixme;
|
||||
|
||||
$deliveries = self::public_recips($env, $AS);
|
||||
|
||||
}
|
||||
|
||||
$deliveries = array_unique($deliveries);
|
||||
@@ -1222,10 +1223,6 @@ class Libzot {
|
||||
|
||||
$author_url = $AS->actor['id'];
|
||||
|
||||
if ($AS->type === 'Announce') {
|
||||
$author_url = Activity::get_attributed_to_actor_url($AS);
|
||||
}
|
||||
|
||||
$r = Activity::get_actor_hublocs($author_url);
|
||||
|
||||
if (!$r) {
|
||||
@@ -1234,17 +1231,16 @@ class Libzot {
|
||||
if ($z) {
|
||||
$r = Activity::get_actor_hublocs($author_url);
|
||||
}
|
||||
|
||||
if (!$r) {
|
||||
logger('Could not fetch author');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
$r = self::zot_record_preferred($r);
|
||||
$item['author_xchan'] = $r['hubloc_hash'];
|
||||
}
|
||||
$r = self::zot_record_preferred($r);
|
||||
|
||||
if (! $item['author_xchan']) {
|
||||
logger('No author!');
|
||||
return;
|
||||
}
|
||||
$item['author_xchan'] = $r['hubloc_hash'];
|
||||
|
||||
$item['owner_xchan'] = $env['sender'];
|
||||
|
||||
@@ -1287,7 +1283,7 @@ class Libzot {
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($AS->meta['hubloc']) && $AS->meta['hubloc']) {
|
||||
if (!empty($AS->meta['hubloc']) || $AS->sigok) {
|
||||
$item['item_verified'] = true;
|
||||
}
|
||||
|
||||
@@ -1305,6 +1301,8 @@ class Libzot {
|
||||
$relay = (($env['type'] === 'response') ? true : false);
|
||||
|
||||
$result = self::process_delivery($env['sender'], $AS, $item, $deliveries, $relay, false, $message_request);
|
||||
|
||||
Activity::init_background_fetch($env['sender']);
|
||||
}
|
||||
elseif ($env['type'] === 'sync') {
|
||||
// $item = get_channelsync_elements($data);
|
||||
@@ -1325,6 +1323,7 @@ class Libzot {
|
||||
if ($result) {
|
||||
$return = array_merge($return, $result);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -1367,11 +1366,13 @@ class Libzot {
|
||||
|
||||
static function find_parent_owner_hashes($env, $act) {
|
||||
$r = [];
|
||||
$thread_parent = self::find_parent($env, $act);
|
||||
if ($thread_parent) {
|
||||
$uids = q("SELECT uid FROM item WHERE thr_parent = '%s' OR parent_mid = '%s'",
|
||||
dbesc($thread_parent),
|
||||
dbesc($thread_parent)
|
||||
$parent = self::find_parent($env, $act);
|
||||
|
||||
if ($parent) {
|
||||
$uids = q("SELECT uid FROM item WHERE thr_parent = '%s' OR parent_mid = '%s' OR mid = '%s'",
|
||||
dbesc($parent),
|
||||
dbesc($parent),
|
||||
dbesc($parent)
|
||||
);
|
||||
|
||||
if ($uids) {
|
||||
@@ -1531,7 +1532,7 @@ class Libzot {
|
||||
$local_public = $public;
|
||||
$item_result = null;
|
||||
|
||||
$DR = new DReport(z_root(), $sender, $d, $arr['mid']);
|
||||
$DR = new DReport(z_root(), $sender, $d, $arr['mid'], $arr['uuid']);
|
||||
|
||||
$channel = channelx_by_hash($d);
|
||||
|
||||
@@ -1582,6 +1583,39 @@ class Libzot {
|
||||
continue;
|
||||
}
|
||||
|
||||
$arr['item_wall'] = 0;
|
||||
|
||||
// This is our own post, possibly coming from a channel clone
|
||||
if ($arr['owner_xchan'] === $d) {
|
||||
$arr['item_wall'] = 1;
|
||||
}
|
||||
|
||||
if (isset($arr['item_deleted']) && $arr['item_deleted']) {
|
||||
|
||||
// remove_community_tag is a no-op if this isn't a community tag activity
|
||||
// self::remove_community_tag($sender, $arr, $channel['channel_id']);
|
||||
|
||||
// set these just in case we need to store a fresh copy of the deleted post.
|
||||
// This could happen if the delete got here before the original post did.
|
||||
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
|
||||
$item_id = self::delete_imported_item($sender, $act, $arr, $channel['channel_id'], $relay);
|
||||
$DR->update(($item_id) ? 'deleted' : 'delete_failed');
|
||||
$result[] = $DR->get();
|
||||
|
||||
if ($relay && $item_id) {
|
||||
logger('process_delivery: invoking relay');
|
||||
Master::Summon(['Notifier', 'relay', intval($item_id), 'delete']);
|
||||
$DR->update('relayed');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// allow public postings to the sys channel regardless of permissions, but not
|
||||
// for comments travelling upstream. Wait and catch them on the way down.
|
||||
// They may have been blocked by the owner.
|
||||
@@ -1608,116 +1642,23 @@ class Libzot {
|
||||
}
|
||||
|
||||
$tag_delivery = tgroup_check($channel['channel_id'], $arr);
|
||||
$perm = 'send_stream';
|
||||
if (($arr['mid'] !== $arr['parent_mid']) && ($relay))
|
||||
$perm = 'post_comments';
|
||||
|
||||
// This is our own post, possibly coming from a channel clone
|
||||
|
||||
if ($arr['owner_xchan'] == $d) {
|
||||
$arr['item_wall'] = 1;
|
||||
}
|
||||
else {
|
||||
$arr['item_wall'] = 0;
|
||||
}
|
||||
|
||||
$friendofriend = false;
|
||||
|
||||
if ((!$tag_delivery) && (!$local_public)) {
|
||||
$allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
|
||||
|
||||
$permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system', 'permit_all_mentions') && i_am_mentioned($channel, $arr));
|
||||
|
||||
if (!$allowed) {
|
||||
if ($perm === 'post_comments') {
|
||||
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if ($parent) {
|
||||
$allowed = can_comment_on_post($sender, $parent[0]);
|
||||
if (!$allowed && $permit_mentions) {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
if (!$allowed) {
|
||||
if (PConfig::Get($channel['channel_id'], 'system', 'moderate_unsolicited_comments') && $arr['obj_type'] !== 'Answer') {
|
||||
$arr['item_blocked'] = ITEM_MODERATED;
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($permit_mentions) {
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request) {
|
||||
// Conversation fetches (e.g. $request == true) take place for
|
||||
// a) new comments on expired posts
|
||||
// b) hyperdrive (friend-of-friend) conversations
|
||||
// c) Repeats of posts by others
|
||||
|
||||
|
||||
// over-ride normal connection permissions for hyperdrive (friend-of-friend) conversations
|
||||
// (if hyperdrive is enabled) and repeated posts by a friend.
|
||||
// If $allowed is already true, this is probably the conversation of a direct friend or a
|
||||
// conversation fetch for a new comment on an expired post
|
||||
// Comments of all these activities are allowed and will only be rejected (later) if the parent
|
||||
// doesn't exist.
|
||||
|
||||
if ($perm === 'send_stream') {
|
||||
if ($force || get_pconfig($channel['channel_id'], 'system', 'hyperdrive', false)) {
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
$friendofriend = true;
|
||||
}
|
||||
|
||||
if (intval($arr['item_private']) === 2) {
|
||||
if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
|
||||
$allowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$allowed) {
|
||||
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
|
||||
$DR->update('permission denied');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// logger('item: ' . print_r($arr,true), LOGGER_DATA);
|
||||
$perm = 'send_stream';
|
||||
|
||||
if ($arr['mid'] !== $arr['parent_mid']) {
|
||||
|
||||
logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"');
|
||||
if ($relay)
|
||||
$perm = 'post_comments';
|
||||
|
||||
// check source route.
|
||||
// We are only going to accept comments from this sender if the comment has the same route as the top-level-post,
|
||||
// this is so that permissions mismatches between senders apply to the entire conversation
|
||||
// As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
|
||||
// processing it is pointless.
|
||||
|
||||
$r = q("select route, id, parent_mid, mid, owner_xchan, item_private, obj_type from item where mid = '%s' and uid = %d limit 1",
|
||||
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($arr['parent_mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
if (!$parent) {
|
||||
$DR->update('comment parent not found');
|
||||
$result[] = $DR->get();
|
||||
|
||||
if ($relay || $request || $local_public) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We don't seem to have a copy of this conversation or at least the parent
|
||||
// - so request a copy of the entire conversation to date.
|
||||
// Don't do this if it's a relay post as we're the ones who are supposed to
|
||||
@@ -1729,24 +1670,40 @@ class Libzot {
|
||||
// the top level post is unlikely to be imported and
|
||||
// this is just an exercise in futility.
|
||||
|
||||
if (perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
|
||||
Master::Summon(['Zotconvo', $channel['channel_id'], $arr['parent_mid']]);
|
||||
if ($relay || $request || (!$local_public && !perm_is_allowed($channel['channel_id'], $sender, 'send_stream'))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($arr['verb'] === 'Announce') {
|
||||
App::$cache['as_fetch_objects'][$arr['mid']]['channels'][] = $channel['channel_id'];
|
||||
App::$cache['as_fetch_objects'][$arr['mid']]['force'] = true;
|
||||
}
|
||||
else {
|
||||
App::$cache['zot_fetch_objects'][$arr['mid']]['channels'][] = $channel['channel_id'];
|
||||
App::$cache['zot_fetch_objects'][$arr['mid']]['force'] = false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($r[0]['obj_type'] === 'Question') {
|
||||
logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"');
|
||||
|
||||
// check source route.
|
||||
// We are only going to accept comments from this sender if the comment has the same route as the top-level-post,
|
||||
// this is so that permissions mismatches between senders apply to the entire conversation
|
||||
// As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
|
||||
// processing it is pointless.
|
||||
|
||||
if ($parent[0]['obj_type'] === 'Question') {
|
||||
// route checking doesn't work correctly here because we've changed the privacy
|
||||
$r[0]['route'] = EMPTY_STR;
|
||||
$parent[0]['route'] = EMPTY_STR;
|
||||
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
|
||||
if ($arr['obj_type'] === ACTIVITY_OBJ_COMMENT && $arr['title'] && (!$arr['body'])) {
|
||||
if (in_array($arr['obj_type'], ['Note', ACTIVITY_OBJ_COMMENT]) && $arr['title'] && (!$arr['body'])) {
|
||||
$arr['obj_type'] = 'Answer';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
|
||||
if ($relay || (intval($parent[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
|
||||
// reset the route in case it travelled a great distance upstream
|
||||
// use our parent's route so when we go back downstream we'll match
|
||||
// with whatever route our parent has.
|
||||
@@ -1754,8 +1711,8 @@ class Libzot {
|
||||
// but we are now getting comments via listener delivery
|
||||
// and if there is no privacy on this or the parent, we don't care about the route,
|
||||
// so just set the owner and route accordingly.
|
||||
$arr['route'] = $r[0]['route'];
|
||||
$arr['owner_xchan'] = $r[0]['owner_xchan'];
|
||||
$arr['route'] = $parent[0]['route'];
|
||||
$arr['owner_xchan'] = $parent[0]['owner_xchan'];
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1765,7 +1722,7 @@ class Libzot {
|
||||
// only compare the last hop since it could have arrived at the last location any number of ways.
|
||||
// Always accept empty routes and firehose items (route contains 'undefined') .
|
||||
|
||||
$existing_route = explode(',', $r[0]['route']);
|
||||
$existing_route = explode(',', $parent[0]['route']);
|
||||
$routes = count($existing_route);
|
||||
if ($routes) {
|
||||
$last_hop = array_pop($existing_route);
|
||||
@@ -1782,8 +1739,8 @@ class Libzot {
|
||||
$current_route = ((isset($arr['route']) && $arr['route']) ? $arr['route'] . ',' : '') . $sender;
|
||||
|
||||
if ($last_hop && $last_hop != $sender) {
|
||||
logger('comment route mismatch: parent route = ' . $r[0]['route'] . ' expected = ' . $current_route, LOGGER_DEBUG);
|
||||
logger('comment route mismatch: parent msg = ' . $r[0]['id'], LOGGER_DEBUG);
|
||||
logger('comment route mismatch: parent route = ' . $parent[0]['route'] . ' expected = ' . $current_route, LOGGER_DEBUG);
|
||||
logger('comment route mismatch: parent msg = ' . $parent[0]['id'], LOGGER_DEBUG);
|
||||
$DR->update('comment route mismatch');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
@@ -1796,6 +1753,70 @@ class Libzot {
|
||||
}
|
||||
}
|
||||
|
||||
if (!$tag_delivery && !$local_public) {
|
||||
$allowed = perm_is_allowed($channel['channel_id'], $sender, $perm);
|
||||
|
||||
$permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system', 'permit_all_mentions') && i_am_mentioned($channel, $arr));
|
||||
|
||||
if (!$allowed) {
|
||||
if ($parent && $perm === 'send_stream') {
|
||||
// if we own the parent we will accept its comments
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
elseif ($parent && $perm === 'post_comments') {
|
||||
$allowed = can_comment_on_post($sender, $parent[0]);
|
||||
|
||||
if (!$allowed && $permit_mentions) {
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
if (!$allowed) {
|
||||
if (PConfig::Get($channel['channel_id'], 'system', 'moderate_unsolicited_comments') && $arr['obj_type'] !== 'Answer') {
|
||||
$arr['item_blocked'] = ITEM_MODERATED;
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elseif ($permit_mentions) {
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request) {
|
||||
// Conversation fetches (e.g. $request == true) take place for
|
||||
// a) new comments on expired posts
|
||||
// b) manual import of posts via search (in this case force will be true)
|
||||
// c) import of conversations from friends of friends (they can currently arriuve from streams if a channel is configured to do so)
|
||||
|
||||
// Comments of all these activities are allowed and will only be rejected (later) if the parent
|
||||
// doesn't exist.
|
||||
|
||||
if ($perm === 'send_stream') {
|
||||
if ($force) {
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (intval($arr['item_private']) === 2) {
|
||||
if (!perm_is_allowed($channel['channel_id'], $sender, 'post_mail')) {
|
||||
$allowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$allowed) {
|
||||
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
|
||||
$DR->update('permission denied');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 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' )",
|
||||
@@ -1804,34 +1825,8 @@ class Libzot {
|
||||
dbesc($arr['author_xchan'])
|
||||
);
|
||||
|
||||
if (isset($arr['item_deleted']) && $arr['item_deleted']) {
|
||||
|
||||
// remove_community_tag is a no-op if this isn't a community tag activity
|
||||
self::remove_community_tag($sender, $arr, $channel['channel_id']);
|
||||
|
||||
// set these just in case we need to store a fresh copy of the deleted post.
|
||||
// This could happen if the delete got here before the original post did.
|
||||
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
|
||||
$item_id = self::delete_imported_item($sender, $act, $arr, $channel['channel_id'], $relay);
|
||||
$DR->update(($item_id) ? 'deleted' : 'delete_failed');
|
||||
$result[] = $DR->get();
|
||||
|
||||
if ($relay && $item_id) {
|
||||
logger('process_delivery: invoking relay');
|
||||
Master::Summon(['Notifier', 'relay', intval($item_id)]);
|
||||
$DR->update('relayed');
|
||||
$result[] = $DR->get();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// reactions such as like and dislike could have an mid with /activity/ in it.
|
||||
// Check for both forms in order to prevent duplicates.
|
||||
|
||||
$r = q("select * from item where mid in ('%s','%s') and uid = %d limit 1",
|
||||
dbesc($arr['mid']),
|
||||
dbesc(str_replace(z_root() . '/activity/', z_root() . '/item/', $arr['mid'])),
|
||||
@@ -1839,14 +1834,6 @@ class Libzot {
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
// We already have this post.
|
||||
// Dismiss its announce
|
||||
if ($act->type === 'Announce') {
|
||||
$DR->update('update ignored');
|
||||
$result[] = $DR->get();
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_id = $r[0]['id'];
|
||||
|
||||
if (intval($r[0]['item_deleted'])) {
|
||||
@@ -1903,12 +1890,12 @@ class Libzot {
|
||||
|
||||
$maxlen = get_max_import_size();
|
||||
|
||||
if ($maxlen && mb_strlen($arr['body']) > $maxlen) {
|
||||
if ($maxlen && isset($arr['body']) && mb_strlen($arr['body']) > $maxlen) {
|
||||
$arr['body'] = mb_substr($arr['body'], 0, $maxlen, 'UTF-8');
|
||||
logger('message length exceeds max_import_size: truncated');
|
||||
}
|
||||
|
||||
if ($maxlen && mb_strlen($arr['summary']) > $maxlen) {
|
||||
if ($maxlen && isset($arr['summary']) && mb_strlen($arr['summary']) > $maxlen) {
|
||||
$arr['summary'] = mb_substr($arr['summary'], 0, $maxlen, 'UTF-8');
|
||||
logger('message summary length exceeds max_import_size: truncated');
|
||||
}
|
||||
@@ -1916,7 +1903,6 @@ class Libzot {
|
||||
if (post_is_importable($arr['uid'], $arr, $abook)) {
|
||||
$item_result = item_store($arr);
|
||||
if ($item_result['success']) {
|
||||
|
||||
$item_id = $item_result['item_id'];
|
||||
|
||||
if ($item_source && in_array($item_result['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
|
||||
@@ -1958,6 +1944,7 @@ class Libzot {
|
||||
// preserve conversations with which you are involved from expiration
|
||||
|
||||
$stored = ((isset($item_result['item'])) ? $item_result['item'] : false);
|
||||
|
||||
if ((is_array($stored)) && ($stored['id'] != $stored['parent'])
|
||||
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
|
||||
retain_item($stored['item']['parent']);
|
||||
@@ -2006,11 +1993,14 @@ class Libzot {
|
||||
|
||||
$ret = [];
|
||||
|
||||
|
||||
$signer = q("select hubloc_hash, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' order by hubloc_id desc limit 1",
|
||||
dbesc($a['signature']['signer'])
|
||||
);
|
||||
|
||||
$signer_hash = $signer[0]['hubloc_hash'] ?? $a['signature']['signer'];
|
||||
$conv_owner = $signer_hash;
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach ($items as $activity) {
|
||||
|
||||
@@ -2024,14 +2014,14 @@ class Libzot {
|
||||
}
|
||||
|
||||
if (!$AS->is_valid()) {
|
||||
logger('FOF Activity rejected: ' . print_r($activity, true));
|
||||
logger('Fetched activity rejected: ' . print_r($activity, true));
|
||||
continue;
|
||||
}
|
||||
|
||||
// logger($AS->debug());
|
||||
|
||||
if(empty($AS->actor['id'])) {
|
||||
logger('No actor id: ' . print_r($AS, true));
|
||||
logger('Fetched activity no actor id: ' . print_r($AS, true));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2044,7 +2034,7 @@ class Libzot {
|
||||
$r = self::zot_record_preferred($r);
|
||||
}
|
||||
if (!$r) {
|
||||
logger('FOF Activity: no actor');
|
||||
logger('Fetched activity: no actor');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2059,7 +2049,7 @@ class Libzot {
|
||||
$ro = self::zot_record_preferred($ro);
|
||||
}
|
||||
if (!$ro) {
|
||||
logger('FOF Activity: no obj actor');
|
||||
logger('Fetched activity: no obj actor');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2074,14 +2064,18 @@ class Libzot {
|
||||
|
||||
$arr['author_xchan'] = $r['hubloc_hash'];
|
||||
|
||||
if ($signer) {
|
||||
$arr['owner_xchan'] = $signer[0]['hubloc_hash'];
|
||||
}
|
||||
else {
|
||||
$arr['owner_xchan'] = $a['signature']['signer'];
|
||||
if ($i === 0) {
|
||||
// Set the author of the toplevel post as conv_owner
|
||||
$conv_owner = $r['hubloc_hash'];
|
||||
}
|
||||
|
||||
if (isset($AS->meta['hubloc']) || $arr['author_xchan'] === $arr['owner_xchan']) {
|
||||
$arr['owner_xchan'] = $conv_owner;
|
||||
$arr['source_xchan'] = $signer_hash;
|
||||
|
||||
// WARNING: the presence of both source_xchan and non-zero item_uplink here will cause a delivery loop
|
||||
$arr['item_uplink'] = 0;
|
||||
|
||||
if (!empty($AS->meta['hubloc']) || $arr['author_xchan'] === $arr['owner_xchan'] || $AS->sigok) {
|
||||
$arr['item_verified'] = true;
|
||||
}
|
||||
|
||||
@@ -2093,13 +2087,15 @@ class Libzot {
|
||||
}
|
||||
}
|
||||
|
||||
logger('FOF Activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
|
||||
logger('Fetched activity received: ' . print_r($arr, true), LOGGER_DATA, LOG_DEBUG);
|
||||
logger('Fetched activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
|
||||
|
||||
$result = self::process_delivery($arr['owner_xchan'], $AS, $arr, [$channel['channel_hash']], false, false, true, $force);
|
||||
if ($result) {
|
||||
$ret = array_merge($ret, $result);
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@@ -2321,12 +2317,20 @@ class Libzot {
|
||||
// this information from the metadata should have no other discernible impact.
|
||||
|
||||
if (($stored['id'] != $stored['parent']) && intval($stored['item_origin'])) {
|
||||
q("update item set item_origin = 0 where id = %d and uid = %d",
|
||||
intval($stored['id']),
|
||||
intval($stored['uid'])
|
||||
q("update item set item_origin = 0 where id = %d",
|
||||
intval($stored['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($stored['id'] !== $stored['parent']) {
|
||||
q(
|
||||
"update item set commented = '%s', changed = '%s' where id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
intval($stored['parent'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels
|
||||
@@ -2815,6 +2819,7 @@ class Libzot {
|
||||
];
|
||||
|
||||
$ret['public_key'] = $e['channel_pubkey'];
|
||||
$ret['ed25519_key'] = $e['xchan_epubkey'];
|
||||
$ret['signing_algorithm'] = 'rsa-sha256';
|
||||
$ret['username'] = $e['channel_address'];
|
||||
$ret['name'] = $e['channel_name'];
|
||||
@@ -2980,7 +2985,7 @@ class Libzot {
|
||||
$ret['site']['admin'] = get_config('system', 'admin_email');
|
||||
|
||||
$visible_plugins = [];
|
||||
if (is_array(\App::$plugins) && count(\App::$plugins)) {
|
||||
if (is_array(App::$plugins) && count(App::$plugins)) {
|
||||
$r = q("select * from addon where hidden = 0");
|
||||
if ($r)
|
||||
foreach ($r as $rr)
|
||||
|
||||
34
Zotlabs/Lib/Multibase.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use StephenHill\Base58;
|
||||
|
||||
class Multibase {
|
||||
|
||||
protected $key = null;
|
||||
|
||||
public function __construct() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function publicKey($key) {
|
||||
$base58 = new Base58();
|
||||
$raw = hex2bin('ed01') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
return 'z' . $base58->encode($raw);
|
||||
}
|
||||
|
||||
public function secretKey($key) {
|
||||
$base58 = new Base58();
|
||||
$raw = hex2bin('8026') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
return 'z' . $base58->encode($raw);
|
||||
}
|
||||
|
||||
public function decode($key, $binary = false) {
|
||||
$base58 = new Base58();
|
||||
$key = substr($key,1);
|
||||
$raw = $base58->decode($key);
|
||||
$binaryKey = substr($raw, 2);
|
||||
return $binary ? $binaryKey : sodium_bin2base64($binaryKey, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -112,7 +112,7 @@ class Share {
|
||||
if(! $this->item)
|
||||
return $bb;
|
||||
|
||||
$is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
|
||||
$is_photo = ((in_array($this->item['obj_type'], ['Image', ACTIVITY_OBJ_PHOTO])) ? true : false);
|
||||
if($is_photo) {
|
||||
$object = json_decode($this->item['obj'],true);
|
||||
$photo_bb = $object['body'];
|
||||
|
||||
24
Zotlabs/Lib/Text.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class Text {
|
||||
|
||||
/**
|
||||
* use this on "body" or "content" input where angle chars shouldn't be removed,
|
||||
* and allow them to be safely displayed.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
||||
public static function escape_tags(string $string): string {
|
||||
if (!$string) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
return htmlspecialchars($string, ENT_COMPAT, 'UTF-8', false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class ThreadItem {
|
||||
private $comment_box_template = 'comment_item.tpl';
|
||||
private $commentable = false;
|
||||
// list of supported reaction emojis - a site can over-ride this via config system.reactions
|
||||
private $reactions = ['1f60a','1f44f','1f37e','1f48b','1f61e','2665','1f606','1f62e','1f634','1f61c','1f607','1f608'];
|
||||
private $reactions = ['slightly_smiling_face','clapping_hands','bottle_with_popping_cork','kiss_mark','disappointed_face','red_heart','grinning_face','astonished_face','sleeping_face','winking_face_with_tongue','smiling_face_with_halo','smiling_face_with_horns'];
|
||||
private $toplevel = false;
|
||||
private $children = array();
|
||||
private $parent = null;
|
||||
@@ -34,6 +34,7 @@ class ThreadItem {
|
||||
private $channel = null;
|
||||
private $display_mode = 'normal';
|
||||
private $reload = '';
|
||||
private $mid_uuid_map = [];
|
||||
|
||||
|
||||
public function __construct($data) {
|
||||
@@ -46,6 +47,7 @@ class ThreadItem {
|
||||
|
||||
// Prepare the children
|
||||
if(isset($data['children'])) {
|
||||
|
||||
foreach($data['children'] as $item) {
|
||||
|
||||
/*
|
||||
@@ -56,7 +58,6 @@ class ThreadItem {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$child = new ThreadItem($item);
|
||||
$this->add_child($child);
|
||||
}
|
||||
@@ -65,6 +66,8 @@ class ThreadItem {
|
||||
unset($this->data['children']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// allow a site to configure the order and content of the reaction emoji list
|
||||
if($this->toplevel) {
|
||||
$x = get_config('system','reactions');
|
||||
@@ -82,7 +85,7 @@ class ThreadItem {
|
||||
* _ false on failure
|
||||
*/
|
||||
|
||||
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
|
||||
public function get_template_data($conv_responses, $mid_uuid_map, $thread_level=1, $conv_flags = []) {
|
||||
|
||||
$result = [];
|
||||
$item = $this->get_data();
|
||||
@@ -121,12 +124,14 @@ class ThreadItem {
|
||||
$locktype = 0;
|
||||
}
|
||||
|
||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
|
||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0)) ? true : false);
|
||||
|
||||
// allow an exemption for sharing stuff from your private feeds
|
||||
if($item['author']['xchan_network'] === 'rss')
|
||||
$shareable = true;
|
||||
|
||||
$repeatable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0) && (in_array($item['author']['xchan_network'], ['zot6', 'activitypub']))) ? true : false);
|
||||
|
||||
// @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.
|
||||
@@ -194,9 +199,14 @@ class ThreadItem {
|
||||
$attend = null;
|
||||
|
||||
// process action responses - e.g. like/dislike/attend/agree/whatever
|
||||
$response_verbs = array('like');
|
||||
if(feature_enabled($conv->get_profile_owner(),'dislike'))
|
||||
$response_verbs[] = 'like';
|
||||
|
||||
if(feature_enabled($conv->get_profile_owner(),'dislike')) {
|
||||
$response_verbs[] = 'dislike';
|
||||
}
|
||||
|
||||
$response_verbs[] = 'announce';
|
||||
|
||||
if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
|
||||
$response_verbs[] = 'attendyes';
|
||||
$response_verbs[] = 'attendno';
|
||||
@@ -222,6 +232,8 @@ class ThreadItem {
|
||||
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
$like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
|
||||
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
|
||||
if (($like_list) && (count($like_list) > MAX_LIKERS)) {
|
||||
@@ -232,6 +244,16 @@ class ThreadItem {
|
||||
}
|
||||
$like_button_label = tt('Like','Likes',$like_count,'noun');
|
||||
|
||||
$repeat_count = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid']] : '');
|
||||
$repeat_list = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid'] . '-l'] : '');
|
||||
if (($repeat_list) && (count($repeat_list) > MAX_LIKERS)) {
|
||||
$repeat_list_part = array_slice($repeat_list, 0, MAX_LIKERS);
|
||||
array_push($repeat_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#repeatModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
|
||||
} else {
|
||||
$repeat_list_part = '';
|
||||
}
|
||||
$repeat_button_label = tt('Repeat','Repeats',$repeat_count,'noun');
|
||||
|
||||
$showdislike = '';
|
||||
if (feature_enabled($conv->get_profile_owner(),'dislike')) {
|
||||
$dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
|
||||
@@ -248,6 +270,7 @@ class ThreadItem {
|
||||
}
|
||||
|
||||
$showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
|
||||
*/
|
||||
|
||||
/*
|
||||
* We should avoid doing this all the time, but it depends on the conversation mode
|
||||
@@ -315,13 +338,11 @@ class ThreadItem {
|
||||
$share = [];
|
||||
$embed = [];
|
||||
if ($shareable) {
|
||||
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
|
||||
// Will allow it only for uri resolvable sources.
|
||||
if(strpos($item['mid'],'http') === 0) {
|
||||
//Not yet ready for primetime
|
||||
//$share = array( t('Repeat This'), t('repeat'));
|
||||
}
|
||||
$embed = [t('Share This'), t('share')];
|
||||
$embed = [t('Share'), t('share')];
|
||||
}
|
||||
|
||||
if ($repeatable) {
|
||||
$share = [t('Repeat'), t('repeat')];
|
||||
}
|
||||
|
||||
$dreport = '';
|
||||
@@ -333,7 +354,7 @@ class ThreadItem {
|
||||
$dreport_link = '';
|
||||
if((intval($item['item_type']) == ITEM_TYPE_POST) && (! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
|
||||
$dreport = t('Delivery Report');
|
||||
$dreport_link = gen_link_id($item['mid']);
|
||||
$dreport_link = '?mid=' . $item['mid'];
|
||||
}
|
||||
|
||||
$is_new = false;
|
||||
@@ -352,8 +373,8 @@ class ThreadItem {
|
||||
if($conv->get_mode() === 'channel')
|
||||
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
|
||||
|
||||
$comment_count_txt = sprintf(tt('%d Comment', '%d Comments', $total_children), $total_children);
|
||||
$list_unseen_txt = (($unseen_comments) ? sprintf(t('%d unseen'), $unseen_comments) : '');
|
||||
$comment_count_txt = ['label' => sprintf(tt('%d comment', '%d comments', $total_children), $total_children), 'count' => $total_children];
|
||||
$list_unseen_txt = $unseen_comments ? ['label' => sprintf(t('%d unseen'), $unseen_comments), 'count' => $unseen_comments] : [];
|
||||
|
||||
$children = $this->get_children();
|
||||
|
||||
@@ -363,8 +384,8 @@ class ThreadItem {
|
||||
call_hooks('dropdown_extras',$dropdown_extras_arr);
|
||||
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
|
||||
|
||||
$midb64 = gen_link_id($item['mid']);
|
||||
$mids = [ $midb64 ];
|
||||
$midb64 = $item['uuid'];
|
||||
$mids = [ $item['uuid'] ];
|
||||
$response_mids = [];
|
||||
foreach($response_verbs as $v) {
|
||||
if(isset($conv_responses[$v]['mids'][$item['mid']])) {
|
||||
@@ -480,35 +501,44 @@ class ThreadItem {
|
||||
'comment_count' => $total_children,
|
||||
'comment_count_txt' => $comment_count_txt,
|
||||
'list_unseen_txt' => $list_unseen_txt,
|
||||
'markseen' => t('Mark all seen'),
|
||||
'markseen' => t('Mark all comments seen'),
|
||||
'responses' => $responses,
|
||||
'my_responses' => $my_responses,
|
||||
/*
|
||||
'like_count' => $like_count,
|
||||
'like_list' => $like_list,
|
||||
'like_list_part' => $like_list_part,
|
||||
'like_button_label' => $like_button_label,
|
||||
'like_modal_title' => t('Likes','noun'),
|
||||
|
||||
'repeat_count' => $repeat_count,
|
||||
'repeat_list' => $repeat_list,
|
||||
'repeat_list_part' => $repeat_list_part,
|
||||
'repeat_button_label' => $repeat_button_label,
|
||||
'repeat_modal_title' => t('Repeats','noun'),
|
||||
|
||||
|
||||
'dislike_modal_title' => t('Dislikes','noun'),
|
||||
'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
|
||||
'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
|
||||
'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
|
||||
'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
|
||||
*/
|
||||
'modal_dismiss' => t('Close'),
|
||||
'showlike' => $showlike,
|
||||
'showdislike' => $showdislike,
|
||||
// 'showlike' => $showlike,
|
||||
// 'showdislike' => $showdislike,
|
||||
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box()),
|
||||
'previewing' => ($conv->is_preview() ? true : false ),
|
||||
'preview_lbl' => t('This is an unsaved preview'),
|
||||
'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_uuid' => (($item['parent_mid'] != $item['thr_parent']) ? $mid_uuid_map[$item['thr_parent']] : ''),
|
||||
'contact_id' => (($contact) ? $contact['abook_id'] : ''),
|
||||
'moderate' => ($item['item_blocked'] == ITEM_MODERATED),
|
||||
'moderate_approve' => t('Approve'),
|
||||
'moderate_delete' => t('Delete'),
|
||||
'rtl' => in_array($item['lang'], rtl_languages())
|
||||
|
||||
'rtl' => in_array($item['lang'], rtl_languages()),
|
||||
);
|
||||
|
||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||
@@ -531,12 +561,12 @@ class ThreadItem {
|
||||
|
||||
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
|
||||
foreach($children as $child) {
|
||||
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1,$conv_flags);
|
||||
$result['children'][] = $child->get_template_data($conv_responses, $mid_uuid_map, $thread_level + 1,$conv_flags);
|
||||
}
|
||||
// Collapse
|
||||
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
|
||||
$result['children'][0]['comment_firstcollapsed'] = true;
|
||||
$result['children'][0]['num_comments'] = $comment_count_txt;
|
||||
$result['children'][0]['num_comments'] = $comment_count_txt['label'];
|
||||
$result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>');
|
||||
if($thread_level > 1) {
|
||||
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
|
||||
@@ -613,7 +643,7 @@ class ThreadItem {
|
||||
* Only add what will be displayed
|
||||
*/
|
||||
|
||||
if(activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE)) {
|
||||
if(activity_match($item->get_data_value('verb'), ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -878,6 +908,12 @@ class ThreadItem {
|
||||
$this->owner_name = $this->data['owner']['xchan_name'];
|
||||
$this->wall_to_wall = true;
|
||||
}
|
||||
elseif($this->is_toplevel() && $this->get_data_value('verb') === 'Announce' && isset($this->data['source'])) {
|
||||
$this->owner_url = chanlink_hash($this->data['source']['xchan_hash']);
|
||||
$this->owner_photo = $this->data['source']['xchan_photo_s'];
|
||||
$this->owner_name = $this->data['source']['xchan_name'];
|
||||
$this->wall_to_wall = true;
|
||||
}
|
||||
}
|
||||
|
||||
private function is_wall_to_wall() {
|
||||
|
||||
@@ -171,7 +171,7 @@ class ThreadStream {
|
||||
*/
|
||||
|
||||
|
||||
if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
|
||||
if($item->get_data_value('id') != $item->get_data_value('parent') && activity_match($item->get_data_value('verb'), ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ class ThreadStream {
|
||||
* _ The data requested on success
|
||||
* _ false on failure
|
||||
*/
|
||||
public function get_template_data($conv_responses) {
|
||||
public function get_template_data($conv_responses, $mid_uuid_map) {
|
||||
$result = array();
|
||||
|
||||
foreach($this->threads as $item) {
|
||||
@@ -220,7 +220,7 @@ class ThreadStream {
|
||||
$item_data = $this->prepared_item;
|
||||
}
|
||||
else {
|
||||
$item_data = $item->get_template_data($conv_responses);
|
||||
$item_data = $item->get_template_data($conv_responses, $mid_uuid_map);
|
||||
}
|
||||
if(!$item_data) {
|
||||
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);
|
||||
|
||||
@@ -7,7 +7,6 @@ use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Activity as ZlibActivity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
@@ -26,7 +25,7 @@ class Activity extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -155,22 +154,7 @@ class Activity extends Controller {
|
||||
if(! $i)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $i);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/x-zot+json' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
as_return_and_die($i, $chan);
|
||||
|
||||
}
|
||||
|
||||
@@ -202,7 +186,7 @@ class Activity extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -260,25 +244,7 @@ class Activity extends Controller {
|
||||
|
||||
$channel = channelx_by_n($items[0]['uid']);
|
||||
|
||||
$x = array_merge( ['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], ZlibActivity::encode_activity($items[0],true));
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$channel);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
as_return_and_die(ZlibActivity::encode_activity($items[0]), $channel);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
|
||||
@@ -68,7 +68,7 @@ class Site {
|
||||
$login_on_homepage = ((x($_POST,'login_on_homepage')) ? True : False);
|
||||
$enable_context_help = ((x($_POST,'enable_context_help')) ? True : False);
|
||||
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
|
||||
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
|
||||
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 30);
|
||||
$active_expire_days = ((array_key_exists('active_expire_days',$_POST)) ? intval($_POST['active_expire_days']) : 7);
|
||||
|
||||
$reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname());
|
||||
@@ -227,20 +227,6 @@ class Site {
|
||||
*/
|
||||
function get() {
|
||||
|
||||
/* Installed langs */
|
||||
$lang_choices = array();
|
||||
$langs = glob('view/*/hstrings.php');
|
||||
|
||||
if(is_array($langs) && count($langs)) {
|
||||
if(! in_array('view/en/hstrings.php',$langs))
|
||||
$langs[] = 'view/en/';
|
||||
asort($langs);
|
||||
foreach($langs as $l) {
|
||||
$t = explode("/",$l);
|
||||
$lang_choices[$t[1]] = $t[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* Installed themes */
|
||||
$theme_choices_mobile["---"] = t("Default");
|
||||
$theme_choices = array();
|
||||
@@ -425,7 +411,6 @@ class Site {
|
||||
'$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')),
|
||||
'$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
|
||||
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
|
||||
//'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
|
||||
'$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
|
||||
// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
|
||||
// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
|
||||
@@ -536,7 +521,7 @@ class Site {
|
||||
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
||||
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
||||
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
|
||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
|
||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days', 30)), t('0 for no expiration of imported content')),
|
||||
'$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''),
|
||||
'$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())),
|
||||
'$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles')),
|
||||
|
||||
@@ -24,42 +24,42 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(\App::$cmd === 'api/oauth/authorize'){
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* api/oauth/authorize interact with the user. return a standard page
|
||||
*/
|
||||
|
||||
|
||||
\App::$page['template'] = 'minimal';
|
||||
|
||||
|
||||
// get consumer/client from request token
|
||||
try {
|
||||
$request = \OAuth1Request::from_request();
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
logger('OAuth exception: ' . print_r($e,true));
|
||||
// echo "<pre>"; var_dump($e);
|
||||
// echo "<pre>"; var_dump($e);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(x($_POST,'oauth_yes')){
|
||||
|
||||
|
||||
$app = $this->oauth_get_client($request);
|
||||
if (is_null($app))
|
||||
if (is_null($app))
|
||||
return "Invalid request. Unknown token.";
|
||||
|
||||
$consumer = new \OAuth1Consumer($app['client_id'], $app['pw'], $app['redirect_uri']);
|
||||
|
||||
|
||||
$verifier = md5($app['secret'] . local_channel());
|
||||
set_config('oauth', $verifier, local_channel());
|
||||
|
||||
|
||||
|
||||
|
||||
if($consumer->callback_url != null) {
|
||||
$params = $request->get_parameters();
|
||||
$glue = '?';
|
||||
@@ -68,28 +68,28 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
goaway($consumer->callback_url . $glue . "oauth_token=" . \OAuth1Util::urlencode_rfc3986($params['oauth_token']) . "&oauth_verifier=" . \OAuth1Util::urlencode_rfc3986($verifier));
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$tpl = get_markup_template("oauth_authorize_done.tpl");
|
||||
$o = replace_macros($tpl, array(
|
||||
'$title' => t('Authorize application connection'),
|
||||
'$info' => t('Return to your app and insert this Security Code:'),
|
||||
'$code' => $verifier,
|
||||
));
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(! local_channel()) {
|
||||
//TODO: we need login form to redirect to this page
|
||||
notice( t('Please login to continue.') . EOL );
|
||||
return login(false,'api-login',$request->get_parameters());
|
||||
}
|
||||
|
||||
|
||||
$app = $this->oauth_get_client($request);
|
||||
if (is_null($app))
|
||||
return "Invalid request. Unknown token.";
|
||||
|
||||
|
||||
$tpl = get_markup_template('oauth_authorize.tpl');
|
||||
$o = replace_macros($tpl, array(
|
||||
'$title' => t('Authorize application connection'),
|
||||
@@ -98,12 +98,12 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
'$yes' => t('Yes'),
|
||||
'$no' => t('No'),
|
||||
));
|
||||
|
||||
|
||||
//echo "<pre>"; var_dump($app); killme();
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
echo api_call();
|
||||
killme();
|
||||
}
|
||||
@@ -112,8 +112,8 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
|
||||
$params = $request->get_parameters();
|
||||
$token = $params['oauth_token'];
|
||||
|
||||
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
|
||||
|
||||
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
|
||||
AND tokens.id = '%s' AND tokens.auth_scope = 'request' ",
|
||||
dbesc($token)
|
||||
);
|
||||
@@ -121,7 +121,7 @@ class Api extends \Zotlabs\Web\Controller {
|
||||
return $r[0];
|
||||
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -110,6 +110,11 @@ class Appman extends \Zotlabs\Web\Controller {
|
||||
dbesc($papp['guid'])
|
||||
);
|
||||
|
||||
$sync[0]['term'] = q("select * from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($sync[0]['id'])
|
||||
);
|
||||
|
||||
if (intval($sync[0]['app_system'])) {
|
||||
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
|
||||
}
|
||||
@@ -126,6 +131,11 @@ class Appman extends \Zotlabs\Web\Controller {
|
||||
dbesc($papp['guid'])
|
||||
);
|
||||
|
||||
$sync[0]['term'] = q("select * from term where otype = %d and oid = %d",
|
||||
intval(TERM_OBJ_APP),
|
||||
intval($sync[0]['id'])
|
||||
);
|
||||
|
||||
if (intval($sync[0]['app_system'])) {
|
||||
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
|
||||
}
|
||||
|
||||
@@ -2,68 +2,13 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
class Apschema extends \Zotlabs\Web\Controller {
|
||||
|
||||
class Apschema extends Controller {
|
||||
function init() {
|
||||
|
||||
$base = z_root();
|
||||
|
||||
$arr = [
|
||||
'@context' => [
|
||||
'zot' => z_root() . '/apschema#',
|
||||
'id' => '@id',
|
||||
'type' => '@type',
|
||||
'commentPolicy' => 'zot:commentPolicy',
|
||||
'meData' => 'zot:meData',
|
||||
'meDataType' => 'zot:meDataType',
|
||||
'meEncoding' => 'zot:meEncoding',
|
||||
'meAlgorithm' => 'zot:meAlgorithm',
|
||||
'meCreator' => 'zot:meCreator',
|
||||
'meSignatureValue' => 'zot:meSignatureValue',
|
||||
'locationAddress' => 'zot:locationAddress',
|
||||
'locationPrimary' => 'zot:locationPrimary',
|
||||
'locationDeleted' => 'zot:locationDeleted',
|
||||
'nomadicLocation' => 'zot:nomadicLocation',
|
||||
'nomadicHubs' => 'zot:nomadicHubs',
|
||||
'emojiReaction' => 'zot:emojiReaction',
|
||||
'expires' => 'zot:expires',
|
||||
'directMessage' => 'zot:directMessage',
|
||||
'schema' => 'http://schema.org#',
|
||||
'PropertyValue' => 'schema:PropertyValue',
|
||||
'value' => 'schema:value',
|
||||
|
||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||
|
||||
|
||||
'magicEnv' => [
|
||||
'@id' => 'zot:magicEnv',
|
||||
'@type' => '@id'
|
||||
],
|
||||
|
||||
'nomadicLocations' => [
|
||||
'@id' => 'zot:nomadicLocations',
|
||||
'@type' => '@id'
|
||||
],
|
||||
|
||||
'ostatus' => 'http://ostatus.org#',
|
||||
'conversation' => 'ostatus:conversation',
|
||||
|
||||
'diaspora' => 'https://diasporafoundation.org/ns/',
|
||||
'guid' => 'diaspora:guid',
|
||||
|
||||
'Hashtag' => 'as:Hashtag'
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
header('Content-Type: application/ld+json');
|
||||
echo json_encode($arr,JSON_UNESCAPED_SLASHES);
|
||||
echo json_encode(Activity::ap_context(), JSON_UNESCAPED_SLASHES);
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -101,16 +101,23 @@ class Channel extends Controller {
|
||||
App::$meta->set('robots', 'noindex, noarchive');
|
||||
}
|
||||
|
||||
$identifier = 'uuid';
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
|
||||
if (str_starts_with($mid, 'b64.')) {
|
||||
$mid = unpack_link_id($mid);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($mid === false) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if (ActivityStreams::is_as_request($channel)) {
|
||||
|
||||
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
|
||||
// Make it do the right thing.
|
||||
|
||||
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
if ($mid === false) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
if ($mid) {
|
||||
$obj = null;
|
||||
if (strpos($mid, z_root() . '/item/') === 0) {
|
||||
@@ -127,6 +134,7 @@ class Channel extends Controller {
|
||||
$obj->init();
|
||||
}
|
||||
}
|
||||
|
||||
as_return_and_die(Activity::encode_person($channel, true), $channel);
|
||||
}
|
||||
|
||||
@@ -155,15 +163,9 @@ class Channel extends Controller {
|
||||
profile_load($which, $profile);
|
||||
|
||||
// Add Opengraph markup
|
||||
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
|
||||
if ($mid === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($mid) {
|
||||
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
$r = q("SELECT * FROM item WHERE $identifier = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||
dbesc($mid),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
@@ -178,7 +180,16 @@ class Channel extends Controller {
|
||||
|
||||
$category = $datequery = $datequery2 = '';
|
||||
|
||||
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
$identifier = 'uuid';
|
||||
$encoded_mid = null;
|
||||
|
||||
if (str_starts_with($mid, 'b64.')) {
|
||||
$encoded_mid = $mid;
|
||||
$mid = unpack_link_id($mid);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($mid === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
return;
|
||||
@@ -322,7 +333,7 @@ class Channel extends Controller {
|
||||
if (($update) && (!$load)) {
|
||||
|
||||
if ($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal_update
|
||||
$r = q("SELECT parent AS item_id, uuid from item where $identifier = '%s' and uid = %d $item_normal_update
|
||||
AND item_wall = 1 $simple_update $sql_extra limit 1",
|
||||
dbesc($mid),
|
||||
intval(App::$profile['profile_uid'])
|
||||
@@ -370,7 +381,7 @@ class Channel extends Controller {
|
||||
|
||||
if ($noscript_content || $load) {
|
||||
if ($mid) {
|
||||
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
|
||||
$r = q("SELECT parent AS item_id, uuid from item where $identifier = '%s' and uid = %d $item_normal
|
||||
AND item_wall = 1 $sql_extra limit 1",
|
||||
dbesc($mid),
|
||||
intval(App::$profile['profile_uid'])
|
||||
@@ -396,7 +407,6 @@ class Channel extends Controller {
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
|
||||
$parents_str = ids_to_querystr($r, 'item_id');
|
||||
|
||||
$r = q("SELECT item.*, item.id AS item_id
|
||||
@@ -427,13 +437,9 @@ class Channel extends Controller {
|
||||
|
||||
$mode = (($search) ? 'search' : 'channel');
|
||||
|
||||
|
||||
if ((!$update) && (!$load)) {
|
||||
|
||||
|
||||
|
||||
//if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($mid);
|
||||
|
||||
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
|
||||
// because browser prefetching might change it on us. We have to deliver it with the page.
|
||||
|
||||
@@ -470,7 +476,7 @@ class Channel extends Controller {
|
||||
'$file' => '',
|
||||
'$cats' => (($category) ? urlencode($category) : ''),
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||
'$mid' => $encoded_mid ?? $mid,
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$dend' => $datequery,
|
||||
|
||||
@@ -54,9 +54,9 @@ class Cloud extends Controller {
|
||||
if (local_channel()) {
|
||||
$channel = \App::get_channel();
|
||||
$auth->setCurrentUser($channel['channel_address']);
|
||||
$auth->channel_account_id = $channel['channel_account_id'];
|
||||
$auth->channel_id = $channel['channel_id'];
|
||||
$auth->channel_hash = $channel['channel_hash'];
|
||||
$auth->channel_account_id = $channel['channel_account_id'];
|
||||
if($channel['channel_timezone'])
|
||||
$auth->setTimezone($channel['channel_timezone']);
|
||||
}
|
||||
|
||||
@@ -177,22 +177,8 @@ class Contactedit extends Controller {
|
||||
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]';
|
||||
|
||||
$xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=' . $contact['xchan_photo_m'] . ']' . $contact['xchan_name'] . '[/zmg][/zrl]';
|
||||
post_activity_item($xarr);
|
||||
|
||||
}
|
||||
@@ -494,28 +480,32 @@ class Contactedit extends Controller {
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
if ($cmd === 'resetphoto') {
|
||||
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
|
||||
if ($cmd === 'refresh') {
|
||||
q("update xchan set xchan_photo_date = '0001-01-01 00:00:00', xchan_name_date = '0001-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');
|
||||
$ret['message'] = t('Refresh failed');
|
||||
}
|
||||
}
|
||||
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');
|
||||
$hookinfo = [
|
||||
'contact' => $contact,
|
||||
'success' => false,
|
||||
'message' => ''
|
||||
];
|
||||
|
||||
call_hooks('actor_refetch', $hookinfo);
|
||||
|
||||
$ret['success'] = $hookinfo['success'];
|
||||
$ret['message'] = $hookinfo['message'];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@@ -625,16 +615,10 @@ class Contactedit extends Controller {
|
||||
return [
|
||||
|
||||
'refresh' => [
|
||||
'label' => t('Refresh Permissions'),
|
||||
'title' => t('Fetch updated permissions'),
|
||||
'label' => t('Refresh'),
|
||||
'title' => t('Refetch contact info'),
|
||||
],
|
||||
|
||||
'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' : ''),
|
||||
|
||||
@@ -25,7 +25,7 @@ class Conversation extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
|
||||
@@ -93,8 +93,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
$image_id = substr($image_id,0,-2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$srcX = intval($_POST['xstart']);
|
||||
$srcY = intval($_POST['ystart']);
|
||||
$srcW = intval($_POST['xfinal']) - $srcX;
|
||||
@@ -228,7 +226,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->send_cover_photo_activity($channel,$base_image,$profile);
|
||||
profile_activity([t('Cover Photo')], $base_image['resource_id']);
|
||||
|
||||
$sync = attach_export_data($channel,$base_image['resource_id']);
|
||||
if($sync)
|
||||
@@ -245,13 +243,12 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$smallest = 0;
|
||||
|
||||
require_once('include/attach.php');
|
||||
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
|
||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', ['album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true, 'source' => 'photos']);
|
||||
|
||||
logger('attach_store: ' . print_r($res,true));
|
||||
|
||||
@@ -287,45 +284,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
}
|
||||
|
||||
function send_cover_photo_activity($channel,$photo,$profile) {
|
||||
|
||||
$arr = array();
|
||||
$arr['item_thread_top'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = 1;
|
||||
|
||||
if($profile && stripos($profile['gender'],t('female')) !== false)
|
||||
$t = t('%1$s updated her %2$s');
|
||||
elseif($profile && stripos($profile['gender'],t('male')) !== false)
|
||||
$t = t('%1$s updated his %2$s');
|
||||
else
|
||||
$t = t('%1$s updated their %2$s');
|
||||
|
||||
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
|
||||
|
||||
$ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
|
||||
|
||||
$arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$x = $acl->get();
|
||||
$arr['allow_cid'] = $x['allow_cid'];
|
||||
|
||||
$arr['allow_gid'] = $x['allow_gid'];
|
||||
$arr['deny_cid'] = $x['deny_cid'];
|
||||
$arr['deny_gid'] = $x['deny_gid'];
|
||||
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
post_activity_item($arr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate content of profile-photo view
|
||||
@@ -334,7 +292,6 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
|
||||
@@ -38,7 +38,14 @@ class Display extends Controller {
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
}
|
||||
|
||||
$item_hash = unpack_link_id($item_hash);
|
||||
$identifier = 'uuid';
|
||||
$encoded_item_hash = null;
|
||||
|
||||
if (str_starts_with($item_hash, 'b64.')) {
|
||||
$encoded_item_hash = $item_hash;
|
||||
$item_hash = unpack_link_id($item_hash);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($item_hash === false) {
|
||||
App::$error = 400;
|
||||
@@ -104,7 +111,7 @@ class Display extends Controller {
|
||||
|
||||
$target_item = null;
|
||||
|
||||
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where mid = '%s' limit 1",
|
||||
$r = q("select id, uid, mid, parent, parent_mid, thr_parent, verb, item_type, item_deleted, author_xchan, item_blocked from item where $identifier = '%s' limit 1",
|
||||
dbesc($item_hash)
|
||||
);
|
||||
|
||||
@@ -152,18 +159,11 @@ class Display extends Controller {
|
||||
call_hooks('item_custom_display', $target_item);
|
||||
|
||||
$simple_update = '';
|
||||
if($update && $_SESSION['loadtime'])
|
||||
if($update && isset($_SESSION['loadtime']))
|
||||
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
|
||||
|
||||
if((! $update) && (! $load)) {
|
||||
|
||||
// if the target item is not a post (eg a like) we want to address its thread parent
|
||||
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($target_item['mid']);
|
||||
|
||||
$o .= '<div id="live-display"></div>' . "\r\n";
|
||||
$o .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
|
||||
. "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
|
||||
@@ -196,7 +196,7 @@ class Display extends Controller {
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||
'$mid' => $encoded_item_hash ?? $item_hash
|
||||
));
|
||||
|
||||
head_add_link([
|
||||
|
||||
@@ -13,11 +13,10 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
|
||||
$table = 'item';
|
||||
$channel = \App::get_channel();
|
||||
$mid = ((argc() > 1) ? unpack_link_id(argv(1)) : '');
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
|
||||
if($mid === 'push') {
|
||||
if(argv(1) === 'push') {
|
||||
$table = 'push';
|
||||
$mid = ((argc() > 2) ? unpack_link_id(argv(2)) : '');
|
||||
|
||||
if($mid) {
|
||||
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
|
||||
@@ -31,7 +30,7 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
sleep(3);
|
||||
goaway(z_root() . '/dreport/' . gen_link_id($mid));
|
||||
goaway(z_root() . '/dreport?mid=' . $mid);
|
||||
}
|
||||
|
||||
if(! $mid) {
|
||||
@@ -114,7 +113,7 @@ class Dreport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
usort($r,'self::dreport_gravity_sort');
|
||||
usort($r, [self::class, 'dreport_gravity_sort']);
|
||||
|
||||
$entries = array();
|
||||
foreach($r as $rr) {
|
||||
|
||||
57
Zotlabs/Module/Emoji.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use App;
|
||||
|
||||
|
||||
class Emoji extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
$shortname = argv(1);
|
||||
|
||||
if (!$shortname) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$emojis = get_emojis();
|
||||
|
||||
if (!isset($emojis[$shortname])) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$emoji = $emojis[$shortname];
|
||||
|
||||
if (!file_exists($emoji['filepath'])) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$image = getimagesize($emoji['filepath']);
|
||||
|
||||
if(ActivityStreams::is_as_request()) {
|
||||
$last_modified = date(ATOM_TIME, filemtime($emoji['filepath']));
|
||||
|
||||
$obj = [
|
||||
'id' => z_root() . '/emoji/' . $shortname,
|
||||
'type' => 'Emoji',
|
||||
'name' => $emoji['shortname'],
|
||||
'updated' => $last_modified,
|
||||
'icon' => [
|
||||
'type' => 'Image',
|
||||
'mediaType' => $image['mime'],
|
||||
'url' => z_root() . '/' . $emoji['filepath']
|
||||
]
|
||||
];
|
||||
|
||||
as_return_and_die($obj);
|
||||
}
|
||||
|
||||
header('Content-Type: ' . $image['mime']);
|
||||
echo file_get_contents($emoji['filepath']);
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ namespace Zotlabs\Module;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Event extends Controller {
|
||||
@@ -17,7 +16,7 @@ class Event extends Controller {
|
||||
if(! $item_id)
|
||||
return;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
|
||||
and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
@@ -49,28 +48,9 @@ class Event extends Controller {
|
||||
$obj = $items[0]['obj'];
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]], $obj );
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$channel);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
as_return_and_die($obj, $channel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Lib\Connect;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
@@ -39,30 +38,14 @@ class Follow extends Controller {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
z_root() . ZOT_APSCHEMA_REV
|
||||
]],
|
||||
[
|
||||
$obj = [
|
||||
'id' => z_root() . '/follow/' . $r[0]['abook_id'],
|
||||
'type' => 'Follow',
|
||||
'actor' => $actor,
|
||||
'object' => $r[0]['xchan_url']
|
||||
]);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
];
|
||||
|
||||
as_return_and_die($obj, $chan);
|
||||
}
|
||||
|
||||
if (! local_channel()) {
|
||||
|
||||
@@ -30,16 +30,20 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
$item_hash = '';
|
||||
|
||||
if(argc() > 1 && argv(1) !== 'load') {
|
||||
$item_hash = unpack_link_id(argv(1));
|
||||
$item_hash = argv(1);
|
||||
}
|
||||
|
||||
if(isset($_REQUEST['mid'])) {
|
||||
$item_hash = unpack_link_id($_REQUEST['mid']);
|
||||
$item_hash = $_REQUEST['mid'];
|
||||
}
|
||||
|
||||
if($item_hash === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
return;
|
||||
$identifier = 'uuid';
|
||||
$encoded_item_hash = null;
|
||||
|
||||
if (str_starts_with($item_hash, 'b64.')) {
|
||||
$encoded_item_hash = $item_hash;
|
||||
$item_hash = unpack_link_id($item_hash);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
$item_normal = item_normal();
|
||||
@@ -54,7 +58,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
// select the target item with a bias to our own item
|
||||
$sql_order = ((local_channel() > $sys['channel_id']) ? 'DESC' : 'ASC');
|
||||
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where uid in (%d, %d) and mid = '%s' order by uid $sql_order limit 2",
|
||||
$r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where uid in (%d, %d) and $identifier = '%s' order by uid $sql_order limit 2",
|
||||
intval(local_channel()),
|
||||
intval($sys['channel_id']),
|
||||
dbesc($item_hash)
|
||||
@@ -118,7 +122,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
//$mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']);
|
||||
|
||||
// if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($target_item['mid']);
|
||||
// $mid = gen_link_id($target_item['mid']);
|
||||
}
|
||||
else {
|
||||
$mid = '';
|
||||
@@ -156,7 +160,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
||||
'$dbegin' => '',
|
||||
'$verb' => '',
|
||||
'$net' => '',
|
||||
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||
'$mid' => $encoded_item_hash ?? $item_hash
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class Item extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -168,7 +168,7 @@ class Item extends Controller {
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
|
||||
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
|
||||
dbesc(ACTIVITY_FOLLOW),
|
||||
dbesc(ACTIVITY_UNFOLLOW)
|
||||
);
|
||||
@@ -275,7 +275,7 @@ class Item extends Controller {
|
||||
|
||||
|
||||
if (argc() > 1 && argv(1) !== 'drop') {
|
||||
$x = q("select uid, item_wall, llink, mid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
|
||||
$x = q("select uid, item_wall, llink, mid, uuid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
|
||||
dbesc(z_root() . '/item/' . argv(1)),
|
||||
dbesc(z_root() . '/activity/' . argv(1)),
|
||||
dbesc(argv(1))
|
||||
@@ -285,7 +285,7 @@ class Item extends Controller {
|
||||
if (intval($xv['item_wall'])) {
|
||||
$c = channelx_by_n($xv['uid']);
|
||||
if ($c) {
|
||||
goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . gen_link_id($xv['mid']));
|
||||
goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $xv['uuid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,7 +298,6 @@ class Item extends Controller {
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
// This will change. Figure out who the observer is and whether or not
|
||||
// they have permission to post here. Else ignore the post.
|
||||
|
||||
@@ -405,7 +404,7 @@ class Item extends Controller {
|
||||
$pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags($_REQUEST['pagetitle']) : '');
|
||||
$layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : '');
|
||||
$plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
|
||||
$obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : ACTIVITY_OBJ_NOTE);
|
||||
$obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : 'Article');
|
||||
|
||||
// allow API to bulk load a bunch of imported items with sending out a bunch of posts.
|
||||
$nopush = ((x($_REQUEST, 'nopush')) ? intval($_REQUEST['nopush']) : 0);
|
||||
@@ -444,9 +443,6 @@ class Item extends Controller {
|
||||
if (!x($_REQUEST, 'type'))
|
||||
$_REQUEST['type'] = 'net-comment';
|
||||
|
||||
if ($obj_type == ACTIVITY_OBJ_NOTE)
|
||||
$obj_type = ACTIVITY_OBJ_COMMENT;
|
||||
|
||||
if ($parent) {
|
||||
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
|
||||
intval($parent)
|
||||
@@ -679,7 +675,7 @@ class Item extends Controller {
|
||||
$verb = $orig_post['verb'];
|
||||
$app = $orig_post['app'];
|
||||
$title = escape_tags(trim($_REQUEST['title']));
|
||||
$summary = trim($_REQUEST['summary']);
|
||||
$summary = escape_tags(trim($_REQUEST['summary']));
|
||||
$body = trim($_REQUEST['body']);
|
||||
$item_flags = $orig_post['item_flags'];
|
||||
$item_origin = $orig_post['item_origin'];
|
||||
@@ -740,7 +736,7 @@ class Item extends Controller {
|
||||
$coord = ((isset($_REQUEST['coord'])) ? notags(trim($_REQUEST['coord'])) : '');
|
||||
$verb = ((isset($_REQUEST['verb'])) ? notags(trim($_REQUEST['verb'])) : '');
|
||||
$title = ((isset($_REQUEST['title'])) ? escape_tags(trim($_REQUEST['title'])) : '');
|
||||
$summary = ((isset($_REQUEST['summary'])) ? trim($_REQUEST['summary']) : '');
|
||||
$summary = ((isset($_REQUEST['summary'])) ? escape_tags(trim($_REQUEST['summary'])) : '');
|
||||
$body = ((isset($_REQUEST['body'])) ? trim($_REQUEST['body']) : '');
|
||||
$body .= ((isset($_REQUEST['attachment'])) ? trim($_REQUEST['attachment']) : '');
|
||||
$postopts = '';
|
||||
@@ -793,7 +789,6 @@ class Item extends Controller {
|
||||
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
|
||||
|
||||
if ($preview) {
|
||||
$summary = z_input_filter($summary, $mimetype, $execflag);
|
||||
$body = z_input_filter($body, $mimetype, $execflag);
|
||||
}
|
||||
|
||||
@@ -943,6 +938,30 @@ class Item extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match_all('/(\:(\w|\+|\-)+\:)(?=|[\!\.\?]|$)/', $body, $match)) {
|
||||
// emoji shortcodes
|
||||
$emojis = get_emojis();
|
||||
foreach ($match[0] as $mtch) {
|
||||
$shortname = trim($mtch, ':');
|
||||
|
||||
if (!isset($emojis[$shortname])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$emoji = $emojis[$shortname];
|
||||
|
||||
$post_tags[] = [
|
||||
'uid' => $profile_uid,
|
||||
'ttype' => TERM_EMOJI,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => trim($mtch),
|
||||
'url' => z_root() . '/emoji/' . $shortname,
|
||||
'imgurl' => z_root() . '/' . $emoji['filepath']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BBCODE end alert
|
||||
}
|
||||
|
||||
@@ -963,6 +982,10 @@ class Item extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if ($orig_post) {
|
||||
// preserve original tags
|
||||
$t = q("select * from term where oid = %d and otype = %d and uid = %d and ttype in ( %d, %d, %d )",
|
||||
@@ -1009,7 +1032,7 @@ class Item extends Controller {
|
||||
|
||||
|
||||
if (!strlen($verb))
|
||||
$verb = ACTIVITY_POST;
|
||||
$verb = 'Create';
|
||||
|
||||
$notify_type = (($parent) ? 'comment-new' : 'wall-new');
|
||||
|
||||
@@ -1220,18 +1243,6 @@ class Item extends Controller {
|
||||
$this->add_listeners($datarray);
|
||||
}
|
||||
|
||||
// We only need edit activities for other federated protocols
|
||||
// which do not support edits natively. While this does federate
|
||||
// edits, it presents a number of issues locally - such as #757 and #758.
|
||||
// The SQL check for an edit activity would not perform that well so to fix these issues
|
||||
// requires an additional item flag (perhaps 'item_edit_activity') that we can add to the
|
||||
// query for searches and notifications.
|
||||
|
||||
// For now we'll just forget about trying to make edits work on network protocols that
|
||||
// don't support them.
|
||||
|
||||
// item_create_edit_activity($x);
|
||||
|
||||
if (!$parent) {
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
@@ -1285,8 +1296,8 @@ class Item extends Controller {
|
||||
'from_xchan' => $datarray['author_xchan'],
|
||||
'to_xchan' => $datarray['owner_xchan'],
|
||||
'item' => $datarray,
|
||||
'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
|
||||
'verb' => ACTIVITY_POST,
|
||||
'link' => z_root() . '/display/' . $datarray['uuid'],
|
||||
'verb' => 'Create',
|
||||
'otype' => 'item',
|
||||
'parent' => $parent,
|
||||
'parent_mid' => $parent_item['mid']
|
||||
@@ -1303,8 +1314,8 @@ class Item extends Controller {
|
||||
'from_xchan' => $datarray['author_xchan'],
|
||||
'to_xchan' => $datarray['owner_xchan'],
|
||||
'item' => $datarray,
|
||||
'link' => z_root() . '/display/' . gen_link_id($datarray['mid']),
|
||||
'verb' => ACTIVITY_POST,
|
||||
'link' => z_root() . '/display/' . $datarray['uuid'],
|
||||
'verb' => 'Create',
|
||||
'otype' => 'item'
|
||||
]);
|
||||
}
|
||||
@@ -1349,7 +1360,7 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
$datarray['id'] = $post_id;
|
||||
$datarray['llink'] = z_root() . '/display/' . gen_link_id($datarray['mid']);
|
||||
$datarray['llink'] = z_root() . '/display/' . $datarray['uuid'];
|
||||
|
||||
call_hooks('post_local_end', $datarray);
|
||||
|
||||
@@ -1373,7 +1384,7 @@ class Item extends Controller {
|
||||
|
||||
if ($return_path) {
|
||||
if ($return_path === 'hq') {
|
||||
goaway(z_root() . '/hq/' . gen_link_id($datarray['mid']));
|
||||
goaway(z_root() . '/hq/' . $datarray['uuid']);
|
||||
}
|
||||
|
||||
goaway(z_root() . "/" . $return_path);
|
||||
|
||||
@@ -19,14 +19,12 @@ class Like extends Controller {
|
||||
private function reaction_to_activity($reaction) {
|
||||
|
||||
$acts = [
|
||||
'like' => ACTIVITY_LIKE,
|
||||
'dislike' => ACTIVITY_DISLIKE,
|
||||
'agree' => ACTIVITY_AGREE,
|
||||
'disagree' => ACTIVITY_DISAGREE,
|
||||
'abstain' => ACTIVITY_ABSTAIN,
|
||||
'attendyes' => ACTIVITY_ATTEND,
|
||||
'attendno' => ACTIVITY_ATTENDNO,
|
||||
'attendmaybe' => ACTIVITY_ATTENDMAYBE
|
||||
'like' => 'Like',
|
||||
'dislike' => 'Dislike',
|
||||
'announce' => ACTIVITY_SHARE,
|
||||
'attendyes' => 'Accept',
|
||||
'attendno' => 'Reject',
|
||||
'attendmaybe' => 'TentativeAccept'
|
||||
];
|
||||
|
||||
// unlike (etc.) reactions are an undo of positive reactions, rather than a negative action.
|
||||
@@ -71,11 +69,12 @@ class Like extends Controller {
|
||||
$activities = q("SELECT item.*, item.id AS item_id FROM item
|
||||
WHERE uid = %d $item_normal
|
||||
AND thr_parent = '%s'
|
||||
AND verb IN ('%s', '%s', '%s', '%s', '%s')",
|
||||
AND verb IN ('%s', '%s', '%s', '%s', '%s', '%s', 'Accept', 'Reject', 'TentativeAccept')",
|
||||
intval($arr['item']['uid']),
|
||||
dbesc($arr['item']['mid']),
|
||||
dbesc(ACTIVITY_LIKE),
|
||||
dbesc(ACTIVITY_DISLIKE),
|
||||
dbesc('Like'),
|
||||
dbesc('Dislike'),
|
||||
dbesc(ACTIVITY_SHARE),
|
||||
dbesc(ACTIVITY_ATTEND),
|
||||
dbesc(ACTIVITY_ATTENDNO),
|
||||
dbesc(ACTIVITY_ATTENDMAYBE)
|
||||
@@ -133,7 +132,7 @@ class Like extends Controller {
|
||||
}
|
||||
|
||||
$is_rsvp = false;
|
||||
if (in_array($activity, [ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
|
||||
if (in_array($activity, ['Accept', 'Reject', 'TentativeAccept', ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
|
||||
$is_rsvp = true;
|
||||
}
|
||||
|
||||
@@ -182,7 +181,7 @@ class Like extends Controller {
|
||||
}
|
||||
}
|
||||
$post_type = t('channel');
|
||||
$obj_type = ACTIVITY_OBJ_PROFILE;
|
||||
$obj_type = 'Profile';
|
||||
|
||||
$profile = $r[0];
|
||||
}
|
||||
@@ -211,8 +210,8 @@ class Like extends Controller {
|
||||
$public = false;
|
||||
|
||||
$post_type = t('thing');
|
||||
$obj_type = ACTIVITY_OBJ_PROFILE;
|
||||
$tgttype = ACTIVITY_OBJ_THING;
|
||||
$obj_type = 'Profile';
|
||||
$tgttype = 'Page';
|
||||
|
||||
$links = array();
|
||||
$links[] = array('rel' => 'alternate', 'type' => 'text/html',
|
||||
@@ -220,12 +219,7 @@ class Like extends Controller {
|
||||
if ($r[0]['imgurl'])
|
||||
$links[] = array('rel' => 'photo', 'href' => $r[0]['obj_imgurl']);
|
||||
|
||||
$target = json_encode(array(
|
||||
'type' => $tgttype,
|
||||
'title' => $r[0]['obj_term'],
|
||||
'id' => z_root() . '/thing/' . $r[0]['obj_obj'],
|
||||
'link' => $links
|
||||
));
|
||||
$target = Activity::fetch_thing(['id' => $r[0]['obj_obj']]);
|
||||
|
||||
$plink = '[zrl=' . z_root() . '/thing/' . $r[0]['obj_obj'] . ']' . $r[0]['obj_term'] . '[/zrl]';
|
||||
|
||||
@@ -323,6 +317,8 @@ class Like extends Controller {
|
||||
// parent, copy that as well.
|
||||
|
||||
if ($r) {
|
||||
$obj_type = $r[0]['obj_type'];
|
||||
|
||||
if ($r[0]['uid'] === $sys_channel['channel_id'] && local_channel()) {
|
||||
$r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
|
||||
}
|
||||
@@ -370,15 +366,11 @@ class Like extends Controller {
|
||||
|
||||
$multi_undo = false;
|
||||
|
||||
// event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
|
||||
// event participation items are essentially radio toggles. If you make a subsequent choice,
|
||||
// we need to eradicate your first choice.
|
||||
|
||||
if ($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
|
||||
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
|
||||
$multi_undo = 1;
|
||||
}
|
||||
if ($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
|
||||
$verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
|
||||
if (in_array($activity, ['Accept', 'Reject', 'TentativeAccept', ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE])) {
|
||||
$verbs = "'Accept','Reject','TentativeAccept','" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
|
||||
$multi_undo = true;
|
||||
}
|
||||
|
||||
@@ -437,7 +429,7 @@ class Like extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
$uuid = new_uuid();
|
||||
|
||||
$arr = array();
|
||||
|
||||
@@ -450,14 +442,20 @@ class Like extends Controller {
|
||||
$arr['item_wall'] = 1;
|
||||
}
|
||||
else {
|
||||
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
|
||||
if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT]))
|
||||
$post_type = t('event');
|
||||
|
||||
$obj_type = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE);
|
||||
|
||||
if ($obj_type === ACTIVITY_OBJ_NOTE && (!intval($item['item_thread_top'])))
|
||||
$obj_type = ACTIVITY_OBJ_COMMENT;
|
||||
switch ($item['object_type']) {
|
||||
case 'Image':
|
||||
$post_type = t('image');
|
||||
break;
|
||||
case 'Invite':
|
||||
$post_type = t('event');
|
||||
break;
|
||||
case 'Profile':
|
||||
$post_type = t('profile');
|
||||
break;
|
||||
default:
|
||||
$post_type = t('status');
|
||||
break;
|
||||
}
|
||||
|
||||
$object = json_encode(Activity::fetch_item(['id' => $item['mid']]));
|
||||
|
||||
@@ -485,12 +483,6 @@ class Like extends Controller {
|
||||
$bodyverb = t('%1$s likes %2$s\'s %3$s');
|
||||
if ($verb === 'dislike')
|
||||
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
|
||||
if ($verb === 'agree')
|
||||
$bodyverb = t('%1$s agrees with %2$s\'s %3$s');
|
||||
if ($verb === 'disagree')
|
||||
$bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s');
|
||||
if ($verb === 'abstain')
|
||||
$bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s');
|
||||
if ($verb === 'attendyes')
|
||||
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
|
||||
if ($verb === 'attendno')
|
||||
@@ -511,7 +503,7 @@ class Like extends Controller {
|
||||
$arr['thr_parent'] = $item['mid'];
|
||||
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . $item['uuid'] . ']' . $post_type . '[/zrl]';
|
||||
$allow_cid = $item['allow_cid'];
|
||||
$allow_gid = $item['allow_gid'];
|
||||
$deny_cid = $item['deny_cid'];
|
||||
@@ -532,7 +524,7 @@ class Like extends Controller {
|
||||
if ($obj_type === 'thing' && $r[0]['imgurl']) {
|
||||
$arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
|
||||
}
|
||||
if ($obj_type === 'profile') {
|
||||
if ($obj_type === 'Profile') {
|
||||
if ($public) {
|
||||
$arr['body'] .= "\n\n" . '[embed]' . z_root() . '/profile/' . $ch[0]['channel_address'] . '[/embed]';
|
||||
}
|
||||
@@ -586,6 +578,7 @@ class Like extends Controller {
|
||||
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
|
||||
}
|
||||
|
||||
|
||||
if ($extended_like) {
|
||||
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
|
||||
intval($ch[0]['channel_id']),
|
||||
|
||||
@@ -291,11 +291,15 @@ class Linkinfo extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Check codepage in HTTP headers or HTML if not exist
|
||||
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
|
||||
if(empty($cp))
|
||||
$cp = (preg_match('/meta.+content=["\']text\/html; charset=([^"\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
if(empty($cp)) {
|
||||
$cp = (preg_match('/meta.+content=["\']text\/html; charset=([^"\']+)/i', $body, $o) ? $o[1] : 'AUTO');
|
||||
}
|
||||
|
||||
$body = mb_convert_encoding($body, 'UTF-8', $cp);
|
||||
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
$body = mb_convert_encoding($body, 'UTF-8', $cp);
|
||||
|
||||
// Handling HTML entities via mbstring is deprecated
|
||||
//$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
|
||||
$body = mb_encode_numericentity($body, [0x80, 0x10FFFF, 0, ~0], 'UTF-8');
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
@$doc->loadHTML($body);
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
|
||||
class Mood extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uid = local_channel();
|
||||
$channel = App::get_channel();
|
||||
$verb = ((isset($_GET['verb'])) ? notags(trim($_GET['verb'])) : '');
|
||||
|
||||
if(! $verb)
|
||||
return;
|
||||
|
||||
$verbs = get_mood_verbs();
|
||||
|
||||
if(! array_key_exists($verb,$verbs))
|
||||
return;
|
||||
|
||||
$activity = ACTIVITY_MOOD . '#' . urlencode($verb);
|
||||
|
||||
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : 0);
|
||||
|
||||
|
||||
logger('mood: verb ' . $verb, LOGGER_DEBUG);
|
||||
|
||||
|
||||
if($parent) {
|
||||
$r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid
|
||||
from item where id = %d and parent = %d and uid = %d limit 1",
|
||||
intval($parent),
|
||||
intval($parent),
|
||||
intval($uid)
|
||||
);
|
||||
if(count($r)) {
|
||||
$parent_mid = $r[0]['mid'];
|
||||
$private = $r[0]['item_private'];
|
||||
$allow_cid = $r[0]['allow_cid'];
|
||||
$allow_gid = $r[0]['allow_gid'];
|
||||
$deny_cid = $r[0]['deny_cid'];
|
||||
$deny_gid = $r[0]['deny_gid'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$private = 0;
|
||||
|
||||
$allow_cid = $channel['channel_allow_cid'];
|
||||
$allow_gid = $channel['channel_allow_gid'];
|
||||
$deny_cid = $channel['channel_deny_cid'];
|
||||
$deny_gid = $channel['channel_deny_gid'];
|
||||
}
|
||||
|
||||
$poster = App::get_observer();
|
||||
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
|
||||
|
||||
$arr = array();
|
||||
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $uid;
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
$arr['owner_xchan'] = (($parent_mid) ? $r[0]['owner_xchan'] : $poster['xchan_hash']);
|
||||
$arr['title'] = '';
|
||||
$arr['allow_cid'] = $allow_cid;
|
||||
$arr['allow_gid'] = $allow_gid;
|
||||
$arr['deny_cid'] = $deny_cid;
|
||||
$arr['deny_gid'] = $deny_gid;
|
||||
$arr['item_private'] = $private;
|
||||
$arr['verb'] = $activity;
|
||||
$arr['body'] = $action;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
if(! $parent_mid)
|
||||
$item['item_thread_top'] = 1;
|
||||
|
||||
if ((! $arr['plink']) && intval($arr['item_thread_top'])) {
|
||||
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
|
||||
}
|
||||
|
||||
|
||||
$post = item_store($arr);
|
||||
$item_id = $post['item_id'];
|
||||
|
||||
if($item_id) {
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','activity', $item_id));
|
||||
}
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
if($_SESSION['return_url'])
|
||||
goaway(z_root() . '/' . $_SESSION['return_url']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Mood')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
$papp = Apps::get_papp('Mood');
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
|
||||
nav_set_selected('Mood');
|
||||
|
||||
$parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0');
|
||||
|
||||
$verbs = get_mood_verbs();
|
||||
|
||||
$shortlist = array();
|
||||
foreach($verbs as $k => $v)
|
||||
if($v !== 'NOTRANSLATION')
|
||||
$shortlist[] = array($k,$v);
|
||||
|
||||
|
||||
$tpl = get_markup_template('mood_content.tpl');
|
||||
|
||||
$o = replace_macros($tpl,array(
|
||||
'$title' => t('Mood'),
|
||||
'$desc' => t('Set your current mood and tell your friends'),
|
||||
'$verbs' => $shortlist,
|
||||
'$parent' => $parent,
|
||||
'$submit' => t('Submit'),
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -275,7 +275,7 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
|
||||
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
|
||||
if(! ($vnotify & VNOTIFY_LIKE))
|
||||
$likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$likes_sql = " AND verb NOT IN ('Like', 'Dislike', '" . 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'",
|
||||
|
||||
@@ -63,10 +63,6 @@ class Owa extends Controller {
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $hubloc) {
|
||||
// fix friendica accept header for nginx
|
||||
if (str_starts_with($keyId, 'acct:') && $_SERVER['HTTP_ACCEPT'] === 'application/x-zot+json')
|
||||
$_SERVER['HTTP_ACCEPT'] = 'application/x-dfrn+json, application/x-zot+json';
|
||||
|
||||
$verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
|
||||
if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
|
||||
logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
|
||||
|
||||
@@ -1108,7 +1108,6 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
|
||||
$conv_responses = array(
|
||||
'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')),
|
||||
'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')),
|
||||
'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
|
||||
);
|
||||
|
||||
@@ -1152,8 +1151,9 @@ class Photos extends \Zotlabs\Web\Controller {
|
||||
$template = $tpl;
|
||||
$sparkle = '';
|
||||
|
||||
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
|
||||
if(activity_match($item['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]) && $item['id'] != $item['parent']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$redirect_url = z_root() . '/redir/' . $item['cid'] ;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class Pin extends \Zotlabs\Web\Controller {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$midb64 = gen_link_id($r[0]['mid']);
|
||||
$midb64 = $r[0]['uuid'];
|
||||
$pinned = (in_array($midb64, get_pconfig($r[0]['uid'], 'pinned', $r[0]['item_type'], [])) ? true : false);
|
||||
|
||||
switch(argv(1)) {
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module; /** @file */
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
/**
|
||||
*
|
||||
* Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
|
||||
* This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
|
||||
* other web request. You must be logged in and connected to a channel.
|
||||
* If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
|
||||
* parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
|
||||
* may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the adult
|
||||
* plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
|
||||
*
|
||||
* private creates a private conversation with the recipient. Otherwise your channel's default post privacy is used.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
class Poke extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uid = local_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$verb = ((isset($_GET['verb'])) ? notags(trim($_GET['verb'])) : '');
|
||||
|
||||
if(! $verb)
|
||||
return;
|
||||
|
||||
$verbs = get_poke_verbs();
|
||||
|
||||
if(! array_key_exists($verb,$verbs))
|
||||
return;
|
||||
|
||||
$activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]);
|
||||
|
||||
$contact_id = intval($_REQUEST['cid']);
|
||||
|
||||
$xchan = trim($_REQUEST['xchan']);
|
||||
|
||||
if(! ($contact_id || $xchan))
|
||||
return;
|
||||
|
||||
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
|
||||
|
||||
logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG);
|
||||
|
||||
|
||||
if($contact_id) {
|
||||
$r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1",
|
||||
intval($contact_id),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
if($xchan) {
|
||||
$r = q("SELECT * FROM xchan where xchan_hash like ( '%s' ) LIMIT 1",
|
||||
dbesc($xchan . '%')
|
||||
);
|
||||
}
|
||||
|
||||
if(! $r) {
|
||||
logger('poke: no target.');
|
||||
return;
|
||||
}
|
||||
|
||||
$target = $r[0];
|
||||
$parent_item = null;
|
||||
|
||||
if($parent) {
|
||||
$r = q("select mid, item_private, owner_xchan, allow_cid, allow_gid, deny_cid, deny_gid
|
||||
from item where id = %d and parent = %d and uid = %d limit 1",
|
||||
intval($parent),
|
||||
intval($parent),
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
$parent_item = $r[0];
|
||||
$parent_mid = $r[0]['mid'];
|
||||
$item_private = $r[0]['item_private'];
|
||||
$allow_cid = $r[0]['allow_cid'];
|
||||
$allow_gid = $r[0]['allow_gid'];
|
||||
$deny_cid = $r[0]['deny_cid'];
|
||||
$deny_gid = $r[0]['deny_gid'];
|
||||
}
|
||||
}
|
||||
elseif($contact_id) {
|
||||
|
||||
$item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0);
|
||||
|
||||
$allow_cid = (($item_private) ? '<' . $target['abook_xchan']. '>' : $channel['channel_allow_cid']);
|
||||
$allow_gid = (($item_private) ? '' : $channel['channel_allow_gid']);
|
||||
$deny_cid = (($item_private) ? '' : $channel['channel_deny_cid']);
|
||||
$deny_gid = (($item_private) ? '' : $channel['channel_deny_gid']);
|
||||
}
|
||||
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['owner_xchan'] = (($parent_item) ? $parent_item['owner_xchan'] : $channel['channel_hash']);
|
||||
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : '');
|
||||
$arr['title'] = '';
|
||||
$arr['allow_cid'] = $allow_cid;
|
||||
$arr['allow_gid'] = $allow_gid;
|
||||
$arr['deny_cid'] = $deny_cid;
|
||||
$arr['deny_gid'] = $deny_gid;
|
||||
$arr['verb'] = $activity;
|
||||
$arr['item_private'] = $item_private;
|
||||
$arr['obj_type'] = ACTIVITY_OBJ_NOTE;
|
||||
$arr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t($verbs[$verb][0]) . ' ' . '[zrl=' . $target['xchan_url'] . ']' . $target['xchan_name'] . '[/zrl]';
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
if(! $parent_item)
|
||||
$arr['item_thread_top'] = 1;
|
||||
|
||||
$arr['obj'] = Activity::encode_item($arr);
|
||||
|
||||
|
||||
post_activity_item($arr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(! Apps::system_app_installed(local_channel(), 'Poke')) {
|
||||
//Do not display any associated widgets at this point
|
||||
App::$pdl = '';
|
||||
$papp = Apps::get_papp('Poke');
|
||||
return Apps::app_render($papp, 'module');
|
||||
}
|
||||
|
||||
nav_set_selected('Poke');
|
||||
|
||||
$name = '';
|
||||
$id = '';
|
||||
|
||||
if(isset($_REQUEST['c']) && intval($_REQUEST['c'])) {
|
||||
$r = q("select abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_id = %d and abook_channel = %d limit 1",
|
||||
intval($_REQUEST['c']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$name = $r[0]['xchan_name'];
|
||||
$id = $r[0]['abook_id'];
|
||||
}
|
||||
}
|
||||
|
||||
$parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : '0');
|
||||
|
||||
$verbs = get_poke_verbs();
|
||||
|
||||
$shortlist = array();
|
||||
foreach($verbs as $k => $v)
|
||||
if($v[1] !== 'NOTRANSLATION')
|
||||
$shortlist[] = array($k,$v[1]);
|
||||
|
||||
|
||||
$poke_basic = get_config('system','poke_basic');
|
||||
if($poke_basic) {
|
||||
$title = t('Poke');
|
||||
$desc = t('Poke somebody');
|
||||
}
|
||||
else {
|
||||
$title = t('Poke');
|
||||
$desc = t('Poke or ping somebody');
|
||||
}
|
||||
|
||||
$o = replace_macros(get_markup_template('poke_content.tpl'),array(
|
||||
'$title' => $title,
|
||||
'$poke_basic' => $poke_basic,
|
||||
'$desc' => $desc,
|
||||
'$clabel' => t('Recipient'),
|
||||
'$choice' => t('Choose action'),
|
||||
'$verbs' => $shortlist,
|
||||
'$parent' => $parent,
|
||||
'$prv_desc' => t('Make this post private'),
|
||||
'$private' => array('private', t('Make this post private'), false, ''),
|
||||
'$submit' => t('Submit'),
|
||||
'$name' => $name,
|
||||
'$id' => $id
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ class Profile_photo extends Controller {
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
send_profile_photo_activity($channel, $base_image, $profile);
|
||||
profile_activity([t('Profile Photo')], $base_image['resource_id']);
|
||||
}
|
||||
else {
|
||||
q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
|
||||
@@ -269,7 +269,6 @@ class Profile_photo extends Controller {
|
||||
|
||||
// Update directory in background
|
||||
Master::Summon(['Directory', $channel['channel_id']]);
|
||||
|
||||
}
|
||||
else
|
||||
notice(t('Unable to process image') . EOL);
|
||||
|
||||
@@ -3,10 +3,6 @@ namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/channel.php');
|
||||
require_once('include/selectors.php');
|
||||
|
||||
|
||||
class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
@@ -492,7 +488,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
|
||||
$publish = ((x($_POST, 'profile_in_directory') && (intval($_POST['profile_in_directory']) == 1)) ? 1 : 0);
|
||||
|
||||
profile_activity($changes,$value);
|
||||
profile_activity($changes, $value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,15 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
|
||||
$site_firehose = ((intval(get_config('system','site_firehose',0))) ? true : false);
|
||||
|
||||
$mid = ((isset($_REQUEST['mid'])) ? unpack_link_id($_REQUEST['mid']) : '');
|
||||
$mid = $_REQUEST['mid'] ?? '';
|
||||
$identifier = 'uuid';
|
||||
$encoded_mid = null;
|
||||
|
||||
if (str_starts_with($mid, 'b64.')) {
|
||||
$encoded_mid = $mid;
|
||||
$mid = unpack_link_id($mid);
|
||||
$identifier = 'mid';
|
||||
}
|
||||
|
||||
if ($mid === false) {
|
||||
notice(t('Malformed message id.') . EOL);
|
||||
@@ -108,9 +116,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
. "; var profile_page = " . \App::$pager['page']
|
||||
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
|
||||
|
||||
//if we got a decoded hash we must encode it again before handing to javascript
|
||||
$mid = gen_link_id($mid);
|
||||
|
||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
||||
'$baseurl' => z_root(),
|
||||
'$pgtype' => 'pubstream',
|
||||
@@ -136,7 +141,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
'$cats' => '',
|
||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||
'$dend' => '',
|
||||
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||
'$mid' => $encoded_mid ?? $mid,
|
||||
'$verb' => '',
|
||||
'$net' => (($net) ? urlencode($net) : ''),
|
||||
'$dbegin' => ''
|
||||
@@ -198,7 +203,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT parent AS item_id FROM item
|
||||
left join abook on item.author_xchan = abook.abook_xchan
|
||||
$net_query
|
||||
WHERE item.mid = '%s' and item.item_private = 0
|
||||
WHERE item.$identifier = '%s' and item.item_private = 0
|
||||
$uids $site_firehose_sql
|
||||
$item_normal
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
@@ -225,7 +230,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT parent AS item_id FROM item
|
||||
left join abook on item.author_xchan = abook.abook_xchan
|
||||
$net_query
|
||||
WHERE item.mid = '%s' and item.item_private = 0
|
||||
WHERE item.$identifier = '%s' and item.item_private = 0
|
||||
$uids $site_firehose_sql $item_normal_update $simple_update
|
||||
and (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||
$sql_extra $net_query2",
|
||||
|
||||
@@ -2,82 +2,96 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Daemon\Master;
|
||||
|
||||
class React extends \Zotlabs\Web\Controller {
|
||||
class React extends Controller {
|
||||
|
||||
function get() {
|
||||
|
||||
if(! local_channel())
|
||||
if (!local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sys = get_sys_channel();
|
||||
$channel = \App::get_channel();
|
||||
$channel = App::get_channel();
|
||||
|
||||
$postid = $_REQUEST['postid'];
|
||||
|
||||
if(! $postid)
|
||||
if (!$postid) {
|
||||
return;
|
||||
|
||||
$emoji = $_REQUEST['emoji'];
|
||||
|
||||
|
||||
if($_REQUEST['emoji']) {
|
||||
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if(! $i) {
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
|
||||
if($i) {
|
||||
$i = [ copy_of_pubitem($channel, $i[0]['mid']) ];
|
||||
$postid = (($i) ? $i[0]['id'] : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(! $i) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
|
||||
$n = array();
|
||||
$n['aid'] = $channel['channel_account_id'];
|
||||
$n['uid'] = $channel['channel_id'];
|
||||
$n['item_origin'] = true;
|
||||
$n['item_type'] = $i[0]['item_type'];
|
||||
$n['parent'] = $postid;
|
||||
$n['parent_mid'] = $i[0]['mid'];
|
||||
$n['uuid'] = $uuid;
|
||||
$n['mid'] = z_root() . '/item/' . $uuid;
|
||||
$n['verb'] = ACTIVITY_REACT . '#' . $emoji;
|
||||
$n['body'] = "\n\n[zmg=32x32]" . z_root() . '/images/emoji/' . $emoji . '.png[/zmg]' . "\n\n";
|
||||
$n['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
$n['tgt_type'] = 'Image';
|
||||
$n['target'] = [
|
||||
'type' => 'Image',
|
||||
'name' => $emoji,
|
||||
'url' => z_root() . '/images/emoji/' . $emoji . '.png'
|
||||
];
|
||||
|
||||
|
||||
$x = item_store($n);
|
||||
|
||||
retain_item($postid);
|
||||
|
||||
if($x['success']) {
|
||||
$nid = $x['item_id'];
|
||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','like',$nid));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$shortname = $_REQUEST['emoji'];
|
||||
|
||||
$emojis = get_emojis();
|
||||
|
||||
if (!isset($emojis[$shortname])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$emoji = $emojis[$shortname];
|
||||
|
||||
if (!$emoji) {
|
||||
return;
|
||||
}
|
||||
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if (!$i) {
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
intval($postid),
|
||||
intval($sys['channel_id'])
|
||||
);
|
||||
|
||||
if ($i) {
|
||||
$i = [ copy_of_pubitem($channel, $i[0]['mid']) ];
|
||||
$postid = (($i) ? $i[0]['id'] : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uuid = item_message_id();
|
||||
|
||||
$n['aid'] = $channel['channel_account_id'];
|
||||
$n['uid'] = $channel['channel_id'];
|
||||
$n['item_origin'] = true;
|
||||
$n['item_type'] = $i[0]['item_type'];
|
||||
$n['parent'] = $postid;
|
||||
$n['parent_mid'] = $i[0]['mid'];
|
||||
$n['uuid'] = $uuid;
|
||||
$n['mid'] = z_root() . '/item/' . $uuid;
|
||||
$n['verb'] = 'Create';
|
||||
$n['body'] = $emoji['shortname']; //'[img class="emoji single-emoji"]' . z_root() . '/' . $emoji['filepath'] . '[/img]';
|
||||
$n['author_xchan'] = $channel['channel_hash'];
|
||||
// $n['obj'] = Activity::fetch_item(['id' => $i[0]['mid']]);
|
||||
// $n['obj_type'] = ((array_path_exists('obj/type', $n)) ? $n['obj']['type'] : EMPTY_STR);
|
||||
|
||||
$n['term'][] = [
|
||||
'uid' => $channel['channel_id'],
|
||||
'ttype' => TERM_EMOJI,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => $emoji['shortname'],
|
||||
'url' => z_root() . '/emoji/' . $shortname,
|
||||
'imgurl' => z_root() . '/' . $emoji['filepath']
|
||||
];
|
||||
|
||||
$x = item_store($n);
|
||||
|
||||
retain_item($postid);
|
||||
|
||||
if ($x['success']) {
|
||||
$nid = $x['item_id'];
|
||||
Master::Summon(['Notifier', 'like', $nid]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,15 +73,15 @@ class Search extends Controller {
|
||||
$f = Libzot::fetch_conversation(App::get_channel(), punify($url), true);
|
||||
|
||||
if ($f) {
|
||||
$mid = $f[0]['message_id'];
|
||||
$uuid = $f[0]['message_uuid'];
|
||||
foreach ($f as $m) {
|
||||
if (str_starts_with($url, $m['message_id'])) {
|
||||
$mid = $m['message_id'];
|
||||
if ($url === $m['message_id']) {
|
||||
$uuid = $m['message_uuid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/hq/' . gen_link_id($mid));
|
||||
goaway(z_root() . '/hq/' . $uuid);
|
||||
}
|
||||
else {
|
||||
// try other fetch providers (e.g. diaspora, pubcrawl)
|
||||
|
||||
@@ -491,6 +491,19 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$this->check_add($checks, t('Generate encryption keys'), $res, true, $help);
|
||||
|
||||
$res = function_exists('sodium_crypto_sign_keypair');
|
||||
if (!$res) {
|
||||
$help = t('Error: the sodium encryption library is not installed.') . EOL;
|
||||
}
|
||||
$this->check_add($checks, t('Generate ed25519 encryption keys'), $res, true, $help);
|
||||
|
||||
$res1 = extension_loaded('bcmath');
|
||||
$res2 = extension_loaded('gmp');
|
||||
if (! ($res1 || $res2)) {
|
||||
$help = t('Error: one of "bcmath" or "gmp" (bigmath library) extensions are required.') . EOL;
|
||||
}
|
||||
$this->check_add($checks, t('Bigmath library (either bcmath or gmp)'), $res1||$res2, $help);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,6 +527,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$this->check_add($ck_funcs, t('mb_string PHP module'), true, true);
|
||||
$this->check_add($ck_funcs, t('xml PHP module'), true, true);
|
||||
$this->check_add($ck_funcs, t('zip PHP module'), true, true);
|
||||
$this->check_add($ck_funcs, t('intl PHP module'), true, true);
|
||||
|
||||
if(function_exists('apache_get_modules')){
|
||||
if(! in_array('mod_rewrite', apache_get_modules())) {
|
||||
@@ -570,6 +584,10 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$ck_funcs[6]['status'] = false;
|
||||
$ck_funcs[6]['help'] = t('Error: zip PHP module required but not installed.');
|
||||
}
|
||||
if(! extension_loaded('intl')) {
|
||||
$ck_funcs[6]['status'] = false;
|
||||
$ck_funcs[6]['help'] = t('Error: intl PHP module required but not installed.');
|
||||
}
|
||||
|
||||
$checks = array_merge($checks, $ck_funcs);
|
||||
}
|
||||
|
||||
@@ -65,9 +65,7 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
|
||||
$item = $r[0];
|
||||
|
||||
$owner_uid = $r[0]['uid'];
|
||||
$owner_aid = $r[0]['aid'];
|
||||
|
||||
/*
|
||||
$can_comment = false;
|
||||
if((array_key_exists('owner',$item)) && intval($item['owner']['abook_self']))
|
||||
$can_comment = perm_is_allowed($item['uid'],$observer['xchan_hash'],'post_comments');
|
||||
@@ -78,7 +76,7 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permission denied') . EOL);
|
||||
killme();
|
||||
}
|
||||
|
||||
*/
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['owner_xchan'])
|
||||
);
|
||||
@@ -96,25 +94,39 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
$arr['aid'] = $owner_aid;
|
||||
$arr['uid'] = $owner_uid;
|
||||
$arr['aid'] = $item['aid'];
|
||||
$arr['uid'] = $item['uid'];
|
||||
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = $item['item_wall'];
|
||||
$arr['item_private'] = $item['item_private'];
|
||||
$arr['uuid'] = item_message_id();
|
||||
$arr['mid'] = z_root() . '/activity/' . $arr['uuid'];
|
||||
$arr['parent_mid'] = $item['mid'];
|
||||
$arr['parent_mid'] = $item['parent_mid'];
|
||||
$arr['thr_parent'] = $item['mid'];
|
||||
|
||||
$created = datetime_convert();
|
||||
|
||||
$arr['created'] = $created;
|
||||
$arr['edited'] = $created;
|
||||
$arr['commented'] = $created;
|
||||
$arr['received'] = $created;
|
||||
$arr['changed'] = $created;
|
||||
$arr['item_type'] = ITEM_TYPE_POST;
|
||||
|
||||
$mention = '@[zrl=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/zrl]';
|
||||
$arr['body'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, Activity::activity_obj_mapper($item['obj_type']));
|
||||
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
$arr['owner_xchan'] = $item['author_xchan'];
|
||||
$arr['obj'] = Activity::encode_item($item);
|
||||
$arr['owner_xchan'] = $item['author_xchan'];
|
||||
$arr['source_xchan'] = '';
|
||||
|
||||
$arr['obj'] = $item['obj'];
|
||||
$arr['obj_type'] = $item['obj_type'];
|
||||
$arr['verb'] = ACTIVITY_SHARE;
|
||||
|
||||
call_hooks('post_local', $arr);
|
||||
|
||||
$post = item_store($arr);
|
||||
|
||||
$post_id = $post['item_id'];
|
||||
@@ -123,7 +135,7 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
info( t('Post repeated') . EOL);
|
||||
// info( t('Post repeated') . EOL);
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
|
||||
@@ -40,7 +40,7 @@ class Sharedwithme extends Controller {
|
||||
//drop all files - localuser
|
||||
if((argc() > 1) && (argv(1) === 'dropall')) {
|
||||
|
||||
$r = q("SELECT id FROM item WHERE verb = '%s' AND obj_type IN ('Document', 'Video', 'Audio', 'Image') AND uid = %d AND owner_xchan != '%s' $item_normal",
|
||||
$r = q("SELECT id FROM item WHERE (verb = 'Create' OR verb = '%s') AND obj_type IN ('Document', 'Video', 'Audio', 'Image') AND uid = %d AND owner_xchan != '%s' $item_normal",
|
||||
dbesc(ACTIVITY_POST),
|
||||
intval(local_channel()),
|
||||
dbesc($channel['channel_hash'])
|
||||
@@ -56,7 +56,7 @@ class Sharedwithme extends Controller {
|
||||
}
|
||||
|
||||
//list files
|
||||
$r = q("SELECT id, uid, obj, item_unseen FROM item WHERE verb = '%s' AND obj_type IN ('Document', 'Video', 'Audio', 'Image') AND uid = %d AND owner_xchan != '%s' $item_normal",
|
||||
$r = q("SELECT id, uid, obj, item_unseen FROM item WHERE (verb = 'Create' OR verb = '%s') AND obj_type IN ('Document', 'Video', 'Audio', 'Image') AND uid = %d AND owner_xchan != '%s' $item_normal",
|
||||
dbesc(ACTIVITY_POST),
|
||||
intval(local_channel()),
|
||||
dbesc($channel['channel_hash'])
|
||||
|
||||
@@ -38,6 +38,8 @@ class Siteinfo extends \Zotlabs\Web\Controller {
|
||||
'$prj_srctxt' => t('Developer homepage'),
|
||||
'$prj_link' => \Zotlabs\Lib\System::get_project_link(),
|
||||
'$prj_src' => \Zotlabs\Lib\System::get_project_srclink(),
|
||||
'$addons' => array( t('Active addons'), \App::$plugins ),
|
||||
'$blocked_sites' => array( t('Blocked sites'), \Zotlabs\Lib\Config::Get('system', 'blacklisted_sites') )
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
@@ -4,18 +4,8 @@ namespace Zotlabs\Module;
|
||||
|
||||
class Smilies extends \Zotlabs\Web\Controller {
|
||||
|
||||
function get() {
|
||||
if (\App::$argv[1]==="json"){
|
||||
$tmp = list_smilies();
|
||||
$results = array();
|
||||
for($i = 0; $i < count($tmp['texts']); $i++) {
|
||||
$results[] = array('text' => $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]);
|
||||
}
|
||||
json_return_and_die($results);
|
||||
}
|
||||
else {
|
||||
return smilies('',true);
|
||||
}
|
||||
function init() {
|
||||
json_return_and_die(get_emojis());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -120,13 +120,17 @@ class Sse_bs extends Controller {
|
||||
|
||||
$mids = [];
|
||||
$str = '';
|
||||
$slice = 0;
|
||||
|
||||
$mids_all_json = Cache::get('sse_mids_all_' . session_id());
|
||||
$mids_all = isset($_SESSION['sse_mids_all']) ? unserialise($_SESSION['sse_mids_all']) : [];
|
||||
|
||||
if (!$mids_all_json)
|
||||
$mids_all_json = '[]';
|
||||
if (count($mids_all) > 3000) {
|
||||
$slice = count($mids_all) - 3000;
|
||||
}
|
||||
|
||||
$mids_all = json_decode($mids_all_json, true);
|
||||
if ($slice) {
|
||||
$mids_all = array_slice($mids_all, $slice);
|
||||
}
|
||||
|
||||
foreach($arr as $a) {
|
||||
$mid_str = '\'' . dbesc(unpack_link_id($a)) . '\'';
|
||||
@@ -137,7 +141,7 @@ class Sse_bs extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
Cache::set('sse_mids_all_' . session_id(), json_encode($mids_all));
|
||||
$_SESSION['sse_mids_all'] = serialise($mids_all);
|
||||
|
||||
if(! self::$uid) {
|
||||
return;
|
||||
@@ -149,7 +153,7 @@ class Sse_bs extends Controller {
|
||||
call_hooks('update_unseen',$x);
|
||||
|
||||
if($x['update'] === 'unset' || intval($x['update'])) {
|
||||
q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND mid in (%s) AND item_unseen = 1",
|
||||
q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND uuid in (%s) AND item_unseen = 1",
|
||||
intval(self::$uid),
|
||||
$str // this is dbesc() in the above foreach loop
|
||||
);
|
||||
@@ -177,10 +181,10 @@ class Sse_bs extends Controller {
|
||||
|
||||
$sql_extra = '';
|
||||
if (!(self::$vnotify & VNOTIFY_LIKE)) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
elseif (!feature_enabled(self::$uid, 'dislike')) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
|
||||
$sql_extra2 = '';
|
||||
@@ -189,8 +193,8 @@ class Sse_bs extends Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
// Filter FEP-5624 approvals for comments and internal follow activities
|
||||
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
// Filter internal follow activities and strerams add/remove activities
|
||||
$item_normal .= " AND verb NOT IN ('Add', 'Remove', 'Follow', 'Ignore', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
@@ -260,10 +264,10 @@ class Sse_bs extends Controller {
|
||||
|
||||
$sql_extra = '';
|
||||
if (!(self::$vnotify & VNOTIFY_LIKE)) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
elseif (!feature_enabled(self::$uid, 'dislike')) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
|
||||
$sql_extra2 = '';
|
||||
@@ -272,8 +276,8 @@ class Sse_bs extends Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
// Filter FEP-5624 approvals for comments and internal follow activities
|
||||
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
// Filter internal follow activities and strerams add/remove activities
|
||||
$item_normal .= " AND verb NOT IN ('Add', 'Remove', 'Follow', 'Ignore', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
@@ -342,10 +346,10 @@ class Sse_bs extends Controller {
|
||||
|
||||
$sql_extra = '';
|
||||
if (!(self::$vnotify & VNOTIFY_LIKE)) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
elseif (!feature_enabled(self::$uid, 'dislike')) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
|
||||
$sql_extra2 = '';
|
||||
@@ -355,8 +359,8 @@ class Sse_bs extends Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
// Filter FEP-5624 approvals for comments and internal follow activities
|
||||
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
// Filter internal follow activities and strerams add/remove activities
|
||||
$item_normal .= " AND verb NOT IN ('Add', 'Remove', 'Follow', 'Ignore', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
@@ -437,10 +441,10 @@ class Sse_bs extends Controller {
|
||||
$sys = get_sys_channel();
|
||||
$sql_extra = '';
|
||||
if (!(self::$vnotify & VNOTIFY_LIKE)) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
elseif (!feature_enabled(self::$uid, 'dislike')) {
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
|
||||
$sql_extra2 = '';
|
||||
@@ -448,10 +452,9 @@ class Sse_bs extends Controller {
|
||||
$sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
|
||||
|
||||
$sql_extra3 = '';
|
||||
$sse_mids_all_json = Cache::get('sse_mids_all_' . session_id());
|
||||
if ($sse_mids_all_json) {
|
||||
$sse_mids_all = json_decode($sse_mids_all_json, true);
|
||||
$sql_extra3 = " AND mid NOT IN (" . protect_sprintf(implode(',', $sse_mids_all)) . ") ";
|
||||
$sse_mids_all = unserialise($_SESSION['sse_mids_all']) ?? [];
|
||||
if ($sse_mids_all) {
|
||||
$sql_extra3 = " AND uuid NOT IN (" . protect_sprintf(implode(',', $sse_mids_all)) . ") ";
|
||||
}
|
||||
|
||||
$uids = " AND uid IN ( " . $sys['channel_id'] . " ) ";
|
||||
@@ -463,8 +466,8 @@ class Sse_bs extends Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
// Filter FEP-5624 approvals for comments and internal follow activities
|
||||
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
// Filter internal follow activities and strerams add/remove activities
|
||||
$item_normal .= " AND verb NOT IN ('Add', 'Remove', 'Follow', 'Ignore', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
|
||||
if ($notifications) {
|
||||
$items = q("SELECT * FROM item
|
||||
@@ -589,7 +592,7 @@ class Sse_bs extends Controller {
|
||||
|
||||
$sql_extra = '';
|
||||
if(! (self::$vnotify & VNOTIFY_LIKE))
|
||||
$sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$sql_extra = " AND verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
|
||||
$fcount = count($forums);
|
||||
$i = 0;
|
||||
@@ -659,12 +662,11 @@ class Sse_bs extends Controller {
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
// Filter FEP-5624 approvals for comments and internal follow activities
|
||||
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
|
||||
// Filter internal follow activities and strerams add/remove activities
|
||||
$item_normal .= " AND verb NOT IN ('Add', 'Remove', 'Follow', 'Ignore', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
|
||||
|
||||
$r = q("SELECT * FROM item
|
||||
WHERE verb = '%s'
|
||||
WHERE (verb = 'Create' OR verb = '%s')
|
||||
AND obj_type IN ('Document', 'Video', 'Audio', 'Image')
|
||||
AND uid = %d
|
||||
AND author_xchan != '%s'
|
||||
|
||||
@@ -24,9 +24,9 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
$item_id = ((argc() > 2) ? notags(trim(argv(2))) : 0);
|
||||
|
||||
if(argv(1) === 'sub')
|
||||
$activity = ACTIVITY_FOLLOW;
|
||||
$activity = 'Follow';
|
||||
elseif(argv(1) === 'unsub')
|
||||
$activity = ACTIVITY_UNFOLLOW;
|
||||
$activity = 'Ignore';
|
||||
|
||||
|
||||
$i = q("select * from item where id = %d and uid = %d",
|
||||
@@ -106,16 +106,13 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
killme();
|
||||
|
||||
|
||||
|
||||
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
|
||||
$objtype = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
|
||||
$objtype = (($item['resource_type'] === 'photo') ? 'Image' : 'Note');
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
@@ -124,9 +121,9 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
if(! intval($item['item_thread_top']))
|
||||
$post_type = 'comment';
|
||||
|
||||
if($activity === ACTIVITY_FOLLOW)
|
||||
if($activity === 'Follow')
|
||||
$bodyverb = t('%1$s is following %2$s\'s %3$s');
|
||||
if($activity === ACTIVITY_UNFOLLOW)
|
||||
if($activity === 'Ignore')
|
||||
$bodyverb = t('%1$s stopped following %2$s\'s %3$s');
|
||||
|
||||
$arr = array();
|
||||
@@ -149,7 +146,7 @@ class Subthread extends \Zotlabs\Web\Controller {
|
||||
|
||||
$ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
|
||||
$alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . gen_link_id($item['mid']) . ']' . $post_type . '[/zrl]';
|
||||
$plink = '[zrl=' . z_root() . '/display/' . $item['uuid'] . ']' . $post_type . '[/zrl]';
|
||||
|
||||
$arr['body'] = sprintf( $bodyverb, $alink, $ulink, $plink );
|
||||
|
||||
|
||||
@@ -67,15 +67,15 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
|
||||
switch($item['resource_type']) {
|
||||
case 'photo':
|
||||
$targettype = ACTIVITY_OBJ_PHOTO;
|
||||
$targettype = 'Image';
|
||||
$post_type = t('photo');
|
||||
break;
|
||||
case 'event':
|
||||
$targettype = ACTIVITY_OBJ_EVENT;
|
||||
$targettype = 'Event';
|
||||
$post_type = t('event');
|
||||
break;
|
||||
default:
|
||||
$targettype = ACTIVITY_OBJ_NOTE;
|
||||
$targettype = 'Note';
|
||||
$post_type = t('post');
|
||||
if($item['mid'] != $item['parent_mid'])
|
||||
$post_type = t('comment');
|
||||
@@ -86,7 +86,7 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
$clean_term = trim($term,'"\' ');
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html',
|
||||
'href' => z_root() . '/display/' . gen_link_id($item['mid'])));
|
||||
'href' => z_root() . '/display/' . $item['uuid']));
|
||||
|
||||
$target = json_encode(array(
|
||||
'type' => $targettype,
|
||||
|
||||
@@ -5,28 +5,51 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
require_once('include/items.php');
|
||||
require_once('include/security.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
|
||||
class Thing extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
if (argv(1) && ActivityStreams::is_as_request()) {
|
||||
$r = q("select obj_channel from obj where obj_type = %d and obj_obj = '%s' limit 1",
|
||||
intval(TERM_OBJ_THING),
|
||||
dbesc(argv(1))
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$sql_extra = permissions_sql($r[0]['obj_channel']);
|
||||
|
||||
$r = q("select * from obj where obj_type = %d and obj_obj = '%s' $sql_extra limit 1",
|
||||
intval(TERM_OBJ_THING),
|
||||
dbesc(argv(1))
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$channel = channelx_by_n($r[0]['obj_channel']);
|
||||
as_return_and_die(Activity::fetch_thing(['id' => $r[0]['obj_obj']]), $channel);
|
||||
}
|
||||
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function post() {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
if($_SERVER['REQUEST_METHOD'] === 'GET' && argc() < 2) {
|
||||
profile_load($channel['channel_address']);
|
||||
}
|
||||
|
||||
|
||||
$term_hash = (($_REQUEST['term_hash']) ? $_REQUEST['term_hash'] : '');
|
||||
|
||||
$name = escape_tags($_REQUEST['term']);
|
||||
@@ -36,7 +59,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
$url = $_REQUEST['url'];
|
||||
$photo = $_REQUEST['img'];
|
||||
|
||||
$hash = random_string();
|
||||
$hash = new_uuid();
|
||||
|
||||
$verbs = obj_verbs();
|
||||
|
||||
@@ -77,13 +100,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
|
||||
if(array_key_exists('contact_allow',$_REQUEST)
|
||||
|| array_key_exists('group_allow',$_REQUEST)
|
||||
|| array_key_exists('contact_deny',$_REQUEST)
|
||||
|| array_key_exists('group_deny',$_REQUEST)) {
|
||||
$acl->set_from_array($_REQUEST);
|
||||
}
|
||||
$acl->set_from_array($_REQUEST);
|
||||
|
||||
$x = $acl->get();
|
||||
|
||||
@@ -181,28 +198,20 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
intval(local_channel()),
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
Libsync::build_sync_packet(0, array('obj' => $r));
|
||||
}
|
||||
|
||||
if($activity) {
|
||||
$arr = array();
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $url));
|
||||
if($local_photo)
|
||||
$links[] = array('rel' => 'photo', 'type' => $local_photo_type, 'href' => $local_photo);
|
||||
|
||||
$objtype = ACTIVITY_OBJ_THING;
|
||||
|
||||
$obj = json_encode(array(
|
||||
'type' => $objtype,
|
||||
'id' => $url,
|
||||
'link' => $links,
|
||||
'title' => $name,
|
||||
'content' => $name
|
||||
));
|
||||
$obj = Activity::fetch_thing(['id' => $r[0]['obj_obj']]);
|
||||
|
||||
$bodyverb = str_replace('OBJ: ', '',t('OBJ: %1$s %2$s %3$s'));
|
||||
|
||||
$arr['uuid'] = $r[0]['obj_obj'];
|
||||
$arr['mid'] = z_root() . '/thing/' . $arr['uuid'];
|
||||
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
|
||||
@@ -213,29 +222,38 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
$ulink = '[zrl=' . $channel['xchan_url'] . ']' . $channel['channel_name'] . '[/zrl]';
|
||||
$plink = '[zrl=' . $url . ']' . $name . '[/zrl]';
|
||||
|
||||
$arr['body'] = sprintf( $bodyverb, $ulink, $translated_verb, $plink );
|
||||
$arr['title'] = $channel['channel_name'] . ' ' . $translated_verb . ' ' . $name;
|
||||
$arr['body'] = $url;
|
||||
|
||||
if($local_photo)
|
||||
$arr['body'] .= "\n\n[zmg]" . $local_photo . "[/zmg]";
|
||||
$arr['body'] = '[zrl=' . $url . '][zmg=' . $local_photo . ']' . $name . '[/zmg][/zrl]';
|
||||
|
||||
$arr['verb'] = $verb;
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['verb'] = 'Create';
|
||||
$arr['obj_type'] = 'Page';
|
||||
$arr['obj'] = $obj;
|
||||
|
||||
if(! $profile['is_default']) {
|
||||
$arr['allow_cid'] = $x['allow_cid'];
|
||||
$arr['allow_gid'] = $x['allow_gid'];
|
||||
$arr['deny_cid'] = $x['deny_cid'];
|
||||
$arr['deny_gid'] = $x['deny_gid'];
|
||||
|
||||
if (!$profile['is_default']) {
|
||||
$arr['item_private'] = true;
|
||||
$str = '';
|
||||
|
||||
$r = q("select abook_xchan from abook where abook_channel = %d and abook_profile = '%s'",
|
||||
intval(local_channel()),
|
||||
dbesc($profile_guid)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$arr['allow_cid'] = '';
|
||||
foreach($r as $rr)
|
||||
foreach($r as $rr) {
|
||||
$arr['allow_cid'] .= '<' . $rr['abook_xchan'] . '>';
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
$arr['allow_cid'] = '<' . get_observer_hash() . '>';
|
||||
}
|
||||
}
|
||||
|
||||
$ret = post_activity_item($arr);
|
||||
@@ -254,21 +272,30 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
intval(TERM_OBJ_THING),
|
||||
dbesc(argv(1))
|
||||
);
|
||||
if($r)
|
||||
$sql_extra = permissions_sql($r[0]['obj_channel']);
|
||||
|
||||
if (!$r) {
|
||||
notice( t('item not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$sql_extra = permissions_sql($r[0]['obj_channel']);
|
||||
|
||||
$r = q("select * from obj where obj_type = %d and obj_obj = '%s' $sql_extra limit 1",
|
||||
intval(TERM_OBJ_THING),
|
||||
dbesc(argv(1))
|
||||
);
|
||||
|
||||
if($r) {
|
||||
if ($r) {
|
||||
$channel = channelx_by_n($r[0]['obj_channel']);
|
||||
profile_load($channel['channel_address']);
|
||||
|
||||
return replace_macros(get_markup_template('show_thing.tpl'), array(
|
||||
'$header' => t('Show Thing'),
|
||||
'$header' => $channel['xchan_name'] . ' ' . $r[0]['obj_verb'] . ' ' . $r[0]['obj_term'],
|
||||
'$edit' => t('Edit'),
|
||||
'$delete' => t('Delete'),
|
||||
'$canedit' => ((local_channel() && local_channel() == $r[0]['obj_channel']) ? true : false),
|
||||
'$thing' => $r[0] ));
|
||||
'$thing' => $r[0]
|
||||
));
|
||||
}
|
||||
else {
|
||||
notice( t('item not found.') . EOL);
|
||||
@@ -283,6 +310,8 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
profile_load($channel['channel_address']);
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$channel_acl = $acl->get();
|
||||
|
||||
@@ -319,7 +348,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
'$img_lbl' => t('URL for photo of thing (optional)'),
|
||||
'$imgurl' => $r[0]['obj_imgurl'],
|
||||
'$permissions' => t('Permissions'),
|
||||
'$aclselect' => populate_acl($channel_acl,false),
|
||||
'$aclselect' => populate_acl($channel_acl, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
|
||||
'$allow_cid' => acl2json($channel_acl['allow_cid']),
|
||||
'$allow_gid' => acl2json($channel_acl['allow_gid']),
|
||||
'$deny_cid' => acl2json($channel_acl['deny_cid']),
|
||||
@@ -344,7 +373,6 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
delete_thing_photo($r[0]['obj_imgurl'],get_observer_hash());
|
||||
|
||||
$x = q("delete from obj where obj_obj = '%s' and obj_type = %d and obj_channel = %d",
|
||||
@@ -372,7 +400,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
'$url_lbl' => t('URL of thing (optional)'),
|
||||
'$img_lbl' => t('URL for photo of thing (optional)'),
|
||||
'$permissions' => t('Permissions'),
|
||||
'$aclselect' => populate_acl($channel_acl,false),
|
||||
'$aclselect' => populate_acl($channel_acl, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
|
||||
'$allow_cid' => acl2json($channel_acl['allow_cid']),
|
||||
'$allow_gid' => acl2json($channel_acl['allow_gid']),
|
||||
'$deny_cid' => acl2json($channel_acl['deny_cid']),
|
||||
|
||||
@@ -98,7 +98,7 @@ class Vote extends Controller {
|
||||
|
||||
// now reset the placeholders
|
||||
|
||||
$item['verb'] = ACTIVITY_POST;
|
||||
$item['verb'] = 'Create';
|
||||
$item['obj_type'] = 'Answer';
|
||||
unset($item['author']);
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ class PhotoGd extends PhotoDriver {
|
||||
$t = [];
|
||||
|
||||
$t['image/jpeg'] = 'jpg';
|
||||
if(imagetypes() & IMG_PNG)
|
||||
if(\imagetypes() & IMG_PNG)
|
||||
$t['image/png'] = 'png';
|
||||
if(imagetypes() & IMG_GIF)
|
||||
if(\imagetypes() & IMG_GIF)
|
||||
$t['image/gif'] = 'gif';
|
||||
if(imagetypes() & IMG_WEBP)
|
||||
if(\imagetypes() & IMG_WEBP)
|
||||
$t['image/webp'] = 'webp';
|
||||
|
||||
return $t;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Zotlabs\Render;
|
||||
|
||||
use App;
|
||||
|
||||
use Zotlabs\Lib\PConfig;
|
||||
|
||||
class Theme {
|
||||
|
||||
@@ -26,8 +26,8 @@ class Theme {
|
||||
*/
|
||||
static public function current(){
|
||||
|
||||
self::$system_theme = ((isset(\App::$config['system']['theme']))
|
||||
? \App::$config['system']['theme'] : '');
|
||||
self::$system_theme = ((isset(App::$config['system']['theme']))
|
||||
? App::$config['system']['theme'] : '');
|
||||
self::$session_theme = ((isset($_SESSION) && x($_SESSION, 'theme'))
|
||||
? $_SESSION['theme'] : self::$system_theme);
|
||||
|
||||
@@ -35,7 +35,7 @@ class Theme {
|
||||
|
||||
// Find the theme that belongs to the channel whose stuff we are looking at
|
||||
|
||||
if(\App::$profile_uid) {
|
||||
if(App::$profile_uid) {
|
||||
$r = q("select channel_theme from channel where channel_id = %d limit 1",
|
||||
intval(\App::$profile_uid)
|
||||
);
|
||||
@@ -46,8 +46,9 @@ class Theme {
|
||||
|
||||
// Themes from Comanche layouts over-ride the channel theme
|
||||
|
||||
if(array_key_exists('theme', \App::$layout) && \App::$layout['theme'])
|
||||
$page_theme = \App::$layout['theme'];
|
||||
if(array_key_exists('theme', \App::$layout) && \App::$layout['theme']) {
|
||||
$page_theme = App::$layout['theme'];
|
||||
}
|
||||
|
||||
$chosen_theme = self::$session_theme;
|
||||
|
||||
@@ -96,14 +97,11 @@ class Theme {
|
||||
*
|
||||
* Provide a sane default if nothing is chosen or the specified theme does not exist.
|
||||
*
|
||||
* @param bool $installing (optional) default false, if true return the name of the first base theme
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function url($installing = false) {
|
||||
static public function url() {
|
||||
|
||||
if($installing)
|
||||
return self::$base_themes[0];
|
||||
$uid = App::$profile_uid ?: local_channel();
|
||||
|
||||
$theme = self::current();
|
||||
|
||||
@@ -111,16 +109,23 @@ class Theme {
|
||||
$s = ((count($theme) > 1) ? $theme[1] : '');
|
||||
|
||||
$opts = '';
|
||||
$opts = ((\App::$profile_uid) ? '?f=&puid=' . \App::$profile_uid : '');
|
||||
$opts = (($uid) ? '?puid=' . $uid : '');
|
||||
|
||||
$schema_str = ((x(\App::$layout,'schema')) ? '&schema=' . App::$layout['schema'] : '');
|
||||
$schema_str = ((x(App::$layout,'schema')) ? '&schema=' . App::$layout['schema'] : '');
|
||||
if(($s) && (! $schema_str))
|
||||
$schema_str = '&schema=' . $s;
|
||||
|
||||
$opts .= $schema_str;
|
||||
|
||||
if ($uid) {
|
||||
$timestamp = PConfig::Get($uid, 'system', 'style_update', false);
|
||||
if ($timestamp) {
|
||||
$opts .= '&updt=' . $timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
if(file_exists('view/theme/' . $t . '/php/style.php'))
|
||||
return('/view/theme/' . $t . '/php/style.pcss' . $opts);
|
||||
return('/view/theme/' . $t . '/php/style.css' . $opts);
|
||||
|
||||
return('/view/theme/' . $t . '/css/style.css');
|
||||
}
|
||||
|
||||
@@ -34,6 +34,14 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
* @var int $channel_id
|
||||
*/
|
||||
public $channel_id = 0;
|
||||
|
||||
/**
|
||||
* @brief channel_account_id of the current channel of the logged-in account.
|
||||
*
|
||||
* @var int $channel_account_id
|
||||
*/
|
||||
public $channel_account_id = 0;
|
||||
|
||||
/**
|
||||
* @brief channel_hash of the current channel of the logged-in account.
|
||||
*
|
||||
@@ -127,6 +135,7 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
*/
|
||||
protected function setAuthenticated($channel) {
|
||||
$this->channel_name = $channel['channel_address'];
|
||||
$this->channel_account_id = $channel['channel_account_id'];
|
||||
$this->channel_id = $channel['channel_id'];
|
||||
$this->channel_hash = $this->observer = $channel['channel_hash'];
|
||||
|
||||
@@ -139,8 +148,8 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
|
||||
}
|
||||
}
|
||||
|
||||
$_SESSION['uid'] = $channel['channel_id'];
|
||||
$_SESSION['account_id'] = $channel['channel_account_id'];
|
||||
$_SESSION['uid'] = $this->channel_id;
|
||||
$_SESSION['account_id'] = $this->channel_account_id;
|
||||
$_SESSION['authenticated'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
intval($this->auth->owner_id)
|
||||
);
|
||||
|
||||
$x = attach_syspaths($this->auth->owner_id,$this->folder_hash);
|
||||
$x = attach_syspaths($this->auth->owner_id, $this->folder_hash);
|
||||
|
||||
$y = q("update attach set display_path = '%s' where hash = '%s' and uid = %d",
|
||||
dbesc($x['path']),
|
||||
@@ -181,6 +181,20 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
intval($this->auth->owner_id)
|
||||
);
|
||||
|
||||
$z = q("select hash from attach where folder = '%s' and uid = %d",
|
||||
dbesc($this->folder_hash),
|
||||
intval($this->auth->owner_id)
|
||||
);
|
||||
|
||||
if($z) {
|
||||
foreach ($z as $zz) {
|
||||
$rs = attach_move($this->auth->owner_id, $zz['hash'], $this->folder_hash, '', false);
|
||||
if(!$rs['success']) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ch = channelx_by_n($this->auth->owner_id);
|
||||
if ($ch) {
|
||||
$sync = attach_export_data($ch, $this->folder_hash);
|
||||
@@ -481,7 +495,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
}
|
||||
|
||||
|
||||
public function moveInto($targetName,$sourcePath, DAV\INode $sourceNode) {
|
||||
public function moveInto($targetName, $sourcePath, DAV\INode $sourceNode) {
|
||||
|
||||
$channel_id = $this->auth->owner_id;
|
||||
// Files have $sourceNode->data['hash'] set. For directories rely on $sourceNode->folder_hash.
|
||||
|
||||
@@ -38,6 +38,8 @@ class File extends DAV\Node implements DAV\IFile {
|
||||
*/
|
||||
private $name;
|
||||
|
||||
public $os_path;
|
||||
public $folder_hash;
|
||||
|
||||
/**
|
||||
* Sets up the node, expects a full path name.
|
||||
|
||||
@@ -24,7 +24,7 @@ class Tagadelic {
|
||||
$x ++;
|
||||
}
|
||||
|
||||
usort($tags,'self::tags_sort');
|
||||
usort($tags, [self::class, 'tags_sort']);
|
||||
|
||||
$range = max(.01, $max - $min) * 1.0001;
|
||||
|
||||
@@ -41,4 +41,4 @@ class Tagadelic {
|
||||
return((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
58
Zotlabs/Update/_1260.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1260 {
|
||||
public function run() {
|
||||
|
||||
$has_sodium = function_exists('sodium_crypto_sign_keypair');
|
||||
$has_bcmath = function_exists('bcadd');
|
||||
$has_gmp = function_exists('gmp_add');
|
||||
|
||||
if (!$has_sodium) {
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
if (!($has_gmp || $has_bcmath)) {
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = dbq("ALTER TABLE channel ADD channel_epubkey text NOT NULL DEFAULT ''");
|
||||
$r2 = dbq("ALTER TABLE channel ADD channel_eprvkey text NOT NULL DEFAULT ''");
|
||||
}
|
||||
else {
|
||||
$r1 = dbq("ALTER TABLE channel ADD channel_epubkey text NOT NULL");
|
||||
$r2 = dbq("ALTER TABLE channel ADD channel_eprvkey text NOT NULL");
|
||||
}
|
||||
|
||||
$channels = dbq("select channel_id from channel where true");
|
||||
if ($channels) {
|
||||
foreach ($channels as $channel) {
|
||||
$keys = sodium_crypto_sign_keypair();
|
||||
$pubkey = sodium_bin2base64(sodium_crypto_sign_publickey($keys), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
$prvkey = sodium_bin2base64(sodium_crypto_sign_secretkey($keys), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
|
||||
q("update channel set channel_epubkey = '%s', channel_eprvkey = '%s' where channel_id = %d",
|
||||
dbesc($pubkey),
|
||||
dbesc($prvkey),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($r1 && $r2) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
public function verify() {
|
||||
$columns = db_columns('channel');
|
||||
return in_array('channel_epubkey', $columns) && in_array('channel_eprvkey', $columns);
|
||||
}
|
||||
}
|
||||
|
||||
58
Zotlabs/Update/_1261.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
use Zotlabs\Lib\Multibase;
|
||||
|
||||
class _1261 {
|
||||
public function run() {
|
||||
|
||||
$has_sodium = function_exists('sodium_crypto_sign_keypair');
|
||||
$has_bcmath = function_exists('bcadd');
|
||||
$has_gmp = function_exists('gmp_add');
|
||||
|
||||
if (!$has_sodium) {
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
if (!($has_gmp || $has_bcmath)) {
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = dbq("ALTER TABLE xchan ADD xchan_epubkey text NOT NULL DEFAULT ''");
|
||||
$r2 = dbq("ALTER TABLE xchan ADD xchan_updated timestamp NOT NULL DEFAULT '0001-01-01 00:00:00'");
|
||||
}
|
||||
else {
|
||||
$r1 = dbq("ALTER TABLE xchan ADD xchan_epubkey text NOT NULL");
|
||||
$r2 = dbq("ALTER TABLE xchan ADD xchan_updated datetime NOT NULL DEFAULT '0001-01-01 00:00:00'");
|
||||
}
|
||||
|
||||
$channels = dbq("select * from channel where true");
|
||||
if ($channels) {
|
||||
foreach ($channels as $channel) {
|
||||
$epubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
q("update xchan set xchan_epubkey = '%s' where xchan_url = '%s'",
|
||||
dbesc($epubkey),
|
||||
dbesc(channel_url($channel))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($r1 && $r2) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
public function verify() {
|
||||
$columns = db_columns('xchan');
|
||||
return in_array('xchan_epubkey', $columns) && in_array('xchan_updated', $columns);
|
||||
}
|
||||
}
|
||||
|
||||
30
Zotlabs/Update/_1262.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1262 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r = true;
|
||||
}
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
|
||||
$r = dbq("ALTER TABLE session MODIFY COLUMN sess_data MEDIUMTEXT NOT NULL");
|
||||
}
|
||||
|
||||
if($r) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
q("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
26
Zotlabs/Update/_1263.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1263 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
$poke = hash('whirlpool', 'Poke');
|
||||
$mood = hash('whirlpool', 'Mood');
|
||||
|
||||
$r = dbq("DELETE FROM app WHERE (app_id = '$poke' OR app_id = '$mood') AND app_system = 1");
|
||||
|
||||
if($r) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,9 +27,12 @@ class HTTPSig {
|
||||
* @param string $alg hash algorithm (one of 'sha256','sha512')
|
||||
* @return string The generated digest header string for $body
|
||||
*/
|
||||
|
||||
static function generate_digest_header($body, $alg = 'sha256') {
|
||||
|
||||
if ($body === null) {
|
||||
$body = '';
|
||||
}
|
||||
|
||||
$digest = base64_encode(hash($alg, $body, true));
|
||||
switch ($alg) {
|
||||
case 'sha512':
|
||||
@@ -41,37 +44,42 @@ class HTTPSig {
|
||||
}
|
||||
}
|
||||
|
||||
static function find_headers($data, &$body) {
|
||||
public static function find_headers($data, &$body) {
|
||||
|
||||
// decide if $data arrived via controller submission or curl
|
||||
// changes $body for the caller
|
||||
|
||||
if (is_array($data) && $data['header']) {
|
||||
if (!$data['success'])
|
||||
if (is_array($data) && array_key_exists('header', $data)) {
|
||||
if (!$data['success']) {
|
||||
$body = EMPTY_STR;
|
||||
return [];
|
||||
}
|
||||
|
||||
$h = new HTTPHeaders($data['header']);
|
||||
$headers = $h->fetcharr();
|
||||
$body = $data['body'];
|
||||
if (!$data['header']) {
|
||||
$body = EMPTY_STR;
|
||||
return [];
|
||||
}
|
||||
|
||||
$h = new HTTPHeaders($data['header']);
|
||||
$headers = $h->fetcharr();
|
||||
$body = $data['body'];
|
||||
$headers['(request-target)'] = $data['request_target'];
|
||||
}
|
||||
|
||||
else {
|
||||
$headers = [];
|
||||
} else {
|
||||
$headers = [];
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$headers['content-type'] = $_SERVER['CONTENT_TYPE'];
|
||||
$headers['content-length'] = $_SERVER['CONTENT_LENGTH'];
|
||||
$headers['content-type'] = $_SERVER['CONTENT_TYPE'];
|
||||
$headers['content-length'] = $_SERVER['CONTENT_LENGTH'];
|
||||
|
||||
foreach ($_SERVER as $k => $v) {
|
||||
if (strpos($k, 'HTTP_') === 0) {
|
||||
$field = str_replace('_', '-', strtolower(substr($k, 5)));
|
||||
$field = str_replace('_', '-', strtolower(substr($k, 5)));
|
||||
$headers[$field] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//logger('SERVER: ' . print_r($_SERVER,true), LOGGER_ALL);
|
||||
|
||||
//logger('headers: ' . print_r($headers,true), LOGGER_ALL);
|
||||
//logger('found_headers: ' . print_r($headers,true), LOGGER_ALL);
|
||||
|
||||
return $headers;
|
||||
}
|
||||
@@ -99,6 +107,10 @@ class HTTPSig {
|
||||
if (!$headers)
|
||||
return $result;
|
||||
|
||||
if (is_array($body)) {
|
||||
btlogger('body is array:' . print_r($body, true));
|
||||
}
|
||||
|
||||
$sig_block = null;
|
||||
|
||||
if (array_key_exists('signature', $headers)) {
|
||||
@@ -214,8 +226,10 @@ class HTTPSig {
|
||||
$result['content_signed'] = true;
|
||||
$digest = explode('=', $headers['digest'], 2);
|
||||
$digest[0] = strtoupper($digest[0]);
|
||||
|
||||
if ($digest[0] === 'SHA-256')
|
||||
$hashalg = 'sha256';
|
||||
|
||||
if ($digest[0] === 'SHA-512')
|
||||
$hashalg = 'sha512';
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ class Messages {
|
||||
|
||||
$channel = App::get_channel();
|
||||
$item_normal = item_normal();
|
||||
$item_normal .= " and item.verb != '" . ACTIVITY_FOLLOW . "'";
|
||||
// Filter internal follow activities and strerams add/remove activities
|
||||
$item_normal .= " and item.verb not in ('Add', 'Remove', 'Follow', 'Ignore', '" . ACTIVITY_FOLLOW . "') ";
|
||||
$item_normal_i = str_replace('item.', 'i.', $item_normal);
|
||||
$item_normal_c = str_replace('item.', 'c.', $item_normal);
|
||||
$entries = [];
|
||||
@@ -75,16 +76,16 @@ class Messages {
|
||||
$vnotify_sql_i = '';
|
||||
|
||||
if (!($vnotify & VNOTIFY_LIKE)) {
|
||||
$vnotify_sql_c = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$vnotify_sql_i = " AND i.verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$vnotify_sql_c = " AND c.verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$vnotify_sql_i = " AND i.verb NOT IN ('Like', 'Dislike', '" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
elseif (!feature_enabled(local_channel(), 'dislike')) {
|
||||
$vnotify_sql_c = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$vnotify_sql_i = " AND i.verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$vnotify_sql_c = " AND c.verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
$vnotify_sql_i = " AND i.verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
|
||||
}
|
||||
|
||||
if($author) {
|
||||
$author_sql = " AND i.owner_xchan = '" . protect_sprintf(dbesc($author)) . "' ";
|
||||
$author_sql = " AND (i.owner_xchan = '" . protect_sprintf(dbesc($author)) . "') ";
|
||||
}
|
||||
|
||||
switch($type) {
|
||||
@@ -101,11 +102,8 @@ class Messages {
|
||||
$type_sql = ' AND i.item_private IN (0, 1) ';
|
||||
}
|
||||
|
||||
// FEP-5624 filter approvals for comments
|
||||
$approvals_c = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
|
||||
|
||||
$items = q("SELECT *,
|
||||
(SELECT count(*) FROM item c WHERE c.uid = %d AND c.parent = i.parent AND c.item_unseen = 1 AND c.item_thread_top = 0 $item_normal_c $approvals_c $vnotify_sql_c) AS unseen_count
|
||||
(SELECT count(*) FROM item c WHERE c.uid = %d AND c.parent = i.parent AND c.item_unseen = 1 AND c.item_thread_top = 0 $item_normal_c $vnotify_sql_c) AS unseen_count
|
||||
FROM item i WHERE i.uid = %d
|
||||
AND i.created <= '%s'
|
||||
$type_sql
|
||||
@@ -147,6 +145,9 @@ class Messages {
|
||||
if($item['owner_xchan'] !== $item['author_xchan']) {
|
||||
$info .= t('via') . ' ' . $item['owner']['xchan_name'];
|
||||
}
|
||||
elseif($item['verb'] === 'Announce' && isset($item['source'])) {
|
||||
$info .= t('via') . ' ' . $item['source']['xchan_name'];
|
||||
}
|
||||
|
||||
$summary = $item['title'];
|
||||
if (!$summary) {
|
||||
@@ -184,8 +185,9 @@ class Messages {
|
||||
$entries[$i]['info'] = $info;
|
||||
$entries[$i]['created'] = datetime_convert('UTC', date_default_timezone_get(), $item['created']);
|
||||
$entries[$i]['summary'] = $summary;
|
||||
$entries[$i]['b64mid'] = gen_link_id($item['mid']);
|
||||
$entries[$i]['href'] = z_root() . '/hq/' . gen_link_id($item['mid']);
|
||||
//$entries[$i]['b64mid'] = gen_link_id($item['mid']);
|
||||
$entries[$i]['b64mid'] = $item['uuid'];
|
||||
$entries[$i]['href'] = z_root() . '/hq/' . $item['uuid'];
|
||||
$entries[$i]['icon'] = $icon;
|
||||
$entries[$i]['unseen_count'] = (($item['unseen_count']) ? $item['unseen_count'] : (($item['item_unseen']) ? ' ' : ''));
|
||||
$entries[$i]['unseen_class'] = (($item['item_unseen']) ? 'primary' : 'secondary');
|
||||
@@ -289,8 +291,8 @@ class Messages {
|
||||
$entries[$i]['info'] = '';
|
||||
$entries[$i]['created'] = datetime_convert('UTC', date_default_timezone_get(), $notice['created']);
|
||||
$entries[$i]['summary'] = $summary;
|
||||
$entries[$i]['b64mid'] = (($notice['ntype'] & NOTIFY_INTRO) ? '' : basename($notice['link']));
|
||||
$entries[$i]['href'] = (($notice['ntype'] & NOTIFY_INTRO) ? $notice['link'] : z_root() . '/hq/' . basename($notice['link']));
|
||||
$entries[$i]['b64mid'] = (($notice['ntype'] & NOTIFY_INTRO) ? '' : ((str_contains($notice['hash'], '-')) ? $notice['hash'] : basename($notice['link'])));
|
||||
$entries[$i]['href'] = (($notice['ntype'] & NOTIFY_INTRO) ? $notice['link'] : z_root() . '/hq/' . ((str_contains($notice['hash'], '-')) ? $notice['hash'] : basename($notice['link'])));
|
||||
$entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="fa fa-user-plus"></i>' : '');
|
||||
|
||||
$i++;
|
||||
|
||||
@@ -46,7 +46,7 @@ class Pinned {
|
||||
|
||||
foreach($items as $item) {
|
||||
|
||||
$midb64 = gen_link_id($item['mid']);
|
||||
$midb64 = $item['uuid'];
|
||||
|
||||
if(isset($observer['xchan_hash']) && in_array($observer['xchan_hash'], get_pconfig($item['uid'], 'pinned_hide', $midb64, [])))
|
||||
continue;
|
||||
@@ -77,17 +77,6 @@ class Pinned {
|
||||
}
|
||||
}
|
||||
|
||||
$consensus = (intval($item['item_consensus']) ? true : false);
|
||||
if($consensus) {
|
||||
$conv_responses['agree'] = [ 'title' => t('Agree','title') ];
|
||||
$conv_responses['disagree'] = [ 'title' => t('Disagree','title') ];
|
||||
$conv_responses['abstain'] = [ 'title' => t('Abstain','title') ];
|
||||
if($commentable && $observer) {
|
||||
$conlabels = [ t('I agree'), t('I disagree'), t('I abstain') ];
|
||||
$canvote = true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->activity($item, $conv_responses);
|
||||
|
||||
$verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
|
||||
@@ -203,7 +192,7 @@ class Pinned {
|
||||
if(empty($mids_list))
|
||||
return [];
|
||||
|
||||
$r = q("SELECT * FROM item WHERE mid IN ( '%s' ) AND uid = %d AND id = parent AND item_private = 0 ORDER BY created DESC",
|
||||
$r = q("SELECT * FROM item WHERE uuid IN ( '%s' ) AND uid = %d AND id = parent AND item_private = 0 ORDER BY created DESC",
|
||||
dbesc(implode(",", $mids_list)),
|
||||
intval($this->uid)
|
||||
);
|
||||
@@ -225,39 +214,30 @@ class Pinned {
|
||||
private function activity($item, &$conv_responses) {
|
||||
|
||||
foreach(array_keys($conv_responses) as $verb) {
|
||||
$verb_sql = '';
|
||||
|
||||
switch($verb) {
|
||||
case 'like':
|
||||
$v = ACTIVITY_LIKE;
|
||||
$verb_sql = " AND verb IN ('Like', '" . ACTIVITY_LIKE . "') ";
|
||||
break;
|
||||
case 'dislike':
|
||||
$v = ACTIVITY_DISLIKE;
|
||||
break;
|
||||
case 'agree':
|
||||
$v = ACTIVITY_AGREE;
|
||||
break;
|
||||
case 'disagree':
|
||||
$v = ACTIVITY_DISAGREE;
|
||||
break;
|
||||
case 'abstain':
|
||||
$v = ACTIVITY_ABSTAIN;
|
||||
$verb_sql = " AND verb IN ('Dislike', '" . ACTIVITY_DISLIKE . "') ";
|
||||
break;
|
||||
case 'attendyes':
|
||||
$v = ACTIVITY_ATTEND;
|
||||
$verb_sql = " AND verb IN ('Accept', '" . ACTIVITY_ATTEND . "') ";
|
||||
break;
|
||||
case 'attendno':
|
||||
$v = ACTIVITY_ATTENDNO;
|
||||
$verb_sql = " AND verb IN ('Reject', '" . ACTIVITY_ATTENDNO . "') ";
|
||||
break;
|
||||
case 'attendmaybe':
|
||||
$v = ACTIVITY_ATTENDMAYBE;
|
||||
$verb_sql = " AND verb IN ('TentativeAccept', '" . ACTIVITY_ATTENDMAYBE . "') ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM item WHERE parent = %d AND id <> parent AND verb = '%s' AND item_deleted = 0",
|
||||
intval($item['id']),
|
||||
dbesc($v)
|
||||
$r = q("SELECT * FROM item WHERE parent = %d AND id <> parent $verb_sql AND item_deleted = 0",
|
||||
intval($item['id'])
|
||||
);
|
||||
if(! $r) {
|
||||
unset($conv_responses[$verb]);
|
||||
|
||||
@@ -22,6 +22,7 @@ class Receiver {
|
||||
protected $prvkey;
|
||||
protected $rawdata;
|
||||
protected $sigdata;
|
||||
protected $hub;
|
||||
|
||||
function __construct($handler, $localdata = null) {
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
version: 3
|
||||
url: $baseurl/mood
|
||||
requires: local_channel
|
||||
name: Mood
|
||||
photo: icon:smile-o
|
||||
categories: Social
|
||||
desc: Set your current mood and tell your friends.
|
||||
@@ -1,7 +0,0 @@
|
||||
version: 3
|
||||
url: $baseurl/poke
|
||||
requires: local_channel
|
||||
name: Poke
|
||||
photo: icon:hand-o-right
|
||||
categories: Social
|
||||
desc: Poke somebody in your addressbook.
|
||||
116
boot.php
@@ -58,12 +58,16 @@ require_once('include/hubloc.php');
|
||||
require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/conversation.php');
|
||||
require_once('include/acl_selectors.php');
|
||||
require_once('include/selectors.php');
|
||||
require_once('include/activities.php');
|
||||
|
||||
define('PLATFORM_NAME', 'hubzilla');
|
||||
define('STD_VERSION', '8.8');
|
||||
define('STD_VERSION', '9.0');
|
||||
define('ZOT_REVISION', '6.0');
|
||||
|
||||
define('DB_UPDATE_VERSION', 1259);
|
||||
define('DB_UPDATE_VERSION', 1263);
|
||||
|
||||
define('PROJECT_BASE', __DIR__);
|
||||
|
||||
@@ -485,66 +489,59 @@ define('NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/');
|
||||
|
||||
define('ACTIVITYSTREAMS_JSONLD_REV', 'https://www.w3.org/ns/activitystreams');
|
||||
|
||||
define('ZOT_APSCHEMA_REV', '/apschema/v1.10');
|
||||
define('ZOT_APSCHEMA_REV', '/apschema/v1.11');
|
||||
|
||||
/**
|
||||
* activity stream defines
|
||||
*/
|
||||
|
||||
define('ACTIVITY_PUBLIC_INBOX', 'https://www.w3.org/ns/activitystreams#Public');
|
||||
|
||||
define('ACTIVITY_REACT', NAMESPACE_ZOT . '/activity/react');
|
||||
define('ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like');
|
||||
define('ACTIVITY_DISLIKE', NAMESPACE_ZOT . '/activity/dislike');
|
||||
define('ACTIVITY_AGREE', NAMESPACE_ZOT . '/activity/agree');
|
||||
define('ACTIVITY_DISAGREE', NAMESPACE_ZOT . '/activity/disagree');
|
||||
define('ACTIVITY_ABSTAIN', NAMESPACE_ZOT . '/activity/abstain');
|
||||
define('ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes');
|
||||
define('ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno');
|
||||
define('ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe');
|
||||
define('ACTIVITY_POLLRESPONSE', NAMESPACE_ZOT . '/activity/pollresponse');
|
||||
define('ACTIVITY_REACT', NAMESPACE_ZOT . '/activity/react'); // deprecated
|
||||
|
||||
define('ACTIVITY_OBJ_HEART', NAMESPACE_ZOT . '/activity/heart');
|
||||
define('ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like'); // AS2 Like
|
||||
define('ACTIVITY_DISLIKE', NAMESPACE_ZOT . '/activity/dislike'); // AS2 Dislike
|
||||
|
||||
define('ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend');
|
||||
define('ACTIVITY_REQ_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'request-friend');
|
||||
define('ACTIVITY_UNFRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'remove-friend');
|
||||
define('ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow');
|
||||
define('ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'stop-following');
|
||||
define('ACTIVITY_JOIN', NAMESPACE_ACTIVITY_SCHEMA . 'join');
|
||||
define('ACTIVITY_AGREE', NAMESPACE_ZOT . '/activity/agree'); // deprecated
|
||||
define('ACTIVITY_DISAGREE', NAMESPACE_ZOT . '/activity/disagree'); // deprecated
|
||||
define('ACTIVITY_ABSTAIN', NAMESPACE_ZOT . '/activity/abstain'); // deprecated
|
||||
|
||||
define('ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post');
|
||||
define('ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update');
|
||||
define('ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag');
|
||||
define('ACTIVITY_SHARE', NAMESPACE_ACTIVITY_SCHEMA . 'share');
|
||||
define('ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite');
|
||||
define('ACTIVITY_CREATE', NAMESPACE_ACTIVITY_SCHEMA . 'create');
|
||||
define('ACTIVITY_DELETE', NAMESPACE_ACTIVITY_SCHEMA . 'delete');
|
||||
define('ACTIVITY_WIN', NAMESPACE_ACTIVITY_SCHEMA . 'win');
|
||||
define('ACTIVITY_LOSE', NAMESPACE_ACTIVITY_SCHEMA . 'lose');
|
||||
define('ACTIVITY_TIE', NAMESPACE_ACTIVITY_SCHEMA . 'tie');
|
||||
define('ACTIVITY_COMPLETE', NAMESPACE_ACTIVITY_SCHEMA . 'complete');
|
||||
define('ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes'); // AS2 Accept
|
||||
define('ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno'); // AS2 Reject
|
||||
define('ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe'); // AS2 TentativeAccept
|
||||
|
||||
define('ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke');
|
||||
define('ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood');
|
||||
define('ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend'); // deprecated
|
||||
|
||||
define('ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow'); // AS2 Follow
|
||||
define('ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'stop-following'); // AS2 Ignore
|
||||
|
||||
|
||||
define('ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post'); // AS2 Create
|
||||
|
||||
define('ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update'); // AS2 Update
|
||||
|
||||
define('ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag'); // unused
|
||||
|
||||
define('ACTIVITY_SHARE', 'Announce');
|
||||
|
||||
define('ACTIVITY_CREATE', NAMESPACE_ACTIVITY_SCHEMA . 'create'); // deprecated
|
||||
|
||||
define('ACTIVITY_DELETE', NAMESPACE_ACTIVITY_SCHEMA . 'delete'); // AS2 Delete
|
||||
|
||||
define('ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke'); // deprecated
|
||||
define('ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood'); // deprecated
|
||||
|
||||
define('ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment'); // AS2 Note
|
||||
define('ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note'); // AS2 Note
|
||||
define('ACTIVITY_OBJ_ARTICLE', NAMESPACE_ACTIVITY_SCHEMA . 'article'); // AS2 Article
|
||||
define('ACTIVITY_OBJ_PERSON', NAMESPACE_ACTIVITY_SCHEMA . 'person'); // AS2 Person
|
||||
define('ACTIVITY_OBJ_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'photo'); // AS2 Image
|
||||
define('ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event'); // AS2 Event
|
||||
|
||||
define('ACTIVITY_OBJ_TAGTERM', NAMESPACE_ZOT . '/activity/tagterm'); // unused
|
||||
define('ACTIVITY_OBJ_PROFILE', NAMESPACE_ZOT . '/activity/profile'); // AS2 Profile
|
||||
define('ACTIVITY_OBJ_THING', NAMESPACE_ZOT . '/activity/thing'); // AS2 Page
|
||||
|
||||
define('ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment');
|
||||
define('ACTIVITY_OBJ_ACTIVITY', NAMESPACE_ACTIVITY_SCHEMA . 'activity');
|
||||
define('ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note');
|
||||
define('ACTIVITY_OBJ_ARTICLE', NAMESPACE_ACTIVITY_SCHEMA . 'article');
|
||||
define('ACTIVITY_OBJ_PERSON', NAMESPACE_ACTIVITY_SCHEMA . 'person');
|
||||
define('ACTIVITY_OBJ_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'photo');
|
||||
define('ACTIVITY_OBJ_P_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'profile-photo');
|
||||
define('ACTIVITY_OBJ_ALBUM', NAMESPACE_ACTIVITY_SCHEMA . 'photo-album');
|
||||
define('ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event');
|
||||
define('ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group');
|
||||
define('ACTIVITY_OBJ_GAME', NAMESPACE_ACTIVITY_SCHEMA . 'game');
|
||||
define('ACTIVITY_OBJ_WIKI', NAMESPACE_ACTIVITY_SCHEMA . 'wiki');
|
||||
define('ACTIVITY_OBJ_TAGTERM', NAMESPACE_ZOT . '/activity/tagterm');
|
||||
define('ACTIVITY_OBJ_PROFILE', NAMESPACE_ZOT . '/activity/profile');
|
||||
define('ACTIVITY_OBJ_THING', NAMESPACE_ZOT . '/activity/thing');
|
||||
define('ACTIVITY_OBJ_LOCATION', NAMESPACE_ZOT . '/activity/location');
|
||||
define('ACTIVITY_OBJ_FILE', NAMESPACE_ZOT . '/activity/file');
|
||||
define('ACTIVITY_OBJ_CARD', NAMESPACE_ZOT . '/activity/card');
|
||||
|
||||
/**
|
||||
* Account Flags
|
||||
@@ -678,8 +675,8 @@ function sys_boot() {
|
||||
* Load configs from db. Overwrite configs from .htconfig.php
|
||||
*/
|
||||
|
||||
load_config('system');
|
||||
load_config('feature');
|
||||
Config::Load('system');
|
||||
Config::Load('feature');
|
||||
|
||||
App::$session = new Zotlabs\Web\Session();
|
||||
App::$session->init();
|
||||
@@ -801,6 +798,7 @@ class App {
|
||||
public static $is_sys = false;
|
||||
public static $nav_sel;
|
||||
public static $comanche;
|
||||
public static $cache = []; // general purpose cache
|
||||
|
||||
|
||||
public static $channel_links;
|
||||
@@ -1401,7 +1399,7 @@ function x($s, $k = null) {
|
||||
* @ref include/system_unavailable.php will handle everything further.
|
||||
*/
|
||||
function system_unavailable() {
|
||||
include('include/system_unavailable.php');
|
||||
require_once('include/system_unavailable.php');
|
||||
system_down();
|
||||
killme();
|
||||
}
|
||||
@@ -2333,8 +2331,6 @@ function construct_page() {
|
||||
|
||||
require_once(theme_include('theme_init.php'));
|
||||
|
||||
$installing = false;
|
||||
|
||||
$uid = ((App::$profile_uid) ? App::$profile_uid : local_channel());
|
||||
|
||||
$navbar = get_config('system', 'navbar', 'default');
|
||||
@@ -2346,14 +2342,10 @@ function construct_page() {
|
||||
$navbar = App::$layout['navbar'];
|
||||
}
|
||||
|
||||
if (App::$module == 'setup') {
|
||||
$installing = true;
|
||||
}
|
||||
else {
|
||||
if (App::$module !== 'setup') {
|
||||
nav($navbar);
|
||||
}
|
||||
|
||||
|
||||
$current_theme = Zotlabs\Render\Theme::current();
|
||||
// logger('current_theme: ' . print_r($current_theme,true));
|
||||
// Zotlabs\Render\Theme::debug();
|
||||
@@ -2374,7 +2366,7 @@ function construct_page() {
|
||||
if (($p = theme_include('mod_' . App::$module . '.css')) != '')
|
||||
head_add_css('mod_' . App::$module . '.css');
|
||||
|
||||
head_add_css(Zotlabs\Render\Theme::url($installing));
|
||||
head_add_css(Zotlabs\Render\Theme::url());
|
||||
|
||||
if (($p = theme_include('mod_' . App::$module . '.js')) != '')
|
||||
head_add_js('mod_' . App::$module . '.js');
|
||||
|
||||
@@ -23,14 +23,17 @@
|
||||
"source": "https://framagit.org/hubzilla/core/"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1",
|
||||
"ext-curl": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-intl": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-posix": "*",
|
||||
"ext-sodium": "*",
|
||||
"ext-bcmath": "*",
|
||||
"sabre/dav": "^4.0",
|
||||
"michelf/php-markdown": "^2.0",
|
||||
"bshaffer/oauth2-server-php": "^1.9",
|
||||
@@ -45,17 +48,18 @@
|
||||
"twbs/bootstrap": "^5.3",
|
||||
"blueimp/jquery-file-upload": "^10.3",
|
||||
"desandro/imagesloaded": "^4.1",
|
||||
"phpseclib/phpseclib": "~2.0",
|
||||
"phpseclib/phpseclib": "^2.0.47",
|
||||
"jbroadway/urlify": "^1.2",
|
||||
"chillerlan/php-qrcode": "^4.3",
|
||||
"spomky-labs/otphp": "^11.1",
|
||||
"patrickschur/language-detection": "^5.3"
|
||||
"patrickschur/language-detection": "^5.3",
|
||||
"stephenhill/base58": "^1.1",
|
||||
"mmccook/php-json-canonicalization-scheme": "^1.0",
|
||||
"scssphp/scssphp": "^1.12"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-yaml": "*",
|
||||
"phpunit/phpunit": "^9.4",
|
||||
"behat/behat": "@stable",
|
||||
"behat/mink-extension": "@stable",
|
||||
"behat/mink-goutte-driver": "@stable",
|
||||
"php-mock/php-mock-phpunit": "^2.6",
|
||||
"phpmd/phpmd": "^2.6",
|
||||
"squizlabs/php_codesniffer": "*",
|
||||
@@ -77,11 +81,5 @@
|
||||
"config": {
|
||||
"notify-on-install": false,
|
||||
"optimize-autoloader": true
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/simplepie/simplepie"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
2321
composer.lock
generated
@@ -85,22 +85,25 @@ There are several ways to deploy a new hub.
|
||||
Example config scripts are available for these platforms in doc/install.
|
||||
Apache and nginx have the most support.
|
||||
|
||||
* PHP 7.1 or later.
|
||||
* Note that on some shared hosting environments, the _command line_
|
||||
version of PHP might differ from the _webserver_ version
|
||||
* PHP 8.1 or later.
|
||||
Note that on some shared hosting environments, the _command line_
|
||||
version of PHP might differ from the _webserver_ version
|
||||
|
||||
* PHP *command line* access with register_argc_argv set to true in the
|
||||
php.ini file * and with no hosting provider restrictions on the use of
|
||||
php.ini file, and with no hosting provider restrictions on the use of
|
||||
exec() and proc_open().
|
||||
|
||||
* curl, gd (with at least jpeg and png support), mysqli, mbstring, zip,
|
||||
and openssl extensions. The imagick extension is not required but desirable.
|
||||
* curl, gd (with at least jpeg and png support), pdo-mysql (or pdo-postgres), mbstring, zip,
|
||||
and openssl extensions. The imagick extension is not required, but recommended.
|
||||
|
||||
* xml extension is required if you want webdav to work.
|
||||
|
||||
* some form of email server or email gateway such that PHP mail() works.
|
||||
|
||||
* Mysql 5.x or MariaDB or postgres database server.
|
||||
* A supported database server. The supported databases are:
|
||||
- Mysql version 8.0.22 or later
|
||||
- MariaDB version 10.4 or later
|
||||
- PostgreSQL version 12 or later
|
||||
|
||||
* ability to schedule jobs with cron.
|
||||
|
||||
|
||||
130
doc/developer/testing.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Testing
|
||||
|
||||
Hubzilla uses [PHPUnit] for automated testing, often called _unit testing_ or _integration testing_.
|
||||
|
||||
The tests are written as PHP classes, and live under the `tests/unit` subdirectory of the main Hubzilla repository. This guide will explain how to run the tests, how the tests are structured, and how you can write your own tests.
|
||||
|
||||
## Running the test suite
|
||||
|
||||
### Installing the dependencies
|
||||
|
||||
To be able to run the tests you have to install the developer dependencies listen in the `composer.json` file. Make sure you have [composer installed] on your development system, and then run:
|
||||
|
||||
% composer install
|
||||
|
||||
This will install phpunit and a few other dependencies. It will also update some files in the `vendor/composer` subdirectory. This may seem a bit noisy, but it's important that these changes are *not* committed to the repository!
|
||||
|
||||
**Warning:** Do not commit the changes to the files in the `vendor/composer` directory to your repository!
|
||||
|
||||
### Setting up the test database
|
||||
|
||||
We have included a script (`tests/create_test_db.sh`) that will help you set up the test database. You can run it like this:
|
||||
|
||||
% HZ_TEST_DB_TYPE=mysql ./tests/create_test_db.sh
|
||||
|
||||
If you are running PostgreSQL instead, you create the test db like this:
|
||||
|
||||
% HZ_TEST_DB_TYPE=postgres ./tests/create_test_db.sh
|
||||
|
||||
The script make some assumptions about your setup, but everything is configurable using environment variables. If you need any customization, see the script source for the details.
|
||||
|
||||
### Running the tests
|
||||
|
||||
Once you have installed the developer dependencies and set up the test database, you can run the tests like this:
|
||||
|
||||
% ./vendor/bin/phpunit -c tests/phpunit.xml
|
||||
|
||||
Again, by default the configuration in `tests/phpunit.xml` makes some assumptions about your setup, which can be overridden using environment variables. See `tests/phpunit.xml` for the details.
|
||||
|
||||
You can also run a specific test, or a specific set of tests using the `--filter` argument to PHPUnit:
|
||||
|
||||
% ./vendor/bin/phpunit -c tests/phpunit.xml --filter Autoname
|
||||
|
||||
Will run any test mathcing "Autoname".
|
||||
|
||||
### Generating coverage reports
|
||||
|
||||
To generate coverage reports you need a driver that is able to generate the coverage info that PHPUnit will collect. We recommend [Xdebug], but see the PHPUnit [page on code coverage analysis](https://docs.phpunit.de/en/9.6/code-coverage-analysis.html) for alternatives and details.
|
||||
|
||||
With Xdebug properly set up, you can generate the coverage report like this:
|
||||
|
||||
% XDEBUG_MODE=coverage ./vendor/bin/phpunit -c ./tests/phpunit.xml
|
||||
|
||||
This will generate a number of HTML files in directories under the `tests/results/coverage/` subdirectory.
|
||||
|
||||
Open the `index.php file in your web browser to view the stats.
|
||||
|
||||
### Debugging
|
||||
|
||||
With Xdebug installed, you can also do step debugging and a number of other things to debug and get information about the execution of the tests. See the [Xdebug] pages and your prefered editor for how to set this up.
|
||||
|
||||
## Test structure and organization
|
||||
|
||||
Tests are located in the `tests/unit` subdirectory, and subdirectories under there again, more or less reflecting the directory layout of the core code repository.
|
||||
|
||||
Tests are written as PHP classes that extends the UnitTestCase class (located in `tests/unit/UnitTestcase.php`). The file name and the test class it contains should be the same, and they _must_ end with `Test.php`.
|
||||
|
||||
Examples are:
|
||||
|
||||
* `tests/unit/includes/AccountTest.php`
|
||||
* `tests/unit/Lib/ActivityTest.php`
|
||||
|
||||
The test classes contain one or more test functions, these must be public and prefixed with `test`.
|
||||
|
||||
Here's an example:
|
||||
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
|
||||
class AccountTest extends UnitTestCase {
|
||||
public function test_get_account_by_id_returns_existing_account() {
|
||||
$account = get_account_by_id(42);
|
||||
$this->assertNotFalse($account);
|
||||
$this->assertEquals(
|
||||
$this->fixtures['account'][0]['account_email'],
|
||||
$account['account_email']
|
||||
);
|
||||
}
|
||||
|
||||
Notice that we try to make the name of the test funtion as descriptive as possible.
|
||||
|
||||
The class can also contain any number of other functions to keep things tidy and nice. These can be private, protected or public as needed by the test code.
|
||||
|
||||
Results and artifacts from the test runs will be left in the `tests/results/` directory. This will typically include the test log, code coverage report etc.
|
||||
|
||||
### Hubzilla specific features
|
||||
|
||||
#### Test database access:
|
||||
|
||||
Ideally it should be able to test each part of the code in isolation, where any dependencies should be replaced by stubs, mocks or fakes.
|
||||
|
||||
This is not feasible with a legacy codebase like Hubzilla, that has not been written with testability in mind. For this reason we use a separate test database, and make it available to the code under test using the same mechanisms as Hubzilla normally do.
|
||||
|
||||
This means that any code that executes database queries will behave as normal when called by a test.
|
||||
|
||||
To make this work we connect to the database before running each test function. We also load some initial data into the database to make sure things work as expected, and that we have a known state of the database when the test runs.
|
||||
|
||||
When the test finishes, the test database is wiped clean, so that we have the same consistent state when the next test runs.
|
||||
|
||||
All of this is handled by the `UnitTestCase` base class.
|
||||
|
||||
#### Database fixtures:
|
||||
|
||||
We need some predictable content in the database to set up things like logging, and other content that's useful in general for the tests. These are database fixtures that are loaded into the database for each test run.
|
||||
|
||||
The database fixtures are located in the `tests/unit/include/dba/_files` directory, and consist of YAML files, where each file represents the content of a database table with the same name as the file itself.
|
||||
|
||||
While database fixtures are nice to have, we try to keep the number of them as minimal as possible. It's usually better to add any content needed for a specific test in the test itself.
|
||||
|
||||
#### Fakes:
|
||||
|
||||
Fakes are classes that we can pass to the code under test that will look and (to the code under test) behave the same as the original class. These are useful when we're able to pass objects to the code under test, as we can control it completely from the test code.
|
||||
|
||||
Fakes are located under the `tests/fakes` directory.
|
||||
|
||||
## Writing your own tests
|
||||
|
||||
To be done
|
||||
|
||||
[PHPUnit]: https://phpunit.de
|
||||
[composer installed]: https://getcomposer.org/
|
||||
[Xdebug]: https://xdebug.org/
|
||||
@@ -1 +1,17 @@
|
||||
[h2]check_account_password[/h2]
|
||||
Use this hook to provide additional checks or validations of the password given when
|
||||
registering and account.
|
||||
[h3]Arguments:[/h3]
|
||||
[code=php]array(
|
||||
'password' => $password, // The password to check
|
||||
'result' => array(
|
||||
'error' => false,
|
||||
'message' => ''
|
||||
)
|
||||
)[/code]
|
||||
[h3]Results:[/h3]
|
||||
For a failed check set the [code]error[/code] member of the [code]result[/code]
|
||||
array to [code]true[/code] and the [code]message[/code] to a short message
|
||||
explaining why it failed.
|
||||
|
||||
Otherwise, leave it alone.
|
||||
|
||||
BIN
images/default_profile_photos/circle_person/300.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
images/default_profile_photos/circle_person/48.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
images/default_profile_photos/circle_person/80.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 842 B |
|
Before Width: | Height: | Size: 901 B |
|
Before Width: | Height: | Size: 935 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 812 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 757 B |