Merge branch 'dev' into 11.2RC

This commit is contained in:
Mario
2026-03-26 07:50:56 +00:00
7 changed files with 151 additions and 3327 deletions

View File

@@ -6,6 +6,11 @@ Hubzilla 11.2 (2026-??-??)
- Refactor drop_query_params() to deal with array params and add test
Maintenance
- Remove private members from API docs
- Remove custom CA certs
- Add type annotations in Extend\Route
- Set method visibility in Extend\Route
- Add API docs and licence info to Extend\Route
- Add a short sleep interval to Activity::init_background_fetch() when adding new work items in a loop
- Add a short sleep interval to the convo daemon loop to spread the load for large collections
- Use PHP matching rules in util/run_xgettext
@@ -18,6 +23,9 @@ Hubzilla 11.2 (2026-??-??)
- Update the nginx config example to meet the more modern approach
Bugfixes
- Fix route and widget register() not deduplicating entries
- Fix issue in route and widget unregister() where we unregistered even if only one of the two arguments did not match
- Fix issue in Storage/Directory where we returned a partial path instead of throwing exception if a directory of a path could not be found
- Fix possible endless loop in externals daemon
- Fix fatal error in italian translation file
- Fix mod network not displaying direct messages when filters active - issue #1973

View File

@@ -1,23 +1,106 @@
<?php
/*
* SPDX-FileCopyrightText: 2018 The Hubzilla Community
* SPDX-FileContributor: Zotlabs
* SPDX-FileContributor: Mario <mario@mariovavti.com>
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
*
* SPDX-License-Identifier: MIT
*/
namespace Zotlabs\Extend;
use Zotlabs\Lib\Config;
/**
* Class for managing routes.
*
* Routes connect a URL path to a module that will handle requests to that
* path.
*
* For example by registering a route like this:
*
* ```php
* Route::register(
* __DIR__ . '/Mod_Myroute.php',
* 'myroute'
* );
* ```
*
* Hubzilla will direct requests to the '/myroute' URL path to the 'Myroute'
* controller located in the '/Mod_Myroute.php' file in the same directory as
* the file this code was called from.
*
* Routes are stored persistently, so this function will typically be called from
* the `<addon>_load()` function if called from an addon. Accordingly, the route must
* be unregistered when no longer needed, like this:
*
* ```php
* Route::unregister(
* __DIR__ . '/Mod_Myroute.php',
* 'myroute'
* );
* ```
*
* This will typically be called from the `<addon>_unload()` function in an addon.
*/
class Route {
static function register($file,$modname) {
/**
* Register a new route.
*
* Example:
* ```php
* Route::register(
* __DIR__ . '/Mod_Myroute.php',
* 'myroute'
* );
* ```
*
* The route is stored persistently, and must be unregistered when no longer needed.
*
* @param string $file The file containing the controller for handling requests to this route.
* @param string $modname The name of the module (URL path).
*
* @see {@link Zotlabs::Extend::Route.unregister() unregister()}
* @see {@link Zotlabs::Extend::Route.unregister_by_file() unregister_by_file()}
*/
public static function register(string $file, string $modname): void {
$rt = self::get();
foreach ($rt as $r) {
if ($r[0] === $file && $r[1] === $modname) {
return;
}
}
$rt[] = [ $file, $modname ];
self::set($rt);
}
static function unregister($file,$modname) {
/**
* Unregister a route.
*
* Example:
* ```php
* Route::unregister(
* __DIR__ . '/Mod_Myroute.php',
* 'myroute'
* );
* ```
*
* @param string $file The file containing the controller for handling requests to this route.
* @param string $modname The name of the module (URL path).
*
* @see {@link Zotlabs::Extend::Route.register() register()}
* @see {@link Zotlabs::Extend::Route.unregister_by_file() unregister_by_file()}
*/
public static function unregister(string $file, string $modname): void {
$rt = self::get();
if($rt) {
$n = [];
foreach($rt as $r) {
if($r[0] !== $file && $r[1] !== $modname) {
if(!($r[0] === $file && $r[1] === $modname)) {
$n[] = $r;
}
}
@@ -25,7 +108,23 @@ class Route {
}
}
static function unregister_by_file($file) {
/**
* Unregister all routes by source file.
*
* Removes all persistently stored routes with hanclers in the
* given source file.
*
* Example:
* ```php
* Route::unregister_by_file(__DIR__ . '/Mod_Myroute.php');
* ```
*
* @param string $file The file containing the controllers to remove.
*
* @see {@link Zotlabs::Extend::Route.register() register()}
* @see {@link Zotlabs::Extend::Route.unregister() unregister()}
*/
public static function unregister_by_file(string $file): void {
$rt = self::get();
if($rt) {
$n = [];
@@ -38,11 +137,18 @@ class Route {
}
}
static function get() {
/**
* Get an array of all defined routes.
*
* @return An array of routes, where each entry is an array
* containing two elements, the file, and the module
* name.
*/
public static function get(): array {
return Config::Get('system','routes',[]);
}
static function set($r) {
private static function set(array $r): mixed {
return Config::Set('system','routes',$r);
}
}

View File

@@ -8,6 +8,13 @@ class Widget {
static function register($file,$widget) {
$rt = self::get();
foreach ($rt as $r) {
if ($r[0] === $file && $r[1] === $widget) {
return;
}
}
$rt[] = [ $file, $widget ];
self::set($rt);
}
@@ -17,7 +24,7 @@ class Widget {
if($rt) {
$n = [];
foreach($rt as $r) {
if($r[0] !== $file && $r[1] !== $widget) {
if(!($r[0] === $file && $r[1] === $widget)) {
$n[] = $r;
}
}

View File

@@ -519,8 +519,8 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
* @return void
*/
function getDir() {
logger('GetDir: ' . $this->ext_path, LOGGER_DEBUG);
$this->auth->log();
$modulename = \App::$module;
@@ -538,7 +538,6 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$file = trim($file, '/');
$path_arr = explode('/', $file);
if (! $path_arr)
return;
@@ -558,9 +557,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$this->auth->owner_id = $channel_id;
$this->auth->owner_nick = $channel_name;
$path = '/' . $channel_name;
$folder = '';
$os_path = '';
$not_found = '';
for ($x = 1; $x < count($path_arr); $x++) {
$r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0",
@@ -568,15 +567,31 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
dbesc($path_arr[$x]),
intval($channel_id)
);
if ($r && intval($r[0]['is_dir'])) {
$folder = $r[0]['hash'];
if (strlen($os_path))
$os_path .= '/';
$os_path .= $folder;
$path = $path . '/' . $r[0]['filename'];
if (strlen($os_path)) {
$os_path .= '/';
}
$os_path .= $folder;
}
else {
// if we got a bogus path collect the
if (strlen($not_found)) {
$not_found .= ',';
}
$not_found .= $path_arr[$x];
}
}
if ($not_found) {
throw new DAV\Exception\NotFound("Path $file does not exist. One or more directories could not be found: $not_found");
}
$this->folder_hash = $folder;
$this->os_path = $os_path;
}

View File

@@ -13,15 +13,6 @@ use Zotlabs\Web\HTTPSig;
* @brief Network related functions.
*/
/**
* @brief Returns path to CA file.
*
* @return string
*/
function get_capath() {
return appdirpath() . '/library/cacert.pem';
}
/**
* @brief fetches an URL.
*
@@ -63,7 +54,6 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_HEADER, true);
@curl_setopt($ch, CURLINFO_HEADER_OUT, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
@curl_setopt($ch, CURLOPT_ENCODING, '');
@@ -262,7 +252,6 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_HEADER, true);
@curl_setopt($ch, CURLINFO_HEADER_OUT, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
@curl_setopt($ch, CURLOPT_POST,1);
@curl_setopt($ch, CURLOPT_POSTFIELDS,$params);

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@ HTML_FILE_EXTENSION = .html
HTML_COLORSTYLE = TOGGLE
GENERATE_LATEX = NO
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PRIVATE = NO
GENERATE_TODOLIST = YES
USE_MDFILE_AS_MAINPAGE = README.md
REFERENCED_BY_RELATION = YES