mirror of
https://codeberg.org/streams/streams.git
synced 2024-09-19 16:55:18 +00:00
Merge branch 'nomadic' into dev
This commit is contained in:
commit
fad117958a
171 changed files with 9429 additions and 1647 deletions
37
.env
Normal file
37
.env
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
###> symfony/mailer ###
|
||||
# MAILER_DSN=null://null
|
||||
###< symfony/mailer ###
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_ENV=dev
|
||||
APP_SECRET=b2e0b4744a825057deefb2b8d6cf7d50
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||
#
|
||||
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
|
||||
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> nelmio/cors-bundle ###
|
||||
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
|
||||
###< nelmio/cors-bundle ###
|
||||
|
||||
###> league/oauth2-server-bundle ###
|
||||
OAUTH_PRIVATE_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||
OAUTH_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||
OAUTH_PASSPHRASE=a557f0cd5e33c785227ae08fa111f55a
|
||||
OAUTH_ENCRYPTION_KEY=0a55b0c0d31a601b7a8cfa5427924fa2
|
||||
###< league/oauth2-server-bundle ###
|
||||
|
||||
###> symfony/messenger ###
|
||||
# Choose one of the transports below
|
||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||
# MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||
###< symfony/messenger ###
|
6
.env.test
Normal file
6
.env.test
Normal file
|
@ -0,0 +1,6 @@
|
|||
# define your env variables for the test env here
|
||||
KERNEL_CLASS='App\Kernel'
|
||||
APP_SECRET='$ecretf0rt3st'
|
||||
SYMFONY_DEPRECATIONS_HELPER=999999
|
||||
PANTHER_APP_ENV=panther
|
||||
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots
|
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -22,6 +22,7 @@ Thumbs.db
|
|||
__pycache__
|
||||
|
||||
## Ignore site specific files and folders
|
||||
.env*
|
||||
.htaccess
|
||||
.htconfig.php
|
||||
.htstartup.php
|
||||
|
@ -85,3 +86,22 @@ vendor/
|
|||
vendor/**/tests/
|
||||
vendor/**/Test/
|
||||
vendor/sabre/*/examples/
|
||||
|
||||
###> phpunit/phpunit ###
|
||||
/phpunit.xml
|
||||
.phpunit.result.cache
|
||||
###< phpunit/phpunit ###
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
/.env.local
|
||||
/.env.local.php
|
||||
/.env.*.local
|
||||
/config/secrets/prod/prod.decrypt.private.php
|
||||
/public/bundles/
|
||||
/var/
|
||||
/vendor/
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> league/oauth2-server-bundle ###
|
||||
/config/jwt/*.pem
|
||||
###< league/oauth2-server-bundle ###
|
||||
|
|
21
bin/console
Executable file
21
bin/console
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
|
||||
if (!is_dir(dirname(__DIR__).'/vendor')) {
|
||||
throw new LogicException('Dependencies are missing. Try running "composer install".');
|
||||
}
|
||||
|
||||
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
|
||||
return new Application($kernel);
|
||||
};
|
19
compose.override.yaml
Normal file
19
compose.override.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
###> symfony/mailer ###
|
||||
mailer:
|
||||
image: axllent/mailpit
|
||||
ports:
|
||||
- "1025"
|
||||
- "8025"
|
||||
environment:
|
||||
MP_SMTP_AUTH_ACCEPT_ANY: 1
|
||||
MP_SMTP_AUTH_ALLOW_INSECURE: 1
|
||||
###< symfony/mailer ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database:
|
||||
ports:
|
||||
- "5432"
|
||||
###< doctrine/doctrine-bundle ###
|
21
compose.yaml
Normal file
21
compose.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database:
|
||||
image: postgres:${POSTGRES_VERSION:-16}-alpine
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-app}
|
||||
# You should definitely change the password in production
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-app}
|
||||
volumes:
|
||||
- database_data:/var/lib/postgresql/data:rw
|
||||
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
|
||||
# - ./docker/db/data:/var/lib/postgresql/data:rw
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
volumes:
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database_data:
|
||||
###< doctrine/doctrine-bundle ###
|
|
@ -15,6 +15,7 @@
|
|||
"require": {
|
||||
"php": ">=8.1",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
|
@ -39,7 +40,7 @@
|
|||
"ext-json": "*",
|
||||
"symfony/yaml": "*",
|
||||
"symfony/uid": "*",
|
||||
"symfony/mailer": "*",
|
||||
"symfony/mailer": "^6.4",
|
||||
"wapmorgan/mp3info": "^0.0.8",
|
||||
"chillerlan/php-qrcode": "^4.3",
|
||||
"spomky-labs/otphp": "^10.0",
|
||||
|
@ -50,25 +51,70 @@
|
|||
"league/oauth2-google": "^4.0",
|
||||
"decomplexity/sendoauth2": "^3.0",
|
||||
"gregwar/captcha": "^1.2",
|
||||
"symfony/symfony": "*",
|
||||
"doctrine/orm": "*",
|
||||
"doctrine/dbal": "*",
|
||||
"root23/php-json-canonicalization": "^1.0"
|
||||
"symfony/flex": "^2.4",
|
||||
"symfony/asset": "^6.4",
|
||||
"symfony/monolog-bundle": "^3.10",
|
||||
"symfony/form": "^6.4",
|
||||
"symfony/security-bundle": "^6.4",
|
||||
"symfony/translation": "^6.4",
|
||||
"symfony/validator": "^6.4",
|
||||
"doctrine/doctrine-bundle": "^2.12",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.3",
|
||||
"symfony/twig-bundle": "^6.4",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0",
|
||||
"api-platform/core": "^3.2",
|
||||
"nelmio/cors-bundle": "^2.4",
|
||||
"symfony/expression-language": "^6.4",
|
||||
"phpdocumentor/reflection-docblock": "^5.3",
|
||||
"phpstan/phpdoc-parser": "^1.27",
|
||||
"symfony/property-access": "^6.4",
|
||||
"symfony/property-info": "^6.4",
|
||||
"symfony/serializer": "^6.4",
|
||||
"league/oauth2-server-bundle": "^0.8.0",
|
||||
"symfony/messenger": "^6.4",
|
||||
"symfony/notifier": "^6.4",
|
||||
"root23/php-json-canonicalization": "^1.0",
|
||||
"symfony/framework-bundle": "^6.4",
|
||||
"forensic/feed-parser": "^1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "@stable",
|
||||
"behat/behat": "*",
|
||||
"behat/mink-extension": "@stable",
|
||||
"behat/mink-goutte-driver": "@stable",
|
||||
"php-mock/php-mock-phpunit": "@stable",
|
||||
"codeception/codeception": "*",
|
||||
"codeception/module-phpbrowser": "*",
|
||||
"codeception/module-asserts": "*"
|
||||
"codeception/module-asserts": "*",
|
||||
"symfony/dotenv": "^6.4",
|
||||
"symfony/maker-bundle": "^1.57",
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.5",
|
||||
"symfony/stopwatch": "^6.4",
|
||||
"symfony/web-profiler-bundle": "^6.4",
|
||||
"symfony/debug-bundle": "^6.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/",
|
||||
"Include\\": "include/",
|
||||
"Code\\": "src/"
|
||||
"Code\\Access\\": "src/Access",
|
||||
"Code\\ActivityStreams\\": "src/ActivityStreams",
|
||||
"Code\\Daemon\\": "src/Daemon",
|
||||
"Code\\Entity\\": "src/Entity",
|
||||
"Code\\Extend\\": "src/Extend",
|
||||
"Code\\Identity\\": "src/Identity",
|
||||
"Code\\Import\\": "src/Import",
|
||||
"Code\\Lib\\": "src/Lib",
|
||||
"Code\\Module\\": "src/Module",
|
||||
"Code\\Nomad\\": "src/Nomad",
|
||||
"Code\\Photo\\": "src/Photo",
|
||||
"Code\\Render\\": "src/Render",
|
||||
"Code\\Storage\\": "src/Storage",
|
||||
"Code\\Text\\": "src/Text",
|
||||
"Code\\Thumbs\\": "src/Thumbs",
|
||||
"Code\\Update\\": "src/Update",
|
||||
"Code\\Web\\": "src/Web",
|
||||
"Code\\Widget\\": "src/Widget"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
@ -76,6 +122,7 @@
|
|||
"Code\\Tests\\Unit\\": "tests/unit"
|
||||
}
|
||||
},
|
||||
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"platform": {
|
||||
|
@ -86,5 +133,11 @@
|
|||
"allow-plugins": {
|
||||
"symfony/flex": true
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
8291
composer.lock
generated
8291
composer.lock
generated
File diff suppressed because it is too large
Load diff
18
config/bundles.php
Normal file
18
config/bundles.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||
League\Bundle\OAuth2ServerBundle\LeagueOAuth2ServerBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
|
||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||
];
|
18
config/packages/api_platform.yaml
Normal file
18
config/packages/api_platform.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
api_platform:
|
||||
title: Hello API Platform
|
||||
version: 1.0.0
|
||||
formats:
|
||||
jsonld: ['application/ld+json']
|
||||
docs_formats:
|
||||
jsonld: ['application/ld+json']
|
||||
jsonopenapi: ['application/vnd.openapi+json']
|
||||
html: ['text/html']
|
||||
defaults:
|
||||
stateless: true
|
||||
cache_headers:
|
||||
vary: ['Content-Type', 'Authorization', 'Origin']
|
||||
extra_properties:
|
||||
standard_put: true
|
||||
rfc_7807_compliant_errors: true
|
||||
event_listeners_backward_compatibility_layer: false
|
||||
keep_legacy_inflector: false
|
19
config/packages/cache.yaml
Normal file
19
config/packages/cache.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
framework:
|
||||
cache:
|
||||
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
|
||||
# The "app" cache stores to the filesystem by default.
|
||||
# The data in this cache should persist between deploys.
|
||||
# Other options include:
|
||||
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: null
|
5
config/packages/debug.yaml
Normal file
5
config/packages/debug.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
when@dev:
|
||||
debug:
|
||||
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||
# See the "server:dump" command to start a new server.
|
||||
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
42
config/packages/doctrine.yaml
Normal file
42
config/packages/doctrine.yaml
Normal file
|
@ -0,0 +1,42 @@
|
|||
doctrine:
|
||||
dbal:
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '14'
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
dbal:
|
||||
# "TEST_TOKEN" is typically set by ParaTest
|
||||
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
|
||||
|
||||
when@prod:
|
||||
doctrine:
|
||||
orm:
|
||||
auto_generate_proxy_classes: false
|
||||
query_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
result_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.result_cache_pool
|
||||
|
||||
framework:
|
||||
cache:
|
||||
pools:
|
||||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
6
config/packages/doctrine_migrations.yaml
Normal file
6
config/packages/doctrine_migrations.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
doctrine_migrations:
|
||||
migrations_paths:
|
||||
# namespace is arbitrary but should be different from App\Migrations
|
||||
# as migrations classes should NOT be autoloaded
|
||||
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
||||
enable_profiler: false
|
24
config/packages/framework.yaml
Normal file
24
config/packages/framework.yaml
Normal file
|
@ -0,0 +1,24 @@
|
|||
# see https://symfony.com/doc/current/reference/configuration/framework.html
|
||||
framework:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
#csrf_protection: true
|
||||
http_method_override: false
|
||||
|
||||
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||
# Remove or comment this section to explicitly disable session support.
|
||||
session:
|
||||
handler_id: null
|
||||
cookie_secure: auto
|
||||
cookie_samesite: lax
|
||||
storage_factory_id: session.storage.factory.native
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
php_errors:
|
||||
log: true
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
test: true
|
||||
session:
|
||||
storage_factory_id: session.storage.factory.mock_file
|
17
config/packages/league_oauth2_server.yaml
Normal file
17
config/packages/league_oauth2_server.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
league_oauth2_server:
|
||||
authorization_server:
|
||||
private_key: '%env(resolve:OAUTH_PRIVATE_KEY)%'
|
||||
private_key_passphrase: '%env(resolve:OAUTH_PASSPHRASE)%'
|
||||
encryption_key: '%env(resolve:OAUTH_ENCRYPTION_KEY)%'
|
||||
resource_server:
|
||||
public_key: '%env(resolve:OAUTH_PUBLIC_KEY)%'
|
||||
scopes:
|
||||
available: ['email']
|
||||
default: ['email']
|
||||
persistence:
|
||||
doctrine: null
|
||||
|
||||
when@test:
|
||||
league_oauth2_server:
|
||||
persistence:
|
||||
in_memory: null
|
3
config/packages/mailer.yaml
Normal file
3
config/packages/mailer.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
framework:
|
||||
mailer:
|
||||
dsn: '%env(MAILER_DSN)%'
|
24
config/packages/messenger.yaml
Normal file
24
config/packages/messenger.yaml
Normal file
|
@ -0,0 +1,24 @@
|
|||
framework:
|
||||
messenger:
|
||||
failure_transport: failed
|
||||
|
||||
transports:
|
||||
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||
async:
|
||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
options:
|
||||
use_notify: true
|
||||
check_delayed_interval: 60000
|
||||
retry_strategy:
|
||||
max_retries: 3
|
||||
multiplier: 2
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
# sync: 'sync://'
|
||||
|
||||
routing:
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
|
||||
# Symfony\Component\Notifier\Message\ChatMessage: async
|
||||
# Symfony\Component\Notifier\Message\SmsMessage: async
|
||||
|
||||
# Route your messages to the transports
|
||||
# 'App\Message\YourMessage': async
|
61
config/packages/monolog.yaml
Normal file
61
config/packages/monolog.yaml
Normal file
|
@ -0,0 +1,61 @@
|
|||
monolog:
|
||||
channels:
|
||||
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
channels: ["!event"]
|
||||
# uncomment to get logging in your browser
|
||||
# you may have to allow bigger header sizes in your Web server configuration
|
||||
#firephp:
|
||||
# type: firephp
|
||||
# level: info
|
||||
#chromephp:
|
||||
# type: chromephp
|
||||
# level: info
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
|
||||
when@test:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
|
||||
when@prod:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||
nested:
|
||||
type: stream
|
||||
path: php://stderr
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
deprecation:
|
||||
type: stream
|
||||
channels: [deprecation]
|
||||
path: php://stderr
|
10
config/packages/nelmio_cors.yaml
Normal file
10
config/packages/nelmio_cors.yaml
Normal file
|
@ -0,0 +1,10 @@
|
|||
nelmio_cors:
|
||||
defaults:
|
||||
origin_regex: true
|
||||
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||
allow_headers: ['Content-Type', 'Authorization']
|
||||
expose_headers: ['Link']
|
||||
max_age: 3600
|
||||
paths:
|
||||
'^/': null
|
16
config/packages/notifier.yaml
Normal file
16
config/packages/notifier.yaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
framework:
|
||||
notifier:
|
||||
#chatter_transports:
|
||||
# slack: '%env(SLACK_DSN)%'
|
||||
# telegram: '%env(TELEGRAM_DSN)%'
|
||||
#texter_transports:
|
||||
# twilio: '%env(TWILIO_DSN)%'
|
||||
# nexmo: '%env(NEXMO_DSN)%'
|
||||
channel_policy:
|
||||
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
|
||||
urgent: ['email']
|
||||
high: ['email']
|
||||
medium: ['email']
|
||||
low: ['email']
|
||||
admin_recipients:
|
||||
- { email: admin@example.com }
|
21
config/packages/nyholm_psr7.yaml
Normal file
21
config/packages/nyholm_psr7.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
services:
|
||||
# Register nyholm/psr7 services for autowiring with PSR-17 (HTTP factories)
|
||||
Psr\Http\Message\RequestFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||
Psr\Http\Message\ResponseFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||
Psr\Http\Message\ServerRequestFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||
Psr\Http\Message\StreamFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||
Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||
Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory'
|
||||
|
||||
# Register nyholm/psr7 services for autowiring with HTTPlug factories
|
||||
Http\Message\MessageFactory: '@nyholm.psr7.httplug_factory'
|
||||
Http\Message\RequestFactory: '@nyholm.psr7.httplug_factory'
|
||||
Http\Message\ResponseFactory: '@nyholm.psr7.httplug_factory'
|
||||
Http\Message\StreamFactory: '@nyholm.psr7.httplug_factory'
|
||||
Http\Message\UriFactory: '@nyholm.psr7.httplug_factory'
|
||||
|
||||
nyholm.psr7.psr17_factory:
|
||||
class: Nyholm\Psr7\Factory\Psr17Factory
|
||||
|
||||
nyholm.psr7.httplug_factory:
|
||||
class: Nyholm\Psr7\Factory\HttplugFactory
|
12
config/packages/routing.yaml
Normal file
12
config/packages/routing.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
framework:
|
||||
router:
|
||||
utf8: true
|
||||
|
||||
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||
#default_uri: http://localhost
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: null
|
48
config/packages/security.yaml
Normal file
48
config/packages/security.yaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
security:
|
||||
enable_authenticator_manager: true
|
||||
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||
password_hashers:
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
||||
providers:
|
||||
users_in_memory: { memory: null }
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
main:
|
||||
lazy: true
|
||||
provider: users_in_memory
|
||||
|
||||
# activate different ways to authenticate
|
||||
# https://symfony.com/doc/current/security.html#the-firewall
|
||||
|
||||
# https://symfony.com/doc/current/security/impersonating_user.html
|
||||
# switch_user: true
|
||||
api_token:
|
||||
pattern: ^/api/token$
|
||||
security: false
|
||||
api:
|
||||
pattern: ^/api
|
||||
security: true
|
||||
stateless: true
|
||||
oauth2: true
|
||||
# Easy way to control access for large sections of your site
|
||||
# Note: Only the *first* access control that matches will be used
|
||||
access_control:
|
||||
- { path: ^/authorize, roles: IS_AUTHENTICATED_REMEMBERED }
|
||||
- { path: ^/admin, roles: ROLE_ADMIN }
|
||||
- { path: ^/profile, roles: ROLE_USER }
|
||||
|
||||
when@test:
|
||||
security:
|
||||
password_hashers:
|
||||
# By default, password hashers are resource intensive and take time. This is
|
||||
# important to generate secure password hashes. In tests however, secure hashes
|
||||
# are not important, waste resources and increase test times. The following
|
||||
# reduces the work factor to the lowest possible values.
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
|
||||
algorithm: auto
|
||||
cost: 4 # Lowest possible value for bcrypt
|
||||
time_cost: 3 # Lowest possible value for argon
|
||||
memory_cost: 10 # Lowest possible value for argon
|
13
config/packages/translation.yaml
Normal file
13
config/packages/translation.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
framework:
|
||||
default_locale: en
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
fallbacks:
|
||||
- en
|
||||
# providers:
|
||||
# crowdin:
|
||||
# dsn: '%env(CROWDIN_DSN)%'
|
||||
# loco:
|
||||
# dsn: '%env(LOCO_DSN)%'
|
||||
# lokalise:
|
||||
# dsn: '%env(LOKALISE_DSN)%'
|
6
config/packages/twig.yaml
Normal file
6
config/packages/twig.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
twig:
|
||||
default_path: '%kernel.project_dir%/templates'
|
||||
|
||||
when@test:
|
||||
twig:
|
||||
strict_variables: true
|
4
config/packages/uid.yaml
Normal file
4
config/packages/uid.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
framework:
|
||||
uid:
|
||||
default_uuid_version: 7
|
||||
time_based_uuid_version: 7
|
13
config/packages/validator.yaml
Normal file
13
config/packages/validator.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
framework:
|
||||
validation:
|
||||
email_validation_mode: html5
|
||||
|
||||
# Enables validator auto-mapping support.
|
||||
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
|
||||
#auto_mapping:
|
||||
# App\Entity\: []
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
validation:
|
||||
not_compromised_password: false
|
17
config/packages/web_profiler.yaml
Normal file
17
config/packages/web_profiler.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler:
|
||||
only_exceptions: false
|
||||
collect_serializer_data: true
|
||||
|
||||
when@test:
|
||||
web_profiler:
|
||||
toolbar: false
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
5
config/preload.php
Normal file
5
config/preload.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||
}
|
6
config/routes.yaml
Normal file
6
config/routes.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
controllers:
|
||||
resource: ../src/Controller/
|
||||
type: attribute
|
||||
oauth2:
|
||||
resource: '@LeagueOAuth2ServerBundle/Resources/config/routes.php'
|
||||
type: php
|
4
config/routes/api_platform.yaml
Normal file
4
config/routes/api_platform.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
api_platform:
|
||||
resource: .
|
||||
type: api_platform
|
||||
prefix: /api
|
4
config/routes/framework.yaml
Normal file
4
config/routes/framework.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
when@dev:
|
||||
_errors:
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
|
||||
prefix: /_error
|
3
config/routes/league_oauth2_server.yaml
Normal file
3
config/routes/league_oauth2_server.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
oauth2_server:
|
||||
resource: '@LeagueOAuth2ServerBundle/Resources/config/routes.php'
|
||||
type: php
|
3
config/routes/security.yaml
Normal file
3
config/routes/security.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
_security_logout:
|
||||
resource: security.route_loader.logout
|
||||
type: service
|
8
config/routes/web_profiler.yaml
Normal file
8
config/routes/web_profiler.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
when@dev:
|
||||
web_profiler_wdt:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
|
||||
prefix: /_wdt
|
||||
|
||||
web_profiler_profiler:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
|
||||
prefix: /_profiler
|
41
config/services.yaml
Normal file
41
config/services.yaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
# This file is the entry point to configure your own services.
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||
parameters:
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/'
|
||||
exclude:
|
||||
- '../src/DependencyInjection/'
|
||||
- '../src/Entity/'
|
||||
- '../src/Kernel.php'
|
||||
- '../src/Access/'
|
||||
- '../src/ActivityStreams/'
|
||||
- '../src/Daemon/'
|
||||
- '../src/Extend/'
|
||||
- '../src/Identity/'
|
||||
- '../src/Import/'
|
||||
- '../src/Lib/'
|
||||
- '../src/Module/'
|
||||
- '../src/Nomad/'
|
||||
- '../src/Photo/'
|
||||
- '../src/Render/'
|
||||
- '../src/Storage/'
|
||||
- '../src/Text/'
|
||||
- '../src/Thumbs/'
|
||||
- '../src/Update/'
|
||||
- '../src/Web/'
|
||||
- '../src/Widget/'
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
|
@ -3,7 +3,7 @@ AddType audio/ogg .oga
|
|||
CGIPassAuth On
|
||||
|
||||
# don't allow any web access to logfiles, even after rotation/compression
|
||||
<FilesMatch "\.(out|log|gz)$">
|
||||
<FilesMatch "\.(out|log|gz|env)$">
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
|
|
@ -1101,7 +1101,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null)
|
|||
}
|
||||
|
||||
if ($notify) {
|
||||
$cloudPath = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path'];
|
||||
$cloudPath = Channel::getDidResolver($channel) . '/cloud/' . $channel['channel_address'] . '/' . $r['0']['display_path'];
|
||||
$object = get_file_activity_object($channel['channel_id'], $r['0']['hash'], $cloudPath);
|
||||
file_activity($channel['channel_id'], $object, $r['0']['allow_cid'], $r['0']['allow_gid'], $r['0']['deny_cid'], $r['0']['deny_gid'], 'post', $notify);
|
||||
}
|
||||
|
@ -1245,7 +1245,7 @@ function attach_dirlist($channel, $observer, $sort_key = 'display_path', $direct
|
|||
'shorttext' => (($folder['path']) ? ellipsify($folder['path'], 28) : '/'),
|
||||
'jstext' => (($folder['path']) ? addslashes($folder['path']) : '/'),
|
||||
'total' => $folder['total'],
|
||||
'url' => z_root() . '/' . $folder['location'],
|
||||
'url' => Channel::getDidResolver($channel) . '/' . $folder['location'],
|
||||
'urlencode' => urlencode($folder['path']),
|
||||
'bin2hex' => $folder['folder']
|
||||
];
|
||||
|
|
|
@ -303,8 +303,8 @@ function mark_orphan_hubsxchans()
|
|||
|
||||
|
||||
$r = q("update hubloc set hubloc_deleted = 1 where hubloc_deleted = 0
|
||||
and hubloc_network in ('nomad','zot6') and hubloc_connected != '0001-01-01 00:00:00' and hubloc_connected < %s - interval %s",
|
||||
db_utcnow(), db_quoteinterval('36 day')
|
||||
and hubloc_network in ('nomad','zot6') and hubloc_connected != '0001-01-01 00:00:00' and hubloc_connected < %s - %s",
|
||||
db_utcnow(), db_quoteinterval('36 day', true)
|
||||
);
|
||||
|
||||
$r = q("select hubloc_id, hubloc_hash from hubloc where hubloc_deleted = 1 and hubloc_orphancheck = 0");
|
||||
|
@ -589,9 +589,9 @@ function random_profile()
|
|||
for ($i = 0; $i < $retryrandom; $i++) {
|
||||
$r = q("select xchan_url, xchan_hash from xchan left join hubloc on hubloc_hash = xchan_hash where
|
||||
xchan_hidden = 0 and xchan_network in ('nomad','zot6') and xchan_deleted = 0 and hubloc_deleted = 0
|
||||
and hubloc_connected > %s - interval %s order by $randfunc limit 1",
|
||||
and hubloc_connected > %s - %s order by $randfunc limit 1",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('30 day')
|
||||
db_quoteinterval('30 day', true)
|
||||
);
|
||||
|
||||
if (!$r) {
|
||||
|
|
|
@ -23,22 +23,19 @@ use Code\Render\Theme;
|
|||
function localize_item(&$item)
|
||||
{
|
||||
|
||||
if (activity_match($item['verb'], ACTIVITY_LIKE) || activity_match($item['verb'], ACTIVITY_DISLIKE)
|
||||
|| $item['verb'] === 'Announce') {
|
||||
if (! $item['obj']) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (intval($item['item_thread_top'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$obj = ((is_array($item['obj'])) ? $item['obj'] : json_decode($item['obj'], true));
|
||||
if (! is_array($obj)) {
|
||||
logger('localize_item: failed to decode object: ' . print_r($item['obj'], true));
|
||||
return;
|
||||
}
|
||||
|
||||
if (activity_match($item['verb'], ACTIVITY_LIKE) || activity_match($item['verb'], ACTIVITY_DISLIKE)
|
||||
|| $item['verb'] === 'Announce') {
|
||||
|
||||
if (intval($item['item_thread_top'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($obj['actor']) && is_string($obj['actor']) && $obj['actor']) {
|
||||
$author_link = $obj['actor'];
|
||||
}
|
||||
|
@ -141,9 +138,6 @@ function localize_item(&$item)
|
|||
$Aname = $item['author']['xchan_name'];
|
||||
$Alink = $item['author']['xchan_url'];
|
||||
|
||||
|
||||
$obj = json_decode($item['obj'], true);
|
||||
|
||||
$Blink = $Bphoto = '';
|
||||
|
||||
if ($obj['link']) {
|
||||
|
@ -177,8 +171,6 @@ function localize_item(&$item)
|
|||
$Aname = $item['author']['xchan_name'];
|
||||
$Alink = $item['author']['xchan_url'];
|
||||
|
||||
$obj = json_decode($item['obj'], true);
|
||||
|
||||
$Blink = $Bphoto = '';
|
||||
|
||||
if ($obj['link']) {
|
||||
|
@ -798,7 +790,7 @@ function thread_author_menu($item, $mode = '')
|
|||
|
||||
if ($local_channel && $contact) {
|
||||
$can_dm = perm_is_allowed($local_channel, $item['author_xchan'], 'post_mail') && intval($contact['xchan_type']) !== XCHAN_TYPE_GROUP ;
|
||||
} elseif ($item['author']['xchan_network'] === 'activitypub') {
|
||||
} elseif (in_array($item['author']['xchan_network'], ['activitypub', 'apnomadic'])) {
|
||||
$can_dm = true;
|
||||
}
|
||||
if ($can_dm) {
|
||||
|
@ -968,6 +960,7 @@ function builtin_activity_puller($item, &$conv_responses)
|
|||
|
||||
if ((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
|
||||
$name = $item['author']['xchan_name'] ?: t('Unknown');
|
||||
|
||||
$url = (($item['author_xchan'] && $item['author']['xchan_photo_s'])
|
||||
? '<a class="dropdown-item" href="' . chanlink_hash($item['author_xchan']) . '">' . '<img class="menu-img-1" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" /> ' . $name . ' (' . relative_date($item['created']) .')</a>'
|
||||
: '<a class="dropdown-item" href="#" class="disabled">' . $name . ' (' . relative_date($item['created']) . ')</a>'
|
||||
|
@ -1542,6 +1535,14 @@ function conv_sort($arr, $order)
|
|||
$narr = [];
|
||||
|
||||
foreach ($arr as $item) {
|
||||
|
||||
if (is_string($item['obj']) && $item['obj']) {
|
||||
$local = json_decode($item['obj'], true);
|
||||
if ($local !== NULL) {
|
||||
$item['obj'] = $local;
|
||||
}
|
||||
}
|
||||
|
||||
// perform view filtering if viewer is logged in locally
|
||||
// This allows blocking and message filters to work on public stream items
|
||||
// or other channel streams on this site which are not owned by the viewer
|
||||
|
@ -1586,10 +1587,9 @@ function conv_sort($arr, $order)
|
|||
}
|
||||
}
|
||||
}
|
||||
if ($item['obj']) {
|
||||
$local = json_decode($item['obj'],true);
|
||||
if (!empty($local['source']) && !empty($local['source']['mediaType']) && !empty($local['source']['content'])) {
|
||||
$cnt = preg_match_all("/\[share(.*?)portable_id='(.*?)'(.*?)]/ism", $local['source']['content'], $matches, PREG_SET_ORDER);
|
||||
if (is_array($item['obj'])) {
|
||||
if (!empty($item['obj']['source']) && !empty($item['obj']['source']['mediaType']) && !empty($item['obj']['source']['content'])) {
|
||||
$cnt = preg_match_all("/\[share(.*?)portable_id='(.*?)'(.*?)]/ism", $item['obj']['source']['content'], $matches, PREG_SET_ORDER);
|
||||
if ($cnt) {
|
||||
foreach ($matches as $match) {
|
||||
if (LibBlock::fetch_by_entity(local_channel(), $match[2])) {
|
||||
|
|
|
@ -554,11 +554,11 @@ function update_birthdays()
|
|||
|
||||
$r = q(
|
||||
"SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_dob > %s + interval %s and abook_dob < %s + interval %s",
|
||||
WHERE abook_dob > %s + %s and abook_dob < %s + %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 day'),
|
||||
db_quoteinterval('7 day', true),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 day')
|
||||
db_quoteinterval('14 day', true)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
|
|
|
@ -307,9 +307,10 @@ function dbescdate($date)
|
|||
return DBA::$dba->escape($date);
|
||||
}
|
||||
|
||||
function db_quoteinterval($txt)
|
||||
function db_quoteinterval($txt, $includeInterval = false)
|
||||
{
|
||||
return DBA::$dba->quote_interval($txt);
|
||||
$returnText = $includeInterval ? 'INTERVAL ' : '';
|
||||
return $returnText . DBA::$dba->quote_interval($txt);
|
||||
}
|
||||
|
||||
function dbesc_identifier($str)
|
||||
|
|
|
@ -97,9 +97,13 @@ function format_event_obj($jobject)
|
|||
|
||||
$event = [];
|
||||
|
||||
if (! is_array($jobject)) {
|
||||
if (is_array($jobject)) {
|
||||
$object = $jobject;
|
||||
}
|
||||
else {
|
||||
$object = json_decode($jobject, true);
|
||||
}
|
||||
|
||||
/*******
|
||||
This is our encoded format
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@ use Code\Daemon\Run;
|
|||
/**
|
||||
* @brief Create an array for hubloc table and insert record.
|
||||
*
|
||||
* Creates an assoziative array which will be inserted into the hubloc table.
|
||||
* Creates an associative array which will be inserted into the hubloc table.
|
||||
*
|
||||
* @param array $arr An assoziative array with hubloc values
|
||||
* @return bool|PDOStatement
|
||||
* @param array $arr An associative array with hubloc values
|
||||
* @return bool
|
||||
*/
|
||||
function hubloc_store_lowlevel($arr)
|
||||
{
|
||||
|
|
|
@ -1625,7 +1625,7 @@ function sync_files($channel, $files)
|
|||
'(request-target)' => 'post ' . $m['path'] . '/' . $att['hash']
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::url($channel), true, 'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::keyId($channel), true, 'sha512');
|
||||
|
||||
$x = Url::post($fetch_url . '/' . $att['hash'], $parr, [ 'filep' => $fp, 'headers' => $headers]);
|
||||
|
||||
|
@ -1717,7 +1717,7 @@ function sync_files($channel, $files)
|
|||
'(request-target)' => 'post ' . $m['path'] . '/' . $att['hash']
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::url($channel), true, 'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::keyId($channel), true, 'sha512');
|
||||
|
||||
$x = Url::post($fetch_url . '/' . $att['hash'], $parr, [ 'filep' => $fp, 'headers' => $headers]);
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ function can_comment_on_post($observer_xchan, $item)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (isset($item['owner']['xchan_network']) && $item['owner']['xchan_network'] === 'activitypub') {
|
||||
if (isset($item['owner']['xchan_network']) && in_array($item['owner']['xchan_network'], ['activitypub', 'apnomadic'])) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -3514,8 +3514,8 @@ function item_expire($uid,$days,$comment_days = 7) {
|
|||
|
||||
$r = q("SELECT id FROM item
|
||||
WHERE uid = %d
|
||||
AND created < %s - INTERVAL %s
|
||||
AND commented < %s - INTERVAL %s
|
||||
AND created < %s - %s
|
||||
AND commented < %s - %s
|
||||
AND item_retained = 0
|
||||
AND item_thread_top = 1
|
||||
AND resource_type = ''
|
||||
|
@ -3523,9 +3523,9 @@ function item_expire($uid,$days,$comment_days = 7) {
|
|||
$sql_extra $item_normal LIMIT $expire_limit ",
|
||||
intval($uid),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(intval($days) . ' DAY'),
|
||||
db_quoteinterval(intval($days) . ' DAY', true),
|
||||
db_utcnow(),
|
||||
db_quoteinterval(intval($comment_days) . ' DAY')
|
||||
db_quoteinterval(intval($comment_days) . ' DAY', true)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
|
|
|
@ -3802,7 +3802,7 @@ function array2XML($obj, $array)
|
|||
* @param string $table
|
||||
* @param array $arr
|
||||
* @param array $binary_fields - fields which will be cleansed with dbescbin rather than dbesc; this is critical for postgres
|
||||
* @return bool|PDOStatement
|
||||
* @return bool
|
||||
*/
|
||||
function create_table_from_array($table, $arr, $binary_fields = [])
|
||||
{
|
||||
|
|
|
@ -758,7 +758,7 @@ function discover_resource(string $resource, $protocol = '', $verify = true)
|
|||
}
|
||||
|
||||
$results = linksByRel($webfinger['links'], 'self');
|
||||
if ($results && ((! $protocol) || (strtolower($protocol) === 'activitypub')) ) {
|
||||
if ($results && ((! $protocol) || (in_array(strtolower($protocol), ['activitypub', 'apnomadic'])))) {
|
||||
foreach ($results as $link) {
|
||||
if (isset($link['type']) && isset($link['href'])
|
||||
&& ($link['type'] === 'application/activity+json' || str_contains($link['type'], 'ld+json'))) {
|
||||
|
|
|
@ -582,10 +582,6 @@ function check_deliver_permissions($item, $arr, $includeMentions = false)
|
|||
return($result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets site wide default permissions.
|
||||
*
|
||||
|
@ -598,23 +594,20 @@ function site_default_perms()
|
|||
|
||||
$typical = [
|
||||
'view_stream' => PERMS_PUBLIC,
|
||||
'search_stream' => PERMS_SPECIFIC,
|
||||
'deliver_stream'=> PERMS_SPECIFIC,
|
||||
'view_profile' => PERMS_PUBLIC,
|
||||
'view_contacts' => PERMS_PUBLIC,
|
||||
'view_storage' => PERMS_PUBLIC,
|
||||
'view_pages' => PERMS_PUBLIC,
|
||||
'view_wiki' => PERMS_PUBLIC,
|
||||
'send_stream' => PERMS_SPECIFIC,
|
||||
'hyperdrive' => PERMS_SPECIFIC,
|
||||
'post_wall' => PERMS_SPECIFIC,
|
||||
'post_comments' => PERMS_SPECIFIC,
|
||||
'post_mail' => PERMS_SPECIFIC,
|
||||
'tag_deliver' => PERMS_SPECIFIC,
|
||||
'chat' => PERMS_SPECIFIC,
|
||||
'write_storage' => PERMS_SPECIFIC,
|
||||
'write_pages' => PERMS_SPECIFIC,
|
||||
'write_wiki' => PERMS_SPECIFIC,
|
||||
'republish' => PERMS_SPECIFIC,
|
||||
'delegate' => PERMS_SPECIFIC,
|
||||
'post_like' => PERMS_NETWORK
|
||||
'moderated' => PERMS_SPECIFIC,
|
||||
];
|
||||
|
||||
$global_perms = Permissions::Perms();
|
||||
|
|
|
@ -9,6 +9,7 @@ use Code\Lib\Apps;
|
|||
use Code\Lib\Activity;
|
||||
use Code\Access\AccessControl;
|
||||
use Code\Access\PermissionLimits;
|
||||
use Code\Lib\Channel;
|
||||
use Code\Lib\Time;
|
||||
use Code\Web\HTTPHeaders;
|
||||
use Code\Daemon\Run;
|
||||
|
@ -266,7 +267,7 @@ function photo_upload($channel, $observer, $args)
|
|||
'rel' => 'alternate',
|
||||
'mediaType' => $type,
|
||||
'summary' => $alt_desc,
|
||||
'href' => z_root() . '/photo/' . $photo_hash . '-0.' . $ph->getExt(),
|
||||
'href' => Channel::getDidResolver($channel) . '/photo/' . $photo_hash . '-0.' . $ph->getExt(),
|
||||
'width' => $width,
|
||||
'height' => $height
|
||||
];
|
||||
|
@ -290,7 +291,7 @@ function photo_upload($channel, $observer, $args)
|
|||
'rel' => 'alternate',
|
||||
'mediaType' => $type,
|
||||
'summary' => $alt_desc,
|
||||
'href' => z_root() . '/photo/' . $photo_hash . '-1.' . $ph->getExt(),
|
||||
'href' => Channel::getDidResolver($channel) . '/photo/' . $photo_hash . '-1.' . $ph->getExt(),
|
||||
'width' => $ph->getWidth(),
|
||||
'height' => $ph->getHeight()
|
||||
];
|
||||
|
@ -309,7 +310,7 @@ function photo_upload($channel, $observer, $args)
|
|||
'rel' => 'alternate',
|
||||
'mediaType' => $type,
|
||||
'summary' => $alt_desc,
|
||||
'href' => z_root() . '/photo/' . $photo_hash . '-2.' . $ph->getExt(),
|
||||
'href' => Channel::getDidResolver($channel) . '/photo/' . $photo_hash . '-2.' . $ph->getExt(),
|
||||
'width' => $ph->getWidth(),
|
||||
'height' => $ph->getHeight()
|
||||
];
|
||||
|
@ -328,7 +329,7 @@ function photo_upload($channel, $observer, $args)
|
|||
'rel' => 'alternate',
|
||||
'mediaType' => $type,
|
||||
'summary' => $alt_desc,
|
||||
'href' => z_root() . '/photo/' . $photo_hash . '-3.' . $ph->getExt(),
|
||||
'href' => Channel::getDidResolver($channel) . '/photo/' . $photo_hash . '-3.' . $ph->getExt(),
|
||||
'width' => $ph->getWidth(),
|
||||
'height' => $ph->getHeight()
|
||||
];
|
||||
|
@ -356,7 +357,7 @@ function photo_upload($channel, $observer, $args)
|
|||
'type' => 'Link',
|
||||
'rel' => 'about',
|
||||
'mediaType' => 'text/html',
|
||||
'href' => z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash
|
||||
'href' => Channel::getDidResolver($channel) . '/photos/image/' . $photo_hash
|
||||
];
|
||||
|
||||
$item_hidden = (($visible) ? 0 : 1 );
|
||||
|
@ -391,12 +392,12 @@ function photo_upload($channel, $observer, $args)
|
|||
. "\n\n" . $alt . "\n\n"
|
||||
. ']' : '[zmg' . $alt . ']');
|
||||
|
||||
$author_link = '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $channel['channel_name'] . '[/zrl]';
|
||||
$author_link = '[zrl=' . Channel::getDidResolver($channel, true) . ']' . $channel['channel_name'] . '[/zrl]';
|
||||
|
||||
$photo_link = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' . t('a new photo') . '[/zrl]';
|
||||
$photo_link = '[zrl=' . Channel::getDidResolver($channel) . '/photos/image/' . $photo_hash . ']' . t('a new photo') . '[/zrl]';
|
||||
|
||||
if (array_path_exists('/directory/hash',$args)) {
|
||||
$album_link = '[zrl=' . z_root() . '/album/' . $channel['channel_address'] . '/' . $args['directory']['hash'] . ']' . ((strlen($album)) ? $album : '/') . '[/zrl]';
|
||||
$album_link = '[zrl=' . Channel::getDidResolver($channel) . '/album/' . $args['directory']['hash'] . ']' . ((strlen($album)) ? $album : '/') . '[/zrl]';
|
||||
$activity_format = sprintf(t('%1$s posted %2$s to %3$s', 'photo_upload'), $author_link, $photo_link, $album_link);
|
||||
}
|
||||
else {
|
||||
|
@ -407,8 +408,8 @@ function photo_upload($channel, $observer, $args)
|
|||
|
||||
// If uploaded into a post, this is the text that is returned to the webapp for inclusion in the post.
|
||||
|
||||
$obj_body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
|
||||
. $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]'
|
||||
$obj_body = '[zrl=' . Channel::getDidResolver($channel) . '/photos/image/' . $photo_hash . ']'
|
||||
. $tag . Channel::getDidResolver($channel) . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]'
|
||||
. '[/zrl]';
|
||||
|
||||
$attribution = (Activity::actorEncode(($visitor) ?: $channel, false));
|
||||
|
@ -432,7 +433,7 @@ function photo_upload($channel, $observer, $args)
|
|||
|
||||
if ($public) {
|
||||
$object['to'] = [ ACTIVITY_PUBLIC_INBOX ];
|
||||
$object['cc'] = [ z_root() . '/followers/' . $channel['channel_address'] ];
|
||||
$object['cc'] = [ Channel::getDidResolver($channel) . '/followers' ];
|
||||
} else {
|
||||
$object['to'] = Activity::map_acl(array_merge($ac, ['item_private' => 1]));
|
||||
}
|
||||
|
@ -440,8 +441,8 @@ function photo_upload($channel, $observer, $args)
|
|||
$target = [
|
||||
'type' => 'Collection',
|
||||
'name' => ((strlen($album)) ? $album : '/'),
|
||||
'id' => z_root() . '/album/' . $channel['channel_address'] . ((isset($args['folder'])) ? '/' . $args['folder'] : EMPTY_STR),
|
||||
'attributedTo' => z_root() . '/channel/' . $channel['channel_address'],
|
||||
'id' => Channel::getDidResolver($channel) . '/album/' . ((isset($args['folder'])) ? '/' . $args['folder'] : EMPTY_STR),
|
||||
'attributedTo' => Channel::getDidResolver($channel, true),
|
||||
];
|
||||
|
||||
$post_tags = [];
|
||||
|
@ -514,7 +515,7 @@ function photo_upload($channel, $observer, $args)
|
|||
}
|
||||
} else {
|
||||
$uuid = new_uuid();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
$mid = Channel::getDidResolver($channel) . '/item/' . $uuid;
|
||||
|
||||
$object['id'] = $mid;
|
||||
|
||||
|
@ -558,7 +559,7 @@ function photo_upload($channel, $observer, $args)
|
|||
$arr['term'] = $post_tags;
|
||||
}
|
||||
|
||||
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']);
|
||||
$arr['plink'] = $arr['mid'];
|
||||
|
||||
if ($lat || $lon) {
|
||||
$arr['lat'] = floatval($lat);
|
||||
|
@ -720,7 +721,7 @@ function photos_albums_list($channel, $observer, $sort_key = 'display_path', $di
|
|||
'shorttext' => (($album['album']) ? ellipsify($album['album'], 28) : '/'),
|
||||
'jstext' => (($album['album']) ? addslashes($album['album']) : '/'),
|
||||
'total' => $album['total'],
|
||||
'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . $album['folder'],
|
||||
'url' => Channel::getDidResolver($channel) . '/photos/album/' . $album['folder'],
|
||||
'urlencode' => urlencode($album['album']),
|
||||
'bin2hex' => $album['folder']
|
||||
];
|
||||
|
@ -794,7 +795,7 @@ function photos_list_photos($channel, $observer, $album = '')
|
|||
|
||||
if ($r) {
|
||||
for ($x = 0; $x < count($r); $x++) {
|
||||
$r[$x]['src'] = z_root() . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['imgscale'];
|
||||
$r[$x]['src'] = Channel::getDidResolver($channel) . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['imgscale'];
|
||||
}
|
||||
$ret['success'] = true;
|
||||
$ret['photos'] = $r;
|
||||
|
|
|
@ -745,7 +745,7 @@ function get_security_ids($channel_id, $ob_hash)
|
|||
if ($xchans[0]['xchan_network'] === 'zot6') {
|
||||
$groups[] = 'zot:' . $rv['channel_hash'];
|
||||
}
|
||||
if ($xchans[0]['xchan_network'] === 'activitypub') {
|
||||
if (in_array($xchans[0]['xchan_network'], ['activitypub', 'apnomadic'])) {
|
||||
$groups[] = 'activitypub:' . $rv['channel_hash'];
|
||||
}
|
||||
}
|
||||
|
|
44
index.php
44
index.php
|
@ -6,9 +6,49 @@ namespace Code\Web;
|
|||
* @file index.php
|
||||
*
|
||||
* @brief The main entry point to the application.
|
||||
*
|
||||
*/
|
||||
|
||||
use App\Kernel;
|
||||
use App\LegacyBridge;
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
use Symfony\Component\ErrorHandler\Debug;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
require_once 'src/Web/WebServer.php';
|
||||
|
||||
$server = new WebServer();
|
||||
$server->run();
|
||||
(new Dotenv())->bootEnv('.env');
|
||||
|
||||
global $kernel;
|
||||
|
||||
if ($_SERVER['APP_DEBUG']) {
|
||||
umask(0000);
|
||||
|
||||
Debug::enable();
|
||||
}
|
||||
|
||||
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) {
|
||||
Request::setTrustedProxies(
|
||||
explode(',', $trustedProxies),
|
||||
Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO
|
||||
);
|
||||
}
|
||||
|
||||
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) {
|
||||
Request::setTrustedHosts([$trustedHosts]);
|
||||
}
|
||||
|
||||
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
||||
$request = Request::createFromGlobals();
|
||||
$response = $kernel->handle($request);
|
||||
|
||||
if (false === $response->isNotFound()) {
|
||||
// Symfony successfully handled the route.
|
||||
$response->send();
|
||||
} else {
|
||||
$server = new WebServer();
|
||||
$server->run($request, $response, __DIR__);
|
||||
}
|
||||
|
||||
$kernel->terminate($request, $response);
|
||||
|
|
|
@ -18,6 +18,7 @@ $db_user = 'mysqlusername';
|
|||
$db_pass = 'mysqlpassword';
|
||||
$db_data = 'mysqldatabasename';
|
||||
$db_type = 0; // use 1 for postgres, 0 for mysql
|
||||
$db_vrsn = ''; // Required for doctrine
|
||||
|
||||
/*
|
||||
* Notice: Many of the following settings will be available in the admin panel
|
||||
|
|
0
migrations/.gitignore
vendored
Normal file
0
migrations/.gitignore
vendored
Normal file
9
public/index.php
Normal file
9
public/index.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
|
@ -49,6 +49,42 @@ class Permissions
|
|||
return 3;
|
||||
}
|
||||
|
||||
|
||||
public $permsMap = [
|
||||
'view_stream' => 'viewStream',
|
||||
'search_stream' => 'canSearch',
|
||||
'deliver_stream' => 'deliverStream',
|
||||
'view_profile' => 'viewProfile',
|
||||
'view_contacts' => 'viewContacts',
|
||||
'view_storage' => 'viewFiles',
|
||||
'post_wall' => 'postHome',
|
||||
'post_mail' => 'postMail',
|
||||
'send_stream' => 'sendStream',
|
||||
'hyperdrive' => 'sendPublic',
|
||||
'post_comments' => 'canReply',
|
||||
'write_storage' => 'writeFiles',
|
||||
'republish' => 'canReAuthor',
|
||||
'moderated' => 'isModerated',
|
||||
'delegate' => 'isModerator',
|
||||
];
|
||||
|
||||
|
||||
function map($permission)
|
||||
{
|
||||
return $this->permsMap[$permission] ?? $permission;
|
||||
}
|
||||
|
||||
function unmap($permission)
|
||||
{
|
||||
foreach ($this->permsMap as $key => $value) {
|
||||
if ($permission === $value) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return $permission;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return an array with Permissions.
|
||||
*
|
||||
|
@ -298,7 +334,7 @@ class Permissions
|
|||
$n = [];
|
||||
if ($p) {
|
||||
foreach ($p as $k => $v) {
|
||||
if (intval($v)) {
|
||||
if ((int)$v) {
|
||||
$n[] = $k;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ class Actor extends ASObject
|
|||
public $outbox;
|
||||
public $followers;
|
||||
public $following;
|
||||
public $permissions; /* extension property */
|
||||
public $endpoints;
|
||||
public $publicKey;
|
||||
public $preferredUsername;
|
||||
|
@ -23,7 +24,9 @@ class Actor extends ASObject
|
|||
public $canSearch;
|
||||
public $indexable;
|
||||
public $assertionMethod;
|
||||
public $aliases;
|
||||
public $gateways;
|
||||
public $openwebauth;
|
||||
public $authredirect;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
|
@ -353,21 +356,73 @@ class Actor extends ASObject
|
|||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAliases()
|
||||
public function getGateways()
|
||||
{
|
||||
return $this->aliases;
|
||||
return $this->gateways;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $aliasess
|
||||
* @param mixed $gateways
|
||||
* @return Actor
|
||||
*/
|
||||
public function setAliases($aliases)
|
||||
public function setGateways($gateways)
|
||||
{
|
||||
$this->aliases = $aliases;
|
||||
$this->gateways = $gateways;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPermissions()
|
||||
{
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $permissions
|
||||
* @return Actor
|
||||
*/
|
||||
public function setPermissions($permissions)
|
||||
{
|
||||
$this->permissions = $permissions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOpenwebauth()
|
||||
{
|
||||
return $this->openwebauth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $openwebauth
|
||||
* @return Actor
|
||||
*/
|
||||
public function setOpenwebauth($openwebauth)
|
||||
{
|
||||
$this->openwebauth = $openwebauth;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAuthredirect()
|
||||
{
|
||||
return $this->authredirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $authredirect
|
||||
* @return Actor
|
||||
*/
|
||||
public function setAuthredirect($authredirect)
|
||||
{
|
||||
$this->authredirect = $authredirect;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,16 +4,18 @@ namespace Code\ActivityStreams;
|
|||
|
||||
class Collection extends ASObject
|
||||
{
|
||||
public $totalItems;
|
||||
public $current;
|
||||
public $first;
|
||||
public $last;
|
||||
public $items;
|
||||
public int $totalItems;
|
||||
public string $current;
|
||||
public string $first;
|
||||
public string $last;
|
||||
public array $items;
|
||||
|
||||
public mixed $collectionOf;
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalItems()
|
||||
public function getTotalItems(): int
|
||||
{
|
||||
return $this->totalItems;
|
||||
}
|
||||
|
@ -22,16 +24,16 @@ class Collection extends ASObject
|
|||
* @param mixed $totalItems
|
||||
* @return Collection
|
||||
*/
|
||||
public function setTotalItems($totalItems)
|
||||
public function setTotalItems(mixed $totalItems): static
|
||||
{
|
||||
$this->totalItems = $totalItems;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrent()
|
||||
public function getCurrent(): string
|
||||
{
|
||||
return $this->current;
|
||||
}
|
||||
|
@ -40,16 +42,16 @@ class Collection extends ASObject
|
|||
* @param mixed $current
|
||||
* @return Collection
|
||||
*/
|
||||
public function setCurrent($current)
|
||||
public function setCurrent(mixed $current): static
|
||||
{
|
||||
$this->current = $current;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getFirst()
|
||||
public function getFirst(): string
|
||||
{
|
||||
return $this->first;
|
||||
}
|
||||
|
@ -58,16 +60,16 @@ class Collection extends ASObject
|
|||
* @param mixed $first
|
||||
* @return Collection
|
||||
*/
|
||||
public function setFirst($first)
|
||||
public function setFirst(mixed $first): static
|
||||
{
|
||||
$this->first = $first;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getLast()
|
||||
public function getLast(): string
|
||||
{
|
||||
return $this->last;
|
||||
}
|
||||
|
@ -76,16 +78,16 @@ class Collection extends ASObject
|
|||
* @param mixed $last
|
||||
* @return Collection
|
||||
*/
|
||||
public function setLast($last)
|
||||
public function setLast(mixed $last): static
|
||||
{
|
||||
$this->last = $last;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return array
|
||||
*/
|
||||
public function getItems()
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
@ -94,11 +96,29 @@ class Collection extends ASObject
|
|||
* @param mixed $items
|
||||
* @return Collection
|
||||
*/
|
||||
public function setItems($items)
|
||||
public function setItems(mixed $items): static
|
||||
{
|
||||
$this->items = $items;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCollectionOf(): mixed
|
||||
{
|
||||
return $this->collectionOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $collectionOf
|
||||
* @return Collection
|
||||
*/
|
||||
public function setCollectionOf(mixed $collectionOf): static
|
||||
{
|
||||
$this->collectionOf = $collectionOf;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
0
src/ApiResource/.gitignore
vendored
Normal file
0
src/ApiResource/.gitignore
vendored
Normal file
0
src/Controller/.gitignore
vendored
Normal file
0
src/Controller/.gitignore
vendored
Normal file
|
@ -33,9 +33,9 @@ class Checksites implements DaemonInterface
|
|||
}
|
||||
|
||||
$r = q(
|
||||
"select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
|
||||
"select * from site where site_dead = 0 and site_update < %s - %s and site_type = %d $sql_options ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval($days . ' DAY'),
|
||||
db_quoteinterval($days . ' DAY', true),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class Content_importer implements DaemonInterface
|
|||
'(request-target)' => 'get /api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::url($channel), true, 'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::keyId($channel), true, 'sha512');
|
||||
|
||||
$x = Url::get($hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page, [ 'headers' => $headers ]);
|
||||
|
||||
|
|
|
@ -92,9 +92,9 @@ class Cron implements DaemonInterface
|
|||
// Ensure that every channel pings their directory occasionally.
|
||||
$interval = floatval(Config::Get('system','delivery_interval', 2));
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_dirdate < %s - INTERVAL %s and channel_removed = 0",
|
||||
"select channel_id from channel where channel_dirdate < %s - %s and channel_removed = 0",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
db_quoteinterval('7 DAY', true)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
|
@ -162,9 +162,9 @@ class Cron implements DaemonInterface
|
|||
|
||||
$r = q(
|
||||
"select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
|
||||
and xchan_photo_date < %s - INTERVAL %s",
|
||||
and xchan_photo_date < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 DAY')
|
||||
db_quoteinterval('1 DAY', true)
|
||||
);
|
||||
if ($r) {
|
||||
require_once('include/photo_factory.php');
|
||||
|
|
|
@ -42,17 +42,17 @@ class Cron_daily implements DaemonInterface
|
|||
// expire any read notifications over a month old
|
||||
|
||||
q(
|
||||
"delete from notify where seen = 1 and created < %s - INTERVAL %s",
|
||||
"delete from notify where seen = 1 and created < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('60 DAY')
|
||||
db_quoteinterval('60 DAY', true)
|
||||
);
|
||||
|
||||
// expire any unread notifications over a year old
|
||||
|
||||
q(
|
||||
"delete from notify where seen = 0 and created < %s - INTERVAL %s",
|
||||
"delete from notify where seen = 0 and created < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 YEAR')
|
||||
db_quoteinterval('1 YEAR', true)
|
||||
);
|
||||
|
||||
// expire old delivery reports
|
||||
|
@ -63,17 +63,17 @@ class Cron_daily implements DaemonInterface
|
|||
}
|
||||
|
||||
q(
|
||||
"delete from dreport where dreport_time < %s - INTERVAL %s",
|
||||
"delete from dreport where dreport_time < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval($keep_reports . ' DAY')
|
||||
db_quoteinterval($keep_reports . ' DAY', true)
|
||||
);
|
||||
|
||||
// delete accounts that did not submit email verification within 3 days
|
||||
|
||||
$r = q(
|
||||
"select * from register where password = 'verify' and created < %s - INTERVAL %s",
|
||||
"select * from register where password = 'verify' and created < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
db_quoteinterval('3 DAY', true)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
|
|
|
@ -35,11 +35,11 @@ class Cron_weekly implements DaemonInterface
|
|||
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_removed = 1 and
|
||||
channel_deleted > %s - INTERVAL %s and channel_deleted < %s - INTERVAL %s",
|
||||
channel_deleted > %s - %s and channel_deleted < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('21 DAY'),
|
||||
db_quoteinterval('21 DAY', true),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('10 DAY')
|
||||
db_quoteinterval('10 DAY', true)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
|
@ -50,9 +50,9 @@ class Cron_weekly implements DaemonInterface
|
|||
// get rid of ancient poco records
|
||||
|
||||
q(
|
||||
"delete from xlink where xlink_updated < %s - INTERVAL %s and xlink_static = 0 ",
|
||||
"delete from xlink where xlink_updated < %s - %s and xlink_static = 0 ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 DAY')
|
||||
db_quoteinterval('14 DAY', true)
|
||||
);
|
||||
|
||||
// Check for dead sites
|
||||
|
|
|
@ -21,9 +21,9 @@ class Expire implements DaemonInterface
|
|||
// so notifications should have been delivered.
|
||||
|
||||
$pending_deletes = q(
|
||||
"select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
|
||||
"select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('4 DAY')
|
||||
db_quoteinterval('4 DAY', true)
|
||||
);
|
||||
if ($pending_deletes) {
|
||||
foreach ($pending_deletes as $item) {
|
||||
|
|
|
@ -37,7 +37,7 @@ class File_importer implements DaemonInterface
|
|||
'(request-target)' => 'get /api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id,
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::url($channel), true, 'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::keyId($channel), true, 'sha512');
|
||||
$x = Url::get($hz_server . '/api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id, [ 'headers' => $headers ]);
|
||||
|
||||
if (! $x['success']) {
|
||||
|
|
|
@ -34,7 +34,7 @@ class Gprobe implements DaemonInterface
|
|||
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
if ($rv['hubloc_network'] === 'activitypub') {
|
||||
if (in_array($rv['hubloc_network'], ['activitypub', 'apnomadic'])) {
|
||||
$protocols[] = 'activitypub';
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -38,9 +38,9 @@ class Importdoc implements DaemonInterface
|
|||
}
|
||||
// remove old files that weren't updated (indicates they were most likely deleted).
|
||||
$i = q(
|
||||
"select * from item where item_type = 5 and edited < %s - INTERVAL %s",
|
||||
"select * from item where item_type = 5 and edited < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 DAY')
|
||||
db_quoteinterval('14 DAY', true)
|
||||
);
|
||||
if ($i) {
|
||||
foreach ($i as $iv) {
|
||||
|
|
|
@ -220,7 +220,7 @@ class Notifier implements DaemonInterface
|
|||
|
||||
$r = q(
|
||||
"select abook_xchan from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_channel = %d and xchan_network != 'activitypub'",
|
||||
where abook_channel = %d and not xchan_network in ('activitypub', 'apnomadic')",
|
||||
intval($item_id)
|
||||
);
|
||||
|
||||
|
|
|
@ -167,10 +167,10 @@ class Onepoll implements DaemonInterface
|
|||
|
||||
$r = q(
|
||||
"SELECT xlink_id from xlink
|
||||
where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
|
||||
where xlink_xchan = '%s' and xlink_updated > %s - %s and xlink_static = 0 limit 1",
|
||||
intval($contact['xchan_hash']),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
db_quoteinterval('7 DAY', true)
|
||||
);
|
||||
if (! $r) {
|
||||
Socgraph::poco_load($contact['xchan_hash'], $contact['xchan_connurl']);
|
||||
|
|
|
@ -18,27 +18,27 @@ class Queue implements DaemonInterface
|
|||
// delete all queue items more than 3 days old
|
||||
// but first mark these sites dead if we haven't heard from them in a month
|
||||
|
||||
$oldqItems = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
|
||||
$oldqItems = q("select outq_posturl from outq where outq_created < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
db_quoteinterval('3 DAY', true)
|
||||
);
|
||||
if ($oldqItems) {
|
||||
foreach ($oldqItems as $qItem) {
|
||||
$h = parse_url($qItem['outq_posturl']);
|
||||
$site_url = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
|
||||
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - %s",
|
||||
dbesc($site_url),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 MONTH')
|
||||
db_quoteinterval('1 MONTH', true)
|
||||
);
|
||||
}
|
||||
logger('Removing ' . count($oldqItems) . ' old queue entries');
|
||||
}
|
||||
|
||||
|
||||
q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
|
||||
q("DELETE FROM outq WHERE outq_created < %s - %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
db_quoteinterval('3 DAY', true)
|
||||
);
|
||||
|
||||
$deliveries = [];
|
||||
|
|
17
src/DataFixtures/AppFixtures.php
Normal file
17
src/DataFixtures/AppFixtures.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\DataFixtures;
|
||||
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class AppFixtures extends Fixture
|
||||
{
|
||||
public function load(ObjectManager $manager): void
|
||||
{
|
||||
// $product = new Product();
|
||||
// $manager->persist($product);
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
0
src/Entity/.gitignore
vendored
Normal file
0
src/Entity/.gitignore
vendored
Normal file
12
src/Kernel.php
Normal file
12
src/Kernel.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
|
||||
class Kernel extends BaseKernel
|
||||
{
|
||||
use MicroKernelTrait;
|
||||
|
||||
}
|
|
@ -272,7 +272,7 @@ class AccessList
|
|||
$sql_extra = " and xchan_network in ('nomad','zot6') ";
|
||||
break;
|
||||
case '3':
|
||||
$sql_extra = " and xchan_network = 'activitypub' ";
|
||||
$sql_extra = " and xchan_network in ('activitypub', 'apnomadic') ";
|
||||
break;
|
||||
case '1':
|
||||
default:
|
||||
|
@ -473,7 +473,7 @@ class AccessList
|
|||
$sql_extra = " and xchan_network in ('nomad','zot6') ";
|
||||
}
|
||||
if (str_starts_with($gv, 'activitypub:')) {
|
||||
$sql_extra = " and xchan_network = 'activitypub' ";
|
||||
$sql_extra = " and xchan_network in ('activitypub', 'apnomadic') ";
|
||||
}
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_hash = '%s' ",
|
||||
|
|
|
@ -181,11 +181,11 @@ class Activity
|
|||
|
||||
$site_url = unparse_url(['scheme' => $parsed['scheme'], 'host' => $parsed['host'], 'port' => ((array_key_exists('port', $parsed) && intval($parsed['port'])) ? $parsed['port'] : 0)]);
|
||||
q(
|
||||
"update site set site_update = '%s' where site_url = '%s' and site_update < %s - INTERVAL %s",
|
||||
"update site set site_update = '%s' where site_url = '%s' and site_update < %s - %s",
|
||||
dbesc(Time::convert()),
|
||||
dbesc($site_url),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 DAY')
|
||||
db_quoteinterval('1 DAY', true)
|
||||
);
|
||||
|
||||
// check for a valid signature, but only if this is not an actor object. If it is signed, it must be valid.
|
||||
|
@ -290,7 +290,7 @@ class Activity
|
|||
return false;
|
||||
}
|
||||
|
||||
public static function paged_collection_init($total, $id, $type = 'OrderedCollection', $attributedTo = ''): array
|
||||
public static function paged_collection_init($total, $id, $type = 'OrderedCollection', $collectionOf = '', $attributedTo = ''): array
|
||||
{
|
||||
|
||||
$ret = [
|
||||
|
@ -298,6 +298,9 @@ class Activity
|
|||
'type' => $type,
|
||||
'totalItems' => $total,
|
||||
];
|
||||
if ($collectionOf) {
|
||||
$ret['collectionOf'] = $collectionOf;
|
||||
}
|
||||
|
||||
$numpages = $total / App::$pager['itemspage'];
|
||||
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
|
||||
|
@ -351,6 +354,7 @@ class Activity
|
|||
$ret = [
|
||||
'id' => z_root() . '/' . $id,
|
||||
'type' => $type,
|
||||
'collectionOf' => 'Activity',
|
||||
'totalItems' => $total,
|
||||
];
|
||||
if ($attributedTo) {
|
||||
|
@ -464,6 +468,7 @@ class Activity
|
|||
$ret = [
|
||||
'id' => z_root() . '/' . $id,
|
||||
'type' => $type . 'Page',
|
||||
'collectionOf' => 'actor',
|
||||
];
|
||||
|
||||
$numpages = $total / App::$pager['itemspage'];
|
||||
|
@ -484,6 +489,7 @@ class Activity
|
|||
$ret = [
|
||||
'id' => z_root() . '/' . $id,
|
||||
'type' => $type,
|
||||
'collectionOf' => 'actor',
|
||||
'totalItems' => $total,
|
||||
];
|
||||
}
|
||||
|
@ -495,7 +501,7 @@ class Activity
|
|||
if ($items) {
|
||||
$x = [];
|
||||
foreach ($items as $i) {
|
||||
if ($i['xchan_network'] === 'activitypub') {
|
||||
if (in_array($i['xchan_network'], ['activitypub', 'apnomadic'])) {
|
||||
$x[] = $i['xchan_hash'];
|
||||
} else {
|
||||
$x[] = $i['xchan_url'];
|
||||
|
@ -512,12 +518,33 @@ class Activity
|
|||
return $ret;
|
||||
}
|
||||
|
||||
public static function map_permissions(array $permissions): array
|
||||
{
|
||||
$perm = new Permissions();
|
||||
$returnValue = [];
|
||||
foreach($permissions as $permission) {
|
||||
$returnValue[] = 'https://purl.org/nomad#' . $perm->map($permission);
|
||||
}
|
||||
return $returnValue;
|
||||
}
|
||||
|
||||
public static function encode_simple_collection($items, $id, $type, $total = 0, $extra = null): array
|
||||
|
||||
public static function unmap_permissions(array $permissions): array
|
||||
{
|
||||
$perm = new Permissions();
|
||||
$returnValue = [];
|
||||
foreach($permissions as $permission) {
|
||||
$returnValue[] = $perm->unmap(trim('#', strstr($permission, '#')));
|
||||
}
|
||||
return $returnValue;
|
||||
}
|
||||
|
||||
|
||||
public static function encode_simple_collection($items, $id, $type, $total = 0, array $extra = []): array
|
||||
{
|
||||
|
||||
$ret = [
|
||||
'id' => z_root() . '/' . $id,
|
||||
'id' => $id,
|
||||
'type' => $type,
|
||||
'totalItems' => $total,
|
||||
];
|
||||
|
@ -1081,6 +1108,7 @@ class Activity
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
$activity = self::encodeAddressing($activity, $item);
|
||||
|
||||
return $activity;
|
||||
|
@ -1096,7 +1124,6 @@ class Activity
|
|||
return $locations;
|
||||
}
|
||||
|
||||
|
||||
public static function encode_item($item, $activitypub = false)
|
||||
{
|
||||
$activity = [];
|
||||
|
@ -1187,7 +1214,7 @@ class Activity
|
|||
}
|
||||
}
|
||||
|
||||
$activity['attributedTo'] = self::actorEncode($item['author'],false);
|
||||
$activity['attributedTo'] = Channel::getDidResolver($item['author'], true);
|
||||
|
||||
if ($item['mid'] === $item['parent_mid']) {
|
||||
if (in_array($item['comment_policy'], ['self', 'none']) || $item['item_nocomment'] || ($item['comments_closed'] > NULL_DATE && Time::convert('UTC', 'UTC', $item['comments_closed']) <= Time::convert())) {
|
||||
|
@ -1195,7 +1222,7 @@ class Activity
|
|||
} elseif (in_array($item['comment_policy'], ['public', 'authenticated'])) {
|
||||
$activity['canReply'] = [ACTIVITY_PUBLIC_INBOX];
|
||||
} elseif (in_array($item['comment_policy'], ['contacts', 'specific'])) {
|
||||
$activity['canReply'] = [z_root() . '/followers/' . substr($item['author']['xchan_addr'], 0, strpos($item['author']['xchan_addr'], '@'))];
|
||||
$activity['canReply'] = [Channel::getDidResolver($item['author']) . '/followers'];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1445,6 +1472,7 @@ class Activity
|
|||
if (isset($parent_i['to']) && is_array($parent_i['to'])) {
|
||||
$activity['to'] = array_merge_clean($activity['to'], $parent_i['to']);
|
||||
}
|
||||
|
||||
} elseif ((int)$item['item_private'] === 1) {
|
||||
if (($audience & AUDIENCE_FOLLOWERS) && $item['item_origin']) {
|
||||
$activity['to'] = $followers;
|
||||
|
@ -1557,7 +1585,7 @@ class Activity
|
|||
$split = explode(':', $t, 2);
|
||||
$listChannel = Channel::from_hash($split[1]);
|
||||
if ($listChannel) {
|
||||
$ret[] = z_root() . '/followers/' . $listChannel['channel_address'];
|
||||
$ret[] = Channel::getDidResolver($listChannel) . '/followers' ;
|
||||
}
|
||||
else {
|
||||
$ret[] = z_root() . '/lists/' . $t;
|
||||
|
@ -1603,17 +1631,49 @@ class Activity
|
|||
return array_values(array_unique($ret));
|
||||
}
|
||||
|
||||
public static function portableActor($arr)
|
||||
{
|
||||
$output = [];
|
||||
foreach ($arr as $key => $value) {
|
||||
if ($key === 'webfinger') {
|
||||
continue;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$output[$key] = self::portableActor($value);
|
||||
} elseif (is_string($value)) {
|
||||
$output[$key] = str_replace(z_root() . '/.well-known/apgateway/', 'ap://', $value);
|
||||
} else {
|
||||
$output[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UnhandledElementException
|
||||
*/
|
||||
public static function actorEncode($p, $extended = true, $activitypub = false)
|
||||
public static function actorEncode($p, $extended = true, $activitypub = false, $export = false, $legacy = false)
|
||||
{
|
||||
|
||||
|
||||
$actor = new Actor();
|
||||
$currhub = false;
|
||||
$aliases =[];
|
||||
$gateways =[];
|
||||
$nomadic = false;
|
||||
|
||||
$channel = ((array_key_exists('channel_id', $p)) ? $p : Channel::from_hash($p['xchan_hash']));
|
||||
|
||||
if ($channel) {
|
||||
$nomadic = (int)PConfig::Get($channel['channel_id'], 'system', 'nomadicAP');
|
||||
if ($legacy) {
|
||||
$nomadic = false;
|
||||
}
|
||||
if ($nomadic && !$extended) {
|
||||
return Channel::getDidResolver($channel, true);
|
||||
}
|
||||
if ($export) {
|
||||
$nomadic = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!$p['xchan_url']) {
|
||||
return $actor->toArray();
|
||||
|
@ -1638,30 +1698,52 @@ class Activity
|
|||
return $current_url;
|
||||
}
|
||||
|
||||
$c = ((array_key_exists('channel_id', $p)) ? $p : Channel::from_hash($p['xchan_hash']));
|
||||
|
||||
$actor->setType('Person');
|
||||
$auto_follow = false;
|
||||
|
||||
if ($c) {
|
||||
$role = PConfig::Get($c['channel_id'], 'system', 'permissions_role');
|
||||
if ($channel) {
|
||||
$role = PConfig::Get($channel['channel_id'], 'system', 'permissions_role');
|
||||
if (str_contains($role, 'forum')) {
|
||||
$actor->setType('Group');
|
||||
}
|
||||
$auto_follow = intval(PConfig::Get($c['channel_id'],'system','autoperms'));
|
||||
$nomadic = (int) PConfig::Get($c['channel_id'], 'system', 'nomadicAP');
|
||||
$auto_follow = intval(PConfig::Get($channel['channel_id'],'system','autoperms'));
|
||||
}
|
||||
|
||||
if ($c) {
|
||||
$locations = self::nomadic_locations(['author_xchan' => $c['channel_hash']]);
|
||||
$aka = [];
|
||||
if ($channel) {
|
||||
$locations = self::nomadic_locations(['author_xchan' => $channel['channel_hash']]);
|
||||
$aplocations = self::nomadic_locations(['author_xchan' => Channel::getDid($channel)]);
|
||||
$aka[] = Channel::getDidResolver($channel, true);
|
||||
$aka[] = z_root() . '/.well-known/nomad-gateway/' . $channel['xchan_hash'] . '/actor';
|
||||
$aka[] = z_root() . '/channel/' . $channel['channel_address'];
|
||||
$gateways[] = z_root();
|
||||
if ($locations) {
|
||||
foreach ($locations as $location) {
|
||||
$aliases[] = $location['hubloc_id_url'];
|
||||
if ($location['hubloc_url'] === z_root()) {
|
||||
continue;
|
||||
}
|
||||
$actor->setAliases($aliases);
|
||||
if (! in_array($location['hubloc_url'], $gateways)) {
|
||||
$gateways[] = $location['hubloc_url'];
|
||||
}
|
||||
if (! in_array($location['hubloc_url'] . '/.well-known/nomad-gateway/' . $location['hubloc_hash'] . '/actor', $aka)) {
|
||||
$aka[] = $location['hubloc_url'] . '/.well-known/nomad-gateway/' . $location['hubloc_hash'] . '/actor';
|
||||
}
|
||||
if (! in_array($location['hubloc_id_url'], $aka)) {
|
||||
$aka[] = $location['hubloc_id_url'];
|
||||
}
|
||||
}
|
||||
foreach ($aplocations as $location) {
|
||||
if (! in_array($location['hubloc_url'], $gateways)) {
|
||||
$gateways[] = $location['hubloc_url'];
|
||||
}
|
||||
if (! in_array($location['hubloc_id_url'], $aka)) {
|
||||
$aka[] = $location['hubloc_id_url'];
|
||||
}
|
||||
}
|
||||
$actor->setAlsoKnownAs($aka);
|
||||
$actor->setGateways($gateways);
|
||||
}
|
||||
$actor->setId($nomadic ? Channel::getDidResolver($channel, true) : Channel::url($channel));
|
||||
|
||||
$actor->setId($nomadic ? Channel::getDidResolver($c) : Channel::url($c));
|
||||
} else {
|
||||
$actor->setId((str_starts_with($p['xchan_hash'], 'http')) ? $p['xchan_hash'] : $current_url);
|
||||
}
|
||||
|
@ -1685,40 +1767,42 @@ class Activity
|
|||
$actor->setLocation((new Place(['type' => 'Place', 'name' => $p['channel_location']])));
|
||||
}
|
||||
|
||||
$tag = [
|
||||
['type' => 'Note', 'name' => 'Protocol', 'content' => 'zot6'],
|
||||
['type' => 'Note', 'name' => 'Protocol', 'content' => 'nomad']
|
||||
];
|
||||
$protocols = [ 'nomad', 'zot6'];
|
||||
$tags = [];
|
||||
|
||||
if ($activitypub && get_config('system', 'activitypub', ACTIVITYPUB_ENABLED)) {
|
||||
if ($c) {
|
||||
if (get_pconfig($c['channel_id'], 'system', 'activitypub', ACTIVITYPUB_ENABLED)) {
|
||||
$actor->setInbox($nomadic ? Channel::getDidResolver($c) . '/inbox' : z_root() . '/inbox/' . $c['channel_address']);
|
||||
$tag[] = ['type' => 'Note', 'name' => 'Protocol', 'content' => 'activitypub'];
|
||||
if ($channel) {
|
||||
if (get_pconfig($channel['channel_id'], 'system', 'activitypub', ACTIVITYPUB_ENABLED)) {
|
||||
$actor->setInbox($nomadic ? Channel::getDidResolver($channel) . '/actor/inbox' : z_root() . '/inbox/' . $channel['channel_address']);
|
||||
$protocols[] = 'activitypub';
|
||||
}
|
||||
|
||||
$actor->setOutbox($nomadic ? Channel::getDidResolver($c) . '/outbox' : z_root() . '/outbox/' . $c['channel_address']);
|
||||
$actor->setFollowers($nomadic ? Channel::getDidResolver($c) . '/followers' : z_root() . '/followers/' . $c['channel_address']);
|
||||
$actor->setFollowing($nomadic ? Channel::getDidResolver($c) . '/following' : z_root() . '/following/' . $c['channel_address']);
|
||||
$actor->setWebfinger('acct:' . $c['channel_address'] . '@' . App::get_hostname());
|
||||
$tags[] = ['type' => 'Note', 'name' => 'Protocols', 'content' => implode(',', $protocols)];
|
||||
$actor->setOutbox($nomadic ? Channel::getDidResolver($channel) . '/actor/outbox' : z_root() . '/outbox/' . $channel['channel_address']);
|
||||
$actor->setFollowers($nomadic ? Channel::getDidResolver($channel) . '/actor/followers' : z_root() . '/followers/' . $channel['channel_address']);
|
||||
$actor->setFollowing($nomadic ? Channel::getDidResolver($channel) . '/actor/following' : z_root() . '/following/' . $channel['channel_address']);
|
||||
$actor->setPermissions($nomadic ? Channel::getDidResolver($channel) . '/actor/permissions' : z_root() . '/permissions/' . $channel['channel_address']);
|
||||
$actor->setWebfinger('acct:' . $channel['channel_address'] . '@' . App::get_hostname());
|
||||
|
||||
$actor->setEndpoints([
|
||||
'sharedInbox' => z_root() . '/inbox',
|
||||
'oauthRegistrationEndpoint' => z_root() . '/api/client/register',
|
||||
'oauthAuthorizationEndpoint' => z_root() . '/authorize',
|
||||
'oauthTokenEndpoint' => z_root() . '/token',
|
||||
'searchContent' => z_root() . '/search/' . $c['channel_address'] . '?search={}',
|
||||
'searchTags' => z_root() . '/search/' . $c['channel_address'] . '?tag={}',
|
||||
'searchContent' => z_root() . '/search/' . $channel['channel_address'] . '?search={}',
|
||||
'searchTags' => z_root() . '/search/' . $channel['channel_address'] . '?tag={}',
|
||||
'openwebauth' => z_root() . '/owa',
|
||||
'authredirect' => z_root() . '/magic'
|
||||
]);
|
||||
|
||||
$actor->setDiscoverable((bool)((1 - intval($p['xchan_hidden']))));
|
||||
|
||||
$searchPerm = PermissionLimits::Get($c['channel_id'], 'search_stream');
|
||||
$searchPerm = PermissionLimits::Get($channel['channel_id'], 'search_stream');
|
||||
if ($searchPerm === PERMS_PUBLIC) {
|
||||
$actor->setCanSearch([ ACTIVITY_PUBLIC_INBOX ]);
|
||||
$actor->setIndexable(true);
|
||||
}
|
||||
elseif (in_array($searchPerm, [ PERMS_SPECIFIC, PERMS_CONTACTS])) {
|
||||
$actor->setCanSearch([z_root() . '/followers/' . $c['channel_address']]);
|
||||
$actor->setCanSearch([z_root() . '/followers/' . $channel['channel_address']]);
|
||||
$actor->setIndexable(false);
|
||||
}
|
||||
else {
|
||||
|
@ -1733,18 +1817,18 @@ class Activity
|
|||
|
||||
|
||||
$actor->setPublicKey([
|
||||
'id' => $current_url . '?operation=rsakey',
|
||||
'owner' => $current_url,
|
||||
'id' => (($nomadic) ? Channel::getDidResolver($channel, true) : $current_url) . '#rsakey',
|
||||
'owner' => $nomadic ? Channel::getDidResolver($channel, true) : $current_url,
|
||||
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
|
||||
'publicKeyPem' => $p['xchan_pubkey']
|
||||
]);
|
||||
|
||||
$ed25519publicKey = (new Multibase())->publicKey($c['channel_epubkey']);
|
||||
$ed25519publicKey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
$actor->setAssertionMethod(new AssertionMethod([
|
||||
[
|
||||
'id' => $nomadic ? Channel::getDidResolver($c) . '?operation=ed25519key' : $current_url . '#' . $ed25519publicKey,
|
||||
'id' => $nomadic ? Channel::getDidResolver($channel, true) . '#ed25519key' : $current_url . '#' . $ed25519publicKey,
|
||||
'type' => 'Multikey',
|
||||
'controller' => $nomadic ? Channel::getDidResolver($c) : $current_url,
|
||||
'controller' => $nomadic ? Channel::getDid($channel) : $current_url,
|
||||
'publicKeyMultibase' => $ed25519publicKey,
|
||||
]
|
||||
]));
|
||||
|
@ -1755,7 +1839,7 @@ class Activity
|
|||
|
||||
$locations = [];
|
||||
$nomadicLocations = [];
|
||||
$locs = Libzot::encode_locations($c);
|
||||
$locs = Libzot::encode_locations($channel);
|
||||
if ($locs) {
|
||||
foreach ($locs as $loc) {
|
||||
if ($loc['url'] !== z_root()) {
|
||||
|
@ -1770,10 +1854,10 @@ class Activity
|
|||
'id' => $loc->getIdUrl(),
|
||||
'url' => $loc->getIdUrl(),
|
||||
'signature' => [
|
||||
'id' => $loc->getIdUrl() . '?operation=rsakey',
|
||||
'id' => $loc->getIdUrl() . '#rsakey',
|
||||
'nonce' => random_string(),
|
||||
'creator' => $loc->getIdUrl(),
|
||||
'signature' => base64_encode(Crypto::sign($loc->getIdUrl(), $c['channel_prvkey'])),
|
||||
'signature' => base64_encode(Crypto::sign($loc->getIdUrl(), $channel['channel_prvkey'])),
|
||||
],
|
||||
];
|
||||
$nomadicLocations[] = $entry;
|
||||
|
@ -1795,13 +1879,13 @@ class Activity
|
|||
// And set the value to the URL of your Mastodon profile.
|
||||
// Then go back to Mastodon and move your account.
|
||||
|
||||
$move_id = PConfig::Get($c['channel_id'],'system','movefrom');
|
||||
$move_id = PConfig::Get($channel['channel_id'],'system','movefrom');
|
||||
if ($move_id) {
|
||||
$actor->setMovedTo(z_root() . '/channel/' . $c['channel_address']);
|
||||
$actor->setMovedTo(z_root() . '/channel/' . $channel['channel_address']);
|
||||
$actor->setAlsoKnownAs($move_id);
|
||||
}
|
||||
|
||||
$cp = Channel::get_cover_photo($c['channel_id'], 'array');
|
||||
$cp = Channel::get_cover_photo($channel['channel_id'], 'array');
|
||||
if ($cp) {
|
||||
$actor->setImage([
|
||||
'type' => 'Image',
|
||||
|
@ -1810,10 +1894,10 @@ class Activity
|
|||
]);
|
||||
}
|
||||
// only fill in profile information if the profile is publicly visible
|
||||
if (perm_is_allowed($c['channel_id'], EMPTY_STR, 'view_profile')) {
|
||||
if (perm_is_allowed($channel['channel_id'], EMPTY_STR, 'view_profile')) {
|
||||
$dp = q(
|
||||
"select * from profile where uid = %d and is_default = 1",
|
||||
intval($c['channel_id'])
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if ($dp) {
|
||||
if ($dp[0]['about']) {
|
||||
|
@ -1846,9 +1930,9 @@ class Activity
|
|||
foreach ($kw as $k) {
|
||||
$k = trim($k);
|
||||
$k = trim($k, '#,');
|
||||
$tag = $actor->getTag();
|
||||
$tag[] = ['type' => 'Hashtag', 'id' => z_root() . '/search?tag=' . urlencode($k), 'name' => '#' . urlencode($k)];
|
||||
$actor->setTag($tag);
|
||||
$tags = $actor->getTag();
|
||||
$tags[] = ['type' => 'Hashtag', 'id' => z_root() . '/search?tag=' . urlencode($k), 'name' => '#' . urlencode($k)];
|
||||
$actor->setTag($tags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1857,21 +1941,24 @@ class Activity
|
|||
} else {
|
||||
$collections = get_xconfig($p['xchan_hash'], 'activitypub', 'collections', []);
|
||||
if ($collections) {
|
||||
$actor = array_merge($actor, $collections);
|
||||
$actor = array_merge($actor->toArray(), $collections);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$actor->setPublicKey([
|
||||
'id' => $current_url,
|
||||
'owner' => $current_url,
|
||||
'id' => (($nomadic) ? Channel::getDidResolver($channel, true) : $current_url) . '#rsakey',
|
||||
'owner' => $nomadic ? Channel::getDidResolver($channel, true) : $current_url,
|
||||
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
|
||||
'publicKeyPem' => $p['xchan_pubkey']
|
||||
]);
|
||||
|
||||
$tags[] = ['type' => 'Note', 'name' => 'Protocols', 'content' => implode(',', $protocols)];
|
||||
}
|
||||
$actor->setTag($tag);
|
||||
$actor->setTag($tags);
|
||||
|
||||
$arr = ['xchan' => $p, 'encoded' => $actor->toArray(), 'activitypub' => $activitypub];
|
||||
Hook::call('encode_person', $arr);
|
||||
return $arr['encoded'];
|
||||
return $export ? self::portableActor($arr['encoded']) : $arr['encoded'];
|
||||
}
|
||||
|
||||
|
||||
|
@ -2133,7 +2220,7 @@ class Activity
|
|||
return;
|
||||
}
|
||||
|
||||
// From here on out we assume a Follow activity to somebody we have no existing relationship with
|
||||
// From here on out we assume a Follow activity from somebody we have no existing relationship with
|
||||
|
||||
set_abconfig($channel['channel_id'], $person_obj['id'], 'activitypub', 'their_follow_id', $their_follow_id);
|
||||
set_abconfig($channel['channel_id'], $person_obj['id'], 'activitypub', 'their_follow_type', $act->type);
|
||||
|
@ -2280,19 +2367,19 @@ class Activity
|
|||
}
|
||||
|
||||
|
||||
public static function actor_store($url, $person_obj, $webfinger = null, $force = false)
|
||||
public static function actor_store($url, $actorRecord, $webfinger = null, $force = false)
|
||||
{
|
||||
if (!is_array($person_obj)) {
|
||||
if (!is_array($actorRecord)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// logger('person_obj: ' . print_r($person_obj,true));
|
||||
|
||||
if (array_key_exists('movedTo', $person_obj) && $person_obj['movedTo'] && !is_array($person_obj['movedTo'])) {
|
||||
$tgt = self::fetch($person_obj['movedTo']);
|
||||
if (array_key_exists('movedTo', $actorRecord) && $actorRecord['movedTo'] && !is_array($actorRecord['movedTo'])) {
|
||||
$tgt = self::fetch($actorRecord['movedTo']);
|
||||
if (is_array($tgt)) {
|
||||
self::actor_store($person_obj['movedTo'], $tgt);
|
||||
ActivityPub::move($person_obj['id'], $tgt);
|
||||
self::actor_store($actorRecord['movedTo'], $tgt);
|
||||
ActivityPub::move($actorRecord['id'], $tgt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2315,9 +2402,9 @@ class Activity
|
|||
if ($ap_hubloc) {
|
||||
// we already have a stored record. Determine if it needs updating.
|
||||
if ($ap_hubloc['hubloc_updated'] < Time::convert('UTC', 'UTC', ' now - ' . self::ACTOR_CACHE_DAYS . ' days') || $force) {
|
||||
$person_obj = self::fetch($url);
|
||||
$actorRecord = self::fetch($url);
|
||||
// ensure we received something
|
||||
if (!is_array($person_obj)) {
|
||||
if (!is_array($actorRecord)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -2326,8 +2413,8 @@ class Activity
|
|||
}
|
||||
|
||||
|
||||
if (isset($person_obj['id'])) {
|
||||
$url = $person_obj['id'];
|
||||
if (isset($actorRecord['id'])) {
|
||||
$url = $actorRecord['id'];
|
||||
}
|
||||
|
||||
if (!$url) {
|
||||
|
@ -2336,40 +2423,41 @@ class Activity
|
|||
|
||||
$actorId = new ActorId($url);
|
||||
$url = $actorId->getId();
|
||||
$isDid = $actorId->getType() === ActorId::ACTORID_TYPE_DID;
|
||||
$isDid = in_array($actorId->getType(), [ActorId::ACTORID_TYPE_DIDKEY, ActorId::ACTORID_TYPE_DIDWEB]);
|
||||
if ($isDid) {
|
||||
$aliases = $person_obj['aliases'];
|
||||
self::updateLocations($url, $actorRecord);
|
||||
|
||||
}
|
||||
|
||||
// store the actor record in XConfig
|
||||
XConfig::Set($url, 'system', 'actor_record', $person_obj);
|
||||
XConfig::Set($url, 'system', 'actor_record', $actorRecord);
|
||||
|
||||
$name = unicode_trim(escape_tags($person_obj['name']));
|
||||
$name = unicode_trim(escape_tags($actorRecord['name']));
|
||||
if (!$name) {
|
||||
$name = escape_tags($person_obj['preferredUsername']);
|
||||
$name = escape_tags($actorRecord['preferredUsername']);
|
||||
}
|
||||
if (!$name) {
|
||||
$name = escape_tags(t('Unknown'));
|
||||
}
|
||||
|
||||
$webfingerAddress = EMPTY_STR;
|
||||
$username = escape_tags($person_obj['preferredUsername']);
|
||||
$username = escape_tags($actorRecord['preferredUsername']);
|
||||
$h = parse_url($url);
|
||||
if ($h && $h['host']) {
|
||||
$webfingerAddress = $username . '@' . $h['host'];
|
||||
}
|
||||
|
||||
$icon = self::getIcon($person_obj['icon']);
|
||||
$icon = self::getIcon($actorRecord['icon']);
|
||||
|
||||
|
||||
$cover_photo = false;
|
||||
|
||||
if (isset($person_obj['image'])) {
|
||||
if (is_string($person_obj['image'])) {
|
||||
$cover_photo = $person_obj['image'];
|
||||
if (isset($actorRecord['image'])) {
|
||||
if (is_string($actorRecord['image'])) {
|
||||
$cover_photo = $actorRecord['image'];
|
||||
}
|
||||
if (isset($person_obj['image']['url'])) {
|
||||
$ptr = $person_obj['image']['url'];
|
||||
if (isset($actorRecord['image']['url'])) {
|
||||
$ptr = $actorRecord['image']['url'];
|
||||
if (is_string($ptr)) {
|
||||
$cover_photo = $ptr;
|
||||
}
|
||||
|
@ -2389,22 +2477,22 @@ class Activity
|
|||
|
||||
$hidden = false;
|
||||
// Mastodon style hidden flag
|
||||
if (array_key_exists('discoverable', $person_obj) && (!intval($person_obj['discoverable']))) {
|
||||
if (array_key_exists('discoverable', $actorRecord) && (!intval($actorRecord['discoverable']))) {
|
||||
$hidden = true;
|
||||
}
|
||||
// Pleroma style hidden flag
|
||||
if (array_key_exists('invisible', $person_obj) && (!intval($person_obj['invisible']))) {
|
||||
if (array_key_exists('invisible', $actorRecord) && (!intval($actorRecord['invisible']))) {
|
||||
$hidden = true;
|
||||
}
|
||||
|
||||
$links = false;
|
||||
$profile = false;
|
||||
|
||||
if (is_array($person_obj['url'])) {
|
||||
if (!array_key_exists(0, $person_obj['url'])) {
|
||||
$links = [$person_obj['url']];
|
||||
if (is_array($actorRecord['url'])) {
|
||||
if (!array_key_exists(0, $actorRecord['url'])) {
|
||||
$links = [$actorRecord['url']];
|
||||
} else {
|
||||
$links = $person_obj['url'];
|
||||
$links = $actorRecord['url'];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2420,15 +2508,15 @@ class Activity
|
|||
if (!$profile) {
|
||||
$profile = $links[0]['href'];
|
||||
}
|
||||
} elseif (isset($person_obj['url']) && is_string($person_obj['url'])) {
|
||||
$profile = $person_obj['url'];
|
||||
} elseif (isset($actorRecord['url']) && is_string($actorRecord['url'])) {
|
||||
$profile = $actorRecord['url'];
|
||||
}
|
||||
|
||||
if (!$profile) {
|
||||
$profile = $url;
|
||||
}
|
||||
|
||||
$inbox = ((array_key_exists('inbox', $person_obj)) ? $person_obj['inbox'] : null);
|
||||
$inbox = ((array_key_exists('inbox', $actorRecord)) ? $actorRecord['inbox'] : null);
|
||||
|
||||
// either an invalid identity or a cached entry of some kind which didn't get caught above
|
||||
|
||||
|
@ -2439,38 +2527,38 @@ class Activity
|
|||
$collections = [];
|
||||
|
||||
$collections['inbox'] = $inbox;
|
||||
if (array_key_exists('outbox', $person_obj) && is_string($person_obj['outbox'])) {
|
||||
$collections['outbox'] = $person_obj['outbox'];
|
||||
if (array_key_exists('outbox', $actorRecord) && is_string($actorRecord['outbox'])) {
|
||||
$collections['outbox'] = $actorRecord['outbox'];
|
||||
}
|
||||
if (array_key_exists('followers', $person_obj) && is_string($person_obj['followers'])) {
|
||||
$collections['followers'] = $person_obj['followers'];
|
||||
if (array_key_exists('followers', $actorRecord) && is_string($actorRecord['followers'])) {
|
||||
$collections['followers'] = $actorRecord['followers'];
|
||||
}
|
||||
if (array_key_exists('following', $person_obj) && is_string($person_obj['following'])) {
|
||||
$collections['following'] = $person_obj['following'];
|
||||
if (array_key_exists('following', $actorRecord) && is_string($actorRecord['following'])) {
|
||||
$collections['following'] = $actorRecord['following'];
|
||||
}
|
||||
if (array_path_exists('endpoints/sharedInbox', $person_obj) && is_string($person_obj['endpoints']['sharedInbox'])) {
|
||||
$collections['sharedInbox'] = $person_obj['endpoints']['sharedInbox'];
|
||||
if (array_path_exists('endpoints/sharedInbox', $actorRecord) && is_string($actorRecord['endpoints']['sharedInbox'])) {
|
||||
$collections['sharedInbox'] = $actorRecord['endpoints']['sharedInbox'];
|
||||
}
|
||||
if (array_path_exists('endpoints/searchContent', $person_obj) && is_string($person_obj['endpoints']['searchContent'])) {
|
||||
$collections['searchContent'] = $person_obj['endpoints']['searchContent'];
|
||||
if (array_path_exists('endpoints/searchContent', $actorRecord) && is_string($actorRecord['endpoints']['searchContent'])) {
|
||||
$collections['searchContent'] = $actorRecord['endpoints']['searchContent'];
|
||||
}
|
||||
if (array_path_exists('endpoints/searchTags', $person_obj) && is_string($person_obj['endpoints']['searchTags'])) {
|
||||
$collections['searchTags'] = $person_obj['endpoints']['searchTags'];
|
||||
if (array_path_exists('endpoints/searchTags', $actorRecord) && is_string($actorRecord['endpoints']['searchTags'])) {
|
||||
$collections['searchTags'] = $actorRecord['endpoints']['searchTags'];
|
||||
}
|
||||
if (isset($person_obj['publicKey']['publicKeyPem'])) {
|
||||
if ($person_obj['id'] === $person_obj['publicKey']['owner']) {
|
||||
$pubkey = $person_obj['publicKey']['publicKeyPem'];
|
||||
if (isset($actorRecord['publicKey']['publicKeyPem'])) {
|
||||
if ($actorRecord['id'] === $actorRecord['publicKey']['owner']) {
|
||||
$pubkey = $actorRecord['publicKey']['publicKeyPem'];
|
||||
if (str_contains($pubkey, 'RSA ')) {
|
||||
$pubkey = Keyutils::rsaToPem($pubkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
$epubkey = self::getEddsaPublicKey($person_obj);
|
||||
$epubkey = self::getEddsaPublicKey($actorRecord);
|
||||
|
||||
$keywords = [];
|
||||
|
||||
if (isset($person_obj['tag']) && is_array($person_obj['tag'])) {
|
||||
foreach ($person_obj['tag'] as $t) {
|
||||
if (isset($actorRecord['tag']) && is_array($actorRecord['tag'])) {
|
||||
foreach ($actorRecord['tag'] as $t) {
|
||||
if (is_array($t) && isset($t['type']) && $t['type'] === 'Hashtag') {
|
||||
if (isset($t['name'])) {
|
||||
$tag = escape_tags((str_starts_with($t['name'], '#')) ? substr($t['name'], 1) : $t['name']);
|
||||
|
@ -2487,8 +2575,8 @@ class Activity
|
|||
}
|
||||
}
|
||||
|
||||
$xchan_type = self::get_xchan_type($person_obj['type']);
|
||||
$about = ((isset($person_obj['summary'])) ? html2bbcode(purify_html($person_obj['summary'])) : EMPTY_STR);
|
||||
$xchan_type = self::get_xchan_type($actorRecord['type']);
|
||||
$about = ((isset($actorRecord['summary'])) ? html2bbcode(purify_html($actorRecord['summary'])) : EMPTY_STR);
|
||||
|
||||
$p = q(
|
||||
"select * from xchan where xchan_url = '%s' and xchan_network in ('zot6','nomad') limit 1",
|
||||
|
@ -2731,6 +2819,51 @@ class Activity
|
|||
Run::Summon(['Xchan_photo', bin2hex($icon), bin2hex($url)]);
|
||||
}
|
||||
|
||||
public static function updateLocations($portableId, $actorRecord)
|
||||
{
|
||||
$gateways = $actorRecord['gateways'];
|
||||
if (!is_array($gateways)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($gateways as $gateway) {
|
||||
|
||||
$parsedUrl = parse_url($gateway);
|
||||
|
||||
$prefix = $gateway . '/.well-known/apgateway/' . $portableId;
|
||||
$machineName = $actorRecord['preferredUsername'] ?? 'unknown';
|
||||
|
||||
$existing = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' and hubloc_network = '%s'",
|
||||
dbesc($portableId),
|
||||
dbesc($gateway),
|
||||
dbesc('apnomadic')
|
||||
);
|
||||
|
||||
$record = [
|
||||
'hubloc_guid' => $portableId,
|
||||
'hubloc_hash' => $portableId,
|
||||
'hubloc_id_url' => $prefix . '/actor',
|
||||
'hubloc_addr' => $machineName . '@' . $parsedUrl['host'],
|
||||
'hubloc_network' => 'apnomadic',
|
||||
'hubloc_url' => $gateway,
|
||||
'hubloc_host' => $parsedUrl['host'],
|
||||
'hubloc_callback' => $prefix . '/actor/inbox',
|
||||
'hubloc_updated' => Time::convert(),
|
||||
'hubloc_primary' => ($count ? 0 : 1)
|
||||
];
|
||||
|
||||
if ($existing) {
|
||||
$record['hubloc_id'] = $existing[0]['hubloc_id'];
|
||||
}
|
||||
hubloc_store_lowlevel($record);
|
||||
|
||||
$count ++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static function update_protocols($xchan, $str)
|
||||
{
|
||||
$existing = explode(',', get_xconfig($xchan, 'system', 'protocols', EMPTY_STR));
|
||||
|
@ -5060,12 +5193,12 @@ class Activity
|
|||
->setParentMid(str_replace('/conversation/','/item/', $target))
|
||||
->setThrParent(str_replace('/conversation/','/item/', $target))
|
||||
->setApproved($object['object']['id'] ?? '')
|
||||
->setReplyto(z_root() . '/channel/' . $channel['channel_address'])
|
||||
->setReplyto(Channel::getDidResolver($channel, true))
|
||||
->setTgtType('Collection')
|
||||
->setTarget([
|
||||
'id' => str_replace('/item/','/conversation/', $target),
|
||||
'type' => 'Collection',
|
||||
'attributedTo' => z_root() . '/channel/' . $channel['channel_address']
|
||||
'attributedTo' => Channel::getDidResolver($channel, true)
|
||||
]
|
||||
)
|
||||
);
|
||||
|
@ -5097,12 +5230,12 @@ class Activity
|
|||
->setObjType($object['type'])
|
||||
->setParentMid(str_replace('/conversation/','/item/', $target))
|
||||
->setThrParent(str_replace('/conversation/','/item/', $target))
|
||||
->setReplyto(z_root() . '/channel/' . $channel['channel_address'])
|
||||
->setReplyto(Channel::getDidResolver($channel, true))
|
||||
->setTgtType('Collection')
|
||||
->setTarget([
|
||||
'id' => str_replace('/item/','/conversation/', $target),
|
||||
'type' => 'Collection',
|
||||
'attributedTo' => z_root() . '/channel/' . $channel['channel_address']
|
||||
'attributedTo' => Channel::getDidResolver($channel, true)
|
||||
]
|
||||
)
|
||||
);
|
||||
|
@ -5119,10 +5252,6 @@ class Activity
|
|||
'https://www.w3.org/ns/did/v1',
|
||||
'https://w3id.org/security/multikey/v1',
|
||||
'https://w3id.org/security/data-integrity/v1',
|
||||
[
|
||||
'fep' => 'https://w3id.org/fep/ef61#',
|
||||
'aliases' => 'fep:aliases'
|
||||
],
|
||||
self::ap_schema($contextType)
|
||||
]];
|
||||
}
|
||||
|
@ -5133,6 +5262,11 @@ class Activity
|
|||
// a limited subset of the entire schema definition for particular activities.
|
||||
|
||||
return [
|
||||
'gateways' => [
|
||||
'@id' => 'https://w3id.org/fep/ef61/gateways',
|
||||
'@type' => '@id',
|
||||
'@container' => '@list'
|
||||
],
|
||||
'wf' => 'https://purl.archive.org/socialweb/webfinger',
|
||||
'xsd' => 'http://www.w3.org/2001/XMLSchema#',
|
||||
'webfinger' => [
|
||||
|
@ -5154,8 +5288,12 @@ class Activity
|
|||
'directMessage' => 'nomad:directMessage',
|
||||
'Category' => 'nomad:Category',
|
||||
'copiedTo' => 'nomad:copiedTo',
|
||||
'permissions' => 'nomad:permissions',
|
||||
'searchContent' => 'nomad:searchContent',
|
||||
'searchTags' => 'nomad:searchTags',
|
||||
'collectionOf' => 'nomad:collectionOf',
|
||||
'openwebauth' => 'nomad:openwebauth',
|
||||
'authredirect' => 'nomad:authredirect',
|
||||
];
|
||||
|
||||
}
|
||||
|
|
|
@ -381,7 +381,7 @@ class ActivityPub
|
|||
$jmsg = json_encode($msg, JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$r = q("select * from abook left join hubloc on abook_xchan = hubloc_hash
|
||||
where abook_channel = %d and hubloc_network = 'activitypub'",
|
||||
where abook_channel = %d and hubloc_network in ('activitypub', 'apnomadic') ",
|
||||
intval($x['sender']['channel_id'])
|
||||
);
|
||||
|
||||
|
|
|
@ -11,17 +11,28 @@ class ActorId
|
|||
|
||||
public const ACTORID_TYPE_UNKNOWN = 0;
|
||||
public const ACTORID_TYPE_URL = 1;
|
||||
public const ACTORID_TYPE_DID = 2;
|
||||
public const ACTORID_TYPE_DIDKEY = 2;
|
||||
public const ACTORID_TYPE_DIDWEB = 3;
|
||||
|
||||
public function __construct($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
if (str_contains($this->id, 'did:ap:key:')) {
|
||||
$this->type = ActorId::ACTORID_TYPE_DID;
|
||||
if (str_starts_with($this->id, 'http')) {
|
||||
$this->id = substr($this->id, strpos($this->id, 'did:ap:key:'));
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '?') ? strpos($this->id, '?') : null);
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '#') ? strpos($this->id, '#') : null);
|
||||
if (str_contains($this->id, 'did:key:')) {
|
||||
$this->type = ActorId::ACTORID_TYPE_DIDKEY;
|
||||
if (str_starts_with($this->id, 'http') || str_starts_with($this->id, 'ap://')) {
|
||||
$this->id = substr($this->id, strpos($this->id, 'did:key:'));
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '/') ?: null);
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '?') ?: null);
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '#') ?: null);
|
||||
}
|
||||
}
|
||||
elseif (str_contains($this->id, 'did:web:')) {
|
||||
$this->type = ActorId::ACTORID_TYPE_DIDWEB;
|
||||
if (str_starts_with($this->id, 'http') || str_starts_with($this->id, 'ap://')) {
|
||||
$this->id = substr($this->id, strpos($this->id, 'did:web:'));
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '/') ?: null);
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '?') ?: null);
|
||||
$this->id = substr($this->id, 0, strpos($this->id, '#') ?: null);
|
||||
}
|
||||
}
|
||||
elseif (str_starts_with($this->id, 'http')) {
|
||||
|
|
|
@ -1181,10 +1181,10 @@ class Channel
|
|||
|
||||
$r = q(
|
||||
"select * from item where item_wall = 1 and item_deleted = 0 and uid = %d
|
||||
and created > %s - INTERVAL %s and resource_type = '' order by created",
|
||||
and created > %s - %s and resource_type = '' order by created",
|
||||
intval($channel_id),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 MONTH')
|
||||
db_quoteinterval('3 MONTH', true)
|
||||
);
|
||||
if ($r) {
|
||||
$ret['item'] = [];
|
||||
|
@ -2066,8 +2066,13 @@ class Channel
|
|||
|
||||
public static function getDid($channel)
|
||||
{
|
||||
if (!empty($channel['xchan_epubkey'])) {
|
||||
$ed25519publicKey = $channel['xchan_epubkey'];
|
||||
}
|
||||
else {
|
||||
$ed25519publicKey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
return 'did:ap:key:' . $ed25519publicKey;
|
||||
}
|
||||
return 'did:key:' . $ed25519publicKey;
|
||||
}
|
||||
|
||||
public static function getDidActor($channel)
|
||||
|
@ -2079,12 +2084,17 @@ class Channel
|
|||
{
|
||||
$pubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
|
||||
$nomadic = PConfig::Get($channel['channel_id'], 'system', 'nomadicAP');
|
||||
return (($nomadic) ? Channel::getDidResolver($channel) : Channel::url($channel) . '#' . $pubkey);
|
||||
return (($nomadic) ? Channel::getDidResolver($channel, true) : Channel::url($channel) . '#' . $pubkey);
|
||||
}
|
||||
|
||||
public static function getDidResolver($channel)
|
||||
public static function getDidResolver($channel, $isActor = false)
|
||||
{
|
||||
return z_root() . '/.well-known/apresolver/' . self::getDid($channel);
|
||||
return z_root() . '/.well-known/apgateway/' . self::getDid($channel) . (($isActor) ? '/actor' : '');
|
||||
}
|
||||
|
||||
public static function getNomadResolver($channel, $isActor = false)
|
||||
{
|
||||
return z_root() . '/.well-known/nomad-gateway/' . $channel['channel_hash']. (($isActor) ? '/actor' : '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2610,10 +2620,12 @@ class Channel
|
|||
}
|
||||
|
||||
if ($channel['channel_address'] === App::get_hostname() || intval($channel['channel_system'])) {
|
||||
return z_root() . '?operation=rsakey';
|
||||
return z_root() . '#rsakey';
|
||||
}
|
||||
$nomadic = PConfig::Get($channel['channel_id'], 'system', 'nomaadicAP');
|
||||
$url = $nomadic ? self::getDidResolver($channel, true) : z_root() . '/channel/' . $channel['channel_address'];
|
||||
|
||||
return (($channel) ? z_root() . '/channel/' . $channel['channel_address'] : z_root()) . '?operation=rsakey';
|
||||
return $url . '#rsakey';
|
||||
}
|
||||
|
||||
public static function is_group($uid)
|
||||
|
|
|
@ -168,9 +168,9 @@ class Chatroom
|
|||
|
||||
if (intval($x[0]['cr_expire'])) {
|
||||
$r = q(
|
||||
"delete from chat where created < %s - INTERVAL %s and chat_room = %d",
|
||||
"delete from chat where created < %s - %s and chat_room = %d",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(intval($x[0]['cr_expire']) . ' MINUTE'),
|
||||
db_quoteinterval(intval($x[0]['cr_expire']) . ' MINUTE', true),
|
||||
intval($x[0]['cr_id'])
|
||||
);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ class Connect
|
|||
|
||||
// ensure there's a valid hubloc for this xchan before proceeding - you cannot connect without it
|
||||
|
||||
if (in_array($r['xchan_network'], ['nomad', 'zot6', 'activitypub'])) {
|
||||
if (in_array($r['xchan_network'], ['nomad', 'zot6', 'activitypub', 'apnomadic'])) {
|
||||
$h = q(
|
||||
"select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
|
||||
dbesc($r['xchan_hash'])
|
||||
|
@ -111,7 +111,7 @@ class Connect
|
|||
// Check the site table to see if we should have a zot6 hubloc,
|
||||
// If so, clear the xchan and start fresh
|
||||
|
||||
if ($r['xchan_network'] === 'activitypub') {
|
||||
if (in_array($r['xchan_network'], [ 'activitypub', 'apnomadic'])) {
|
||||
$m = parse_url($r['xchan_hash']);
|
||||
unset($m['path']);
|
||||
$h = unparse_url($m);
|
||||
|
@ -177,7 +177,7 @@ class Connect
|
|||
return $result;
|
||||
}
|
||||
|
||||
if ($r['xchan_network'] === 'activitypub') {
|
||||
if (in_array($r['xchan_network'], [ 'activitypub', 'apnomadic'])) {
|
||||
if (!$ap_allowed) {
|
||||
$result['message'] = t('Protocol not supported');
|
||||
return $result;
|
||||
|
|
|
@ -22,7 +22,7 @@ class JcsEddsa2022
|
|||
'type' => 'DataIntegrityProof',
|
||||
'cryptosuite' => 'eddsa-jcs-2022',
|
||||
'created' => Time::convert(format: ISO8601),
|
||||
'verificationMethod' => Channel::getVerifier($channel),
|
||||
'verificationMethod' => Channel::getDid($channel),
|
||||
'proofPurpose' => 'assertionMethod',
|
||||
];
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ class Libsync
|
|||
}
|
||||
}
|
||||
|
||||
if ((!$found) && (!in_array($abook['xchan_network'], ['nomad', 'zot6', 'activitypub']))) {
|
||||
if ((!$found) && (!in_array($abook['xchan_network'], ['nomad', 'zot6', 'activitypub', 'apnomadic']))) {
|
||||
// just import the record.
|
||||
$xc = [];
|
||||
foreach ($abook as $k => $v) {
|
||||
|
@ -979,6 +979,8 @@ class Libsync
|
|||
if (isset($sender['site']) && isset($sender['site']['url']) && $sender['site']['url'] === $location['url']) {
|
||||
if (isset($sender['site']['protocol_version']) && intval($sender['site']['protocol_version']) > 10) {
|
||||
$network = 'nomad';
|
||||
$owa = $sender['site']['openWebAuth'] ?? '';
|
||||
$redirect = $sender['site']['authRedirect'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ class Libzot
|
|||
$h = HTTPSig::create_sig(
|
||||
$headers,
|
||||
$channel['channel_prvkey'],
|
||||
Channel::url($channel),
|
||||
Channel::keyId($channel),
|
||||
false,
|
||||
'sha512',
|
||||
(($crypto) ? ['key' => $crypto['hubloc_sitekey'], 'algorithm' => self::best_algorithm($crypto['site_crypto'])] : false)
|
||||
|
@ -257,7 +257,7 @@ class Libzot
|
|||
'(request-target)' => 'post ' . get_request_string($url)
|
||||
];
|
||||
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],Channel::url($channel),false,'sha512',
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],Channel::keyId($channel),false,'sha512',
|
||||
(($crypto) ? [ 'key' => $crypto['hubloc_sitekey'], 'algorithm' => self::best_algorithm($crypto['site_crypto']) ] : false));
|
||||
}
|
||||
else {
|
||||
|
@ -3037,7 +3037,7 @@ class Libzot
|
|||
|
||||
$ret['id'] = $e['xchan_guid'];
|
||||
$ret['id_sig'] = self::sign($e['xchan_guid'], $e['channel_prvkey']);
|
||||
$ret['did'] = Channel::getDidResolver($e);
|
||||
$ret['did'] = Channel::getDid($e);
|
||||
|
||||
$primary = new Primary([
|
||||
'address' => $e['xchan_addr'],
|
||||
|
@ -3047,6 +3047,7 @@ class Libzot
|
|||
'outbox' => z_root() . '/outbox/' . $e['channel_address'],
|
||||
'followers' => z_root() . '/followers/' . $e['channel_address'],
|
||||
'following' => z_root() . '/following/' . $e['channel_address'],
|
||||
'permissions' => z_root() . '/permissions/' . $e['channel_address'],
|
||||
'searchContent' => z_root() . '/search/' . $e['channel_address'] . '?search={}',
|
||||
'searchTags' => z_root() . '/search/' . $e['channel_address'] . '?tags={}',
|
||||
]);
|
||||
|
@ -3354,6 +3355,11 @@ class Libzot
|
|||
return $v;
|
||||
}
|
||||
}
|
||||
foreach ($arr as $v) {
|
||||
if ($v[$check] === 'apnomadic') {
|
||||
return $v;
|
||||
}
|
||||
}
|
||||
return $arr[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ class MessageFilter
|
|||
return false;
|
||||
}
|
||||
|
||||
// Ordering of this check (for falsiness) with relation to the following one (check for truthiness) is important.
|
||||
// Ordering of this check (for falseness) with relation to the following one (check for truthiness) is important.
|
||||
if (preg_match('/!(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (!$x) {
|
||||
|
|
|
@ -107,7 +107,7 @@ class Share
|
|||
'term' => substr($this->item['author']['xchan_addr'],0,strpos($this->item['author']['xchan_addr'],'@'))
|
||||
];
|
||||
|
||||
if ($this->item['author']['network'] === 'activitypub') {
|
||||
if (in_array($this->item['author']['network'], ['activitypub', 'apnomadic'])) {
|
||||
// for Mastodon compatibility, send back an ActivityPub Announce activity.
|
||||
// We don't need or want these on our own network as there is no mechanism for providing
|
||||
// a fair-use defense to copyright claims and frivolous lawsuits.
|
||||
|
|
|
@ -118,9 +118,9 @@ class Socgraph {
|
|||
}
|
||||
}
|
||||
q(
|
||||
"delete from xchat where xchat_edited < %s - INTERVAL %s and xchat_xchan = '%s' ",
|
||||
"delete from xchat where xchat_edited < %s - %s and xchat_xchan = '%s' ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY'),
|
||||
db_quoteinterval('7 DAY', true),
|
||||
dbesc($xchan)
|
||||
);
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class Socgraph {
|
|||
$profile_url = $url['value'];
|
||||
continue;
|
||||
}
|
||||
if (in_array($url['type'], ['nomad', 'zot6', 'activitypub'])) {
|
||||
if (in_array($url['type'], ['nomad', 'zot6', 'activitypub', 'apnomadic'])) {
|
||||
$network = $url['type'];
|
||||
$address = str_replace('acct:', '', $url['value']);
|
||||
continue;
|
||||
|
@ -166,7 +166,7 @@ class Socgraph {
|
|||
}
|
||||
}
|
||||
|
||||
if (! in_array($network, ['nomad', 'zot6', 'activitypub'])) {
|
||||
if (! in_array($network, ['nomad', 'zot6', 'activitypub', 'apnomadic'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ class Socgraph {
|
|||
|
||||
if (($x !== false) && (! count($x))) {
|
||||
if ($address) {
|
||||
if (in_array($network, ['nomad', 'zot6', 'activitypub'])) {
|
||||
if (in_array($network, ['nomad', 'zot6', 'activitypub', 'apnomadic'])) {
|
||||
$wf = discover_resource($profile_url, verify: false);
|
||||
if ($wf) {
|
||||
$x = q(
|
||||
|
@ -241,10 +241,10 @@ class Socgraph {
|
|||
logger("poco_load: loaded $total entries", LOGGER_DEBUG);
|
||||
|
||||
q(
|
||||
"delete from xlink where xlink_xchan = '%s' and xlink_updated < %s - INTERVAL %s and xlink_static = 0",
|
||||
"delete from xlink where xlink_xchan = '%s' and xlink_updated < %s - %s and xlink_static = 0",
|
||||
dbesc($xchan),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
db_quoteinterval('7 DAY', true)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -344,10 +344,10 @@ class Socgraph {
|
|||
logger("ap_poco_load: loaded $total entries", LOGGER_DEBUG);
|
||||
|
||||
q(
|
||||
"delete from xlink where xlink_xchan = '%s' and xlink_updated < %s - INTERVAL %s and xlink_static = 0",
|
||||
"delete from xlink where xlink_xchan = '%s' and xlink_updated < %s - %s and xlink_static = 0",
|
||||
dbesc($xchan),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
db_quoteinterval('7 DAY', true)
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -70,10 +70,10 @@ class Verify
|
|||
public static function purge(string $type, string $interval): void
|
||||
{
|
||||
q(
|
||||
"delete from verify where vtype = '%s' and created < ( %s - INTERVAL %s )",
|
||||
"delete from verify where vtype = '%s' and created < ( %s - %s )",
|
||||
dbesc($type),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($interval)
|
||||
db_quoteinterval($interval, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class Zotfinger
|
|||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($resource)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::url($channel), false);
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::keyId($channel), false);
|
||||
}
|
||||
else {
|
||||
$h = ['Accept: ' . $accepts];
|
||||
|
@ -125,7 +125,7 @@ class Zotfinger
|
|||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get ' . get_request_string($resource)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::url($channel), false);
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Channel::keyId($channel), false);
|
||||
}
|
||||
else {
|
||||
$h = ['Accept: ' . $accepts];
|
||||
|
|
|
@ -240,7 +240,7 @@ class Activity extends Controller
|
|||
|
||||
$observer = App::get_observer();
|
||||
$parent = $items[0];
|
||||
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
|
||||
$recips = (in_array($parent['owner']['xchan_network'], ['activitypub', 'apnomadic']) ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
|
||||
$to = (($recips && array_key_exists('to', $recips) && is_array($recips['to'])) ? $recips['to'] : null);
|
||||
$nitems = [];
|
||||
foreach ($items as $i) {
|
||||
|
@ -300,7 +300,7 @@ class Activity extends Controller
|
|||
$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));
|
||||
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], Channel::keyId($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
|
|
@ -21,8 +21,6 @@ class Album extends Controller
|
|||
|
||||
public function init()
|
||||
{
|
||||
|
||||
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
|
@ -104,8 +102,9 @@ class Album extends Controller
|
|||
$collection = fetch_post_tags($collection);
|
||||
}
|
||||
|
||||
$obj = Activity::encode_photo_collection($collection, App::$query_string, 'Collection', true, z_root() . '/channel/' . $channel['channel_address'], count($collection));
|
||||
$obj = Activity::encode_photo_collection($collection, App::$query_string, 'Collection', true, Channel::getDidResolver($channel, true), count($collection));
|
||||
$obj['content'] = bbcode($obj['content'], ['export' => true]);
|
||||
|
||||
as_return_and_die($obj, $channel);
|
||||
}
|
||||
goaway(z_root() . '/photos/' . argv(1) . '/album/' . argv(2));
|
||||
|
|
113
src/Module/Apgateway.php
Normal file
113
src/Module/Apgateway.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Code\Module;
|
||||
|
||||
use App;
|
||||
|
||||
use Code\Lib\ActivityStreams;
|
||||
use Code\Web\Controller;
|
||||
use Code\Web\Router;
|
||||
|
||||
class Apgateway extends Controller
|
||||
{
|
||||
|
||||
protected $module;
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
||||
// Concatenate path components starting with argv(1)
|
||||
// to isolate the DID URL.
|
||||
$url = null;
|
||||
for ($index = 1; $index < argc(); $index ++) {
|
||||
if ($index != 1) {
|
||||
$url .= '/';
|
||||
}
|
||||
$url .= argv($index);
|
||||
}
|
||||
// Extract the ed25519 key from the DID URL.
|
||||
$key = str_replace('did:key:', '', $url);
|
||||
$key = rtrim($key, '/');
|
||||
$index = strpos($key, '/');
|
||||
$key = substr($key, 0, $index ?: null);
|
||||
|
||||
// Find a channel on this site which has that ed25519 key.
|
||||
$query = q("select * from xchan left join channel
|
||||
on xchan_hash = channel_hash where xchan_epubkey = '%s'",
|
||||
dbesc($key)
|
||||
);
|
||||
if (!($query && isset($query[0]['channel_id']))) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
$mappedPath = $this->mapObject(str_replace('did:key:' . $key, '', rtrim($url, '/')), $query[0]);
|
||||
$localPath = ltrim($mappedPath, '/');
|
||||
App::$cmd = $localPath;
|
||||
App::$argv = explode('/', App::$cmd);
|
||||
|
||||
App::$argc = count(App::$argv);
|
||||
if ((array_key_exists('0', App::$argv)) && strlen(App::$argv[0])) {
|
||||
if (strpos(App::$argv[0],'.')) {
|
||||
$_REQUEST['module_format'] = substr(App::$argv[0],strpos(App::$argv[0], '.') + 1);
|
||||
App::$argv[0] = substr(App::$argv[0], 0, strpos(App::$argv[0], '.'));
|
||||
}
|
||||
|
||||
App::$module = str_replace(".", "_", App::$argv[0]);
|
||||
App::$module = str_replace("-", "_", App::$module);
|
||||
if (str_starts_with(App::$module, '_')) {
|
||||
App::$module = substr(App::$module, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
App::$argc = 1;
|
||||
App::$argv = ['home'];
|
||||
App::$module = 'home';
|
||||
}
|
||||
header('Link: ' . '<' . $url . '>; rel="alternate"', false);
|
||||
// recursively call the router.
|
||||
App::$module_loaded = false;
|
||||
$router = new Router();
|
||||
$router->Dispatch(true);
|
||||
|
||||
}
|
||||
|
||||
protected function mapObject($path, $channel)
|
||||
{
|
||||
// lookup abstract paths
|
||||
$systemPaths = [
|
||||
'' => '/channel/' . $channel['channel_address'],
|
||||
'/inbox' => '/inbox/' . $channel['channel_address'],
|
||||
'/outbox' => '/outbox/' . $channel['channel_address'],
|
||||
'/followers' => '/followers/' . $channel['channel_address'],
|
||||
'/following' => '/following/' . $channel['channel_address'],
|
||||
'/permissions' => '/permissions/' . $channel['channel_address'],
|
||||
'/actor' => '/channel/' . $channel['channel_address'],
|
||||
'/actor/inbox' => '/inbox/' . $channel['channel_address'],
|
||||
'/actor/outbox' => '/outbox/' . $channel['channel_address'],
|
||||
'/actor/followers' => '/followers/' . $channel['channel_address'],
|
||||
'/actor/following' => '/following/' . $channel['channel_address'],
|
||||
'/actor/permissions' => '/permissions/' . $channel['channel_address'],
|
||||
];
|
||||
|
||||
$partialPaths = [
|
||||
'/files/' => '/cloud/' . $channel['channel_address'],
|
||||
'/photos/' => '/photos/' . $channel['channel_address'],
|
||||
'/album/' => '/album/' . $channel['channel_address'],
|
||||
'/object/' => '/item',
|
||||
];
|
||||
|
||||
foreach ($systemPaths as $index => $localPath) {
|
||||
if ($path === $index) {
|
||||
return $localPath;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($partialPaths as $index => $localPath) {
|
||||
if (str_starts_with($path, $index)) {
|
||||
$suffix = substr($path, strlen($index));
|
||||
return $localPath . '/' . ltrim($suffix, '/');
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Code\Module;
|
||||
|
||||
use App;
|
||||
|
||||
use Code\Lib\ActivityStreams;
|
||||
use Code\Web\Controller;
|
||||
|
||||
class Apresolver extends Controller
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
// Concatenate path components starting with argv(1)
|
||||
// to isolate the DID URL.
|
||||
$url = null;
|
||||
for ($index = 1; $index < argc(); $index ++) {
|
||||
if ($index != 1) {
|
||||
$url .= '/';
|
||||
}
|
||||
$url .= argv($index);
|
||||
}
|
||||
// Extract the ed25519 key from the DID URL.
|
||||
$key = str_replace('did:ap:key:', '', $url);
|
||||
$key = rtrim($key, '/');
|
||||
$index = strpos($key, '/');
|
||||
$key = substr($key, 0, $index ?: null);
|
||||
|
||||
// Find a channel on this site which has that ed25519 key.
|
||||
$query = q("select * from xchan left join channel
|
||||
on xchan_hash = channel_hash where xchan_epubkey = '%s'",
|
||||
dbesc($key)
|
||||
);
|
||||
if (!($query && isset($query[0]['channel_id']))) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
$mappedPath = $this->mapObject(str_replace('did:ap:key:' . $key, '', rtrim($url, '/')), $query[0]);
|
||||
$localPath = ltrim($mappedPath, '/');
|
||||
App::$cmd = $localPath;
|
||||
$controller = "\\Code\Module\\" . ucfirst(substr($localPath, 0, strpos($localPath, '/')));
|
||||
$module = new $controller;
|
||||
App::$argv = explode('/', App::$cmd);
|
||||
|
||||
App::$argc = count(App::$argv);
|
||||
if ((array_key_exists('0', App::$argv)) && strlen(App::$argv[0])) {
|
||||
if (strpos(App::$argv[0],'.')) {
|
||||
$_REQUEST['module_format'] = substr(App::$argv[0],strpos(App::$argv[0], '.') + 1);
|
||||
App::$argv[0] = substr(App::$argv[0], 0, strpos(App::$argv[0], '.'));
|
||||
}
|
||||
|
||||
App::$module = str_replace(".", "_", App::$argv[0]);
|
||||
App::$module = str_replace("-", "_", App::$module);
|
||||
if (str_starts_with(App::$module, '_')) {
|
||||
App::$module = substr(App::$module, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
App::$argc = 1;
|
||||
App::$argv = ['home'];
|
||||
App::$module = 'home';
|
||||
}
|
||||
header('Link: ' . '<' . $url . '>; rel="alternate"', false);
|
||||
$module->init();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected function mapObject($path, $channel)
|
||||
{
|
||||
// lookup abstract paths
|
||||
$systemPaths = [
|
||||
'' => '/channel/' . $channel['channel_address'],
|
||||
'/inbox' => '/inbox/' . $channel['channel_address'],
|
||||
'/outbox' => '/outbox/' . $channel['channel_address'],
|
||||
'/followers' => '/followers/' . $channel['channel_address'],
|
||||
'/following' => '/following/' . $channel['channel_address'],
|
||||
];
|
||||
|
||||
foreach ($systemPaths as $index => $localPath) {
|
||||
if ($path === $index) {
|
||||
return $localPath;
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
}
|
|
@ -42,6 +42,7 @@ class Channel extends Controller
|
|||
public $profile_uid = 0;
|
||||
public $loading = 0;
|
||||
public $updating = 0;
|
||||
public $legacy = true;
|
||||
|
||||
|
||||
public function init()
|
||||
|
@ -153,8 +154,8 @@ class Channel extends Controller
|
|||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
}
|
||||
|
||||
as_return_and_die(Activity::actorEncode($channel, true, true), $channel);
|
||||
$export = !empty($_REQUEST['export']);
|
||||
as_return_and_die(Activity::actorEncode($channel, extended: true, activitypub: true, export: $export, legacy: $this->legacy), $channel);
|
||||
}
|
||||
|
||||
// handle zot6 channel discovery
|
||||
|
@ -199,7 +200,7 @@ class Channel extends Controller
|
|||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Zlib\Channel::url($channel));
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], Zlib\Channel::keyId($channel));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $data;
|
||||
killme();
|
||||
|
|
|
@ -434,7 +434,7 @@ class Connedit extends Controller
|
|||
notice(t('Refresh failed - channel is currently unavailable.'));
|
||||
}
|
||||
} else {
|
||||
if ($orig_record['xchan_network'] === 'activitypub') {
|
||||
if (in_array($orig_record['xchan_network'], ['activitypub', 'apnomadic'])) {
|
||||
ActivityPub::discover($orig_record['xchan_hash'], true);
|
||||
}
|
||||
// if they are on a different network we'll force a refresh of the connection basic info
|
||||
|
@ -508,7 +508,7 @@ class Connedit extends Controller
|
|||
}
|
||||
|
||||
if ($cmd === 'drop') {
|
||||
if ($orig_record['xchan_network'] === 'activitypub') {
|
||||
if (in_array($orig_record['xchan_network'], ['activitypub', 'apnomadic'])) {
|
||||
ActivityPub::contact_remove(local_channel(), $orig_record);
|
||||
}
|
||||
contact_remove(local_channel(), $orig_record['abook_id'], true);
|
||||
|
@ -531,11 +531,31 @@ class Connedit extends Controller
|
|||
$abook_prev = 0;
|
||||
$abook_next = 0;
|
||||
|
||||
|
||||
$order_q = 'xchan_name';
|
||||
if (isset($_REQUEST['order'])) {
|
||||
switch ($_REQUEST['order']) {
|
||||
case 'date':
|
||||
$order_q = 'abook_created desc';
|
||||
break;
|
||||
case 'created':
|
||||
$order_q = 'abook_created';
|
||||
break;
|
||||
case 'cmax':
|
||||
$order_q = 'abook_closeness';
|
||||
break;
|
||||
case 'name':
|
||||
default:
|
||||
$order_q = 'xchan_name';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$contact_id = App::$poi['abook_id'];
|
||||
$contact = App::$poi;
|
||||
|
||||
$cn = q(
|
||||
"SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name",
|
||||
"SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by $order_q",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
|
@ -819,6 +839,7 @@ class Connedit extends Controller
|
|||
'$section' => $section,
|
||||
'$sections' => $sections,
|
||||
'$vcard' => $vcard,
|
||||
'$order' => $_REQUEST['order'] ?? '',
|
||||
'$addr_text' => t('This connection\'s primary address is'),
|
||||
'$loc_text' => t('Available locations:'),
|
||||
'$locstr' => $locstr,
|
||||
|
|
|
@ -32,14 +32,16 @@ class Conversation extends Controller
|
|||
// do we have the item (at all)?
|
||||
|
||||
$test = q(
|
||||
"select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id)
|
||||
"select * from item where mid like '%s' and mid like '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '%'),
|
||||
dbesc('%/activity/' . $item_id)
|
||||
);
|
||||
|
||||
if (!$test) {
|
||||
$test = q(
|
||||
"select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
"select * from item where mid like '%s' and mid like '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '%'),
|
||||
dbesc('%/item/' . $item_id)
|
||||
);
|
||||
if (!$test) {
|
||||
http_status_exit(404, 'Not found');
|
||||
|
@ -123,7 +125,7 @@ class Conversation extends Controller
|
|||
|
||||
$observer = App::get_observer();
|
||||
$parent = $items[0];
|
||||
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
|
||||
$recips = (in_array($parent['owner']['xchan_network'], ['activitypub', 'apnomadic']) ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
|
||||
$to = (($recips && array_key_exists('to', $recips) && is_array($recips['to'])) ? $recips['to'] : null);
|
||||
$nitems = [];
|
||||
foreach ($items as $i) {
|
||||
|
|
|
@ -35,6 +35,7 @@ require_once('include/photos.php');
|
|||
*/
|
||||
class Cover_photo extends Controller
|
||||
{
|
||||
public $channel;
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
@ -42,8 +43,8 @@ class Cover_photo extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
Libprofile::load($channel['channel_address']);
|
||||
$this->$channel = App::get_channel();
|
||||
Libprofile::load($this->channel['channel_address']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,8 +61,6 @@ class Cover_photo extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
||||
|
||||
if ((array_key_exists('cropfinal', $_POST)) && ($_POST['cropfinal'] == 1)) {
|
||||
|
@ -203,17 +202,16 @@ class Cover_photo extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
$this->send_cover_photo_activity($channel, $base_image, $profile);
|
||||
$this->send_cover_photo_activity($this->channel, $base_image, $profile);
|
||||
// put the url and a copy in the places we look for remote cover photos.
|
||||
XConfig::Set($channel['channel_hash'], 'system', 'cover_photo', z_root() . '/photo/' . $base_image['resource_id'] . '-7');
|
||||
Stdio::fcopy('store/' . $channel['channel_address'] . '/' . $p['os_path'] . '-9', Hashpath::path($channel['channel_hash'], 'cache/xp' , 2) . '-9');
|
||||
XConfig::Set($this->channel['channel_hash'], 'system', 'cover_photo', Channel::getDidResolver($this->channel) . '/photo/' . $base_image['resource_id'] . '-7');
|
||||
Stdio::fcopy('store/' . $this->channel['channel_address'] . '/' . $p['os_path'] . '-9', Hashpath::path($this->channel['channel_hash'], 'cache/xp' , 2) . '-9');
|
||||
} else {
|
||||
notice(t('Unable to process image') . EOL);
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/channel/' . $channel['channel_address']);
|
||||
goaway(z_root() . '/channel/' . $this->channel['channel_address']);
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,7 +230,7 @@ class Cover_photo extends Controller
|
|||
}
|
||||
|
||||
if ($partial) {
|
||||
$x = save_chunk($channel, $matches[1], $matches[2], $matches[3]);
|
||||
$x = save_chunk($this->channel, $matches[1], $matches[2], $matches[3]);
|
||||
|
||||
if ($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
|
@ -267,7 +265,7 @@ class Cover_photo extends Controller
|
|||
json_return_and_die(['message' => $hash]);
|
||||
}
|
||||
|
||||
public function send_cover_photo_activity($channel, $photo, $profile)
|
||||
public function send_cover_photo_activity($photo, $profile)
|
||||
{
|
||||
|
||||
$arr = [];
|
||||
|
@ -287,11 +285,11 @@ class Cover_photo extends Controller
|
|||
$t = t('%1$s updated their %2$s');
|
||||
}
|
||||
|
||||
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
|
||||
$ptext = '[zrl=' . z_root() . '/photos/' . $this->channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
|
||||
|
||||
$ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg alt="' . t('cover photo') . '"]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
|
||||
$ltext = '[zrl=' . z_root() . '/profile/' . $this->channel['channel_address'] . ']' . '[zmg alt="' . t('cover photo') . '"]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
|
||||
|
||||
$arr['body'] = sprintf($t, $channel['channel_name'], $ptext) . "\n\n" . $ltext;
|
||||
$arr['body'] = sprintf($t, $this->channel['channel_name'], $ptext) . "\n\n" . $ltext;
|
||||
|
||||
$arr['obj'] = [
|
||||
'type' => ACTIVITY_OBJ_NOTE,
|
||||
|
@ -301,10 +299,10 @@ class Cover_photo extends Controller
|
|||
'url' => ['type' => 'Link', 'mediaType' => $photo['mimetype'], 'href' => z_root() . '/photo/' . $photo['resource_id'] . '-7'],
|
||||
'source' => ['content' => $arr['body'], 'mediaType' => 'text/x-multicode'],
|
||||
'content' => bbcode($arr['body']),
|
||||
'actor' => Activity::actorEncode($channel, false),
|
||||
'actor' => Activity::actorEncode($this->channel, false),
|
||||
];
|
||||
|
||||
$acl = new AccessControl($channel);
|
||||
$acl = new AccessControl($this->channel);
|
||||
$x = $acl->get();
|
||||
$arr['allow_cid'] = $x['allow_cid'];
|
||||
|
||||
|
@ -312,11 +310,11 @@ class Cover_photo extends Controller
|
|||
$arr['deny_cid'] = $x['deny_cid'];
|
||||
$arr['deny_gid'] = $x['deny_gid'];
|
||||
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $this->channel['channel_id'];
|
||||
$arr['aid'] = $this->channel['channel_account_id'];
|
||||
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
$arr['owner_xchan'] = $this->channel['channel_hash'];
|
||||
$arr['author_xchan'] = $this->channel['channel_hash'];
|
||||
|
||||
post_activity_item($arr);
|
||||
}
|
||||
|
@ -335,11 +333,9 @@ class Cover_photo extends Controller
|
|||
|
||||
if (!local_channel()) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
$newuser = false;
|
||||
|
||||
if (argc() == 2 && argv(1) === 'new') {
|
||||
|
@ -349,7 +345,7 @@ class Cover_photo extends Controller
|
|||
if (argv(1) === 'use') {
|
||||
if (argc() < 3) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
||||
|
@ -363,7 +359,7 @@ class Cover_photo extends Controller
|
|||
);
|
||||
if (!$r) {
|
||||
notice(t('Photo not available.') . EOL);
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
$havescale = false;
|
||||
foreach ($r as $rr) {
|
||||
|
@ -379,7 +375,7 @@ class Cover_photo extends Controller
|
|||
);
|
||||
if (!$r) {
|
||||
notice(t('Photo not available.') . EOL);
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
if (intval($r[0]['os_storage'])) {
|
||||
|
@ -412,7 +408,7 @@ class Cover_photo extends Controller
|
|||
|
||||
if (!array_key_exists('imagecrop', App::$data)) {
|
||||
$o = replace_macros(Theme::get_template('cover_photo.tpl'), [
|
||||
'$user' => App::$channel['channel_address'],
|
||||
'$user' => $this->channel['channel_address'],
|
||||
'$info' => t('Your cover photo may be visible to anybody on the internet'),
|
||||
'$existing' => Channel::get_cover_photo(local_channel(), 'array', PHOTO_RES_COVER_850),
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
|
@ -458,7 +454,6 @@ class Cover_photo extends Controller
|
|||
|
||||
/* @brief Generate the UI for photo-cropping
|
||||
*
|
||||
* @param $a Current application
|
||||
* @param $ph
|
||||
* @return void
|
||||
*
|
||||
|
|
|
@ -309,7 +309,7 @@ class Directory extends Controller
|
|||
$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));
|
||||
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], Channel::keyId($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue