nextcloud / files_accesscontrol

šŸš« App to manage access control for files
https://apps.nextcloud.com/apps/files_accesscontrol
50 stars 20 forks source link

Error when trying to create version directory structure #591

Closed juliushaertl closed 6 days ago

juliushaertl commented 2 weeks ago

This trace blocked file creation from templates where there is a second write to a file:

It looks like the path extraction logic is not working properly if the versions backend tries to create missing directory structures (when the file is written in a subdirectory).


{
  "reqId": "bOWsJWruz89BUKyg3hqR",
  "level": 3,
  "time": "2024-09-01T11:26:12+00:00",
  "remoteAddr": "95.118.78.43",
  "user": "christine",
  "app": "no app in context",
  "method": "POST",
  "url": "/ocs/v2.php/apps/files/api/v1/templates/create",
  "message": "substr(): Argument #3 ($length) must be of type ?int, bool given in file '/var/www/example.com/apps/files_accesscontrol/lib/Operation.php' line 137",
  "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:129.0) Gecko/20100101 Firefox/129.0",
  "version": "30.0.0.11",
  "exception": {
    "Exception": "Exception",
    "Message": "substr(): Argument #3 ($length) must be of type ?int, bool given in file '/var/www/example.com/apps/files_accesscontrol/lib/Operation.php' line 137",
    "Code": 0,
    "Trace": [
      {
        "file": "/var/www/example.com/lib/private/AppFramework/App.php",
        "line": 161,
        "function": "dispatch",
        "class": "OC\\AppFramework\\Http\\Dispatcher",
        "type": "->"
      },
      {
        "file": "/var/www/example.com/lib/private/Route/Router.php",
        "line": 302,
        "function": "main",
        "class": "OC\\AppFramework\\App",
        "type": "::"
      },
      {
        "file": "/var/www/example.com/ocs/v1.php",
        "line": 43,
        "function": "match",
        "class": "OC\\Route\\Router",
        "type": "->"
      },
      {
        "file": "/var/www/example.com/ocs/v2.php",
        "line": 7,
        "args": [
          "/var/www/example.com/ocs/v1.php"
        ],
        "function": "require_once"
      }
    ],
    "File": "/var/www/example.com/lib/private/AppFramework/Http/Dispatcher.php",
    "Line": 146,
    "Previous": {
      "Exception": "TypeError",
      "Message": "substr(): Argument #3 ($length) must be of type ?int, bool given",
      "Code": 0,
      "Trace": [
        {
          "file": "/var/www/example.com/apps/files_accesscontrol/lib/Operation.php",
          "line": 137,
          "function": "substr"
        },
        {
          "file": "/var/www/example.com/apps/files_accesscontrol/lib/Operation.php",
          "line": 63,
          "function": "translatePath",
          "class": "OCA\\FilesAccessControl\\Operation",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/apps/files_accesscontrol/lib/StorageWrapper.php",
          "line": 43,
          "function": "checkFileAccess",
          "class": "OCA\\FilesAccessControl\\Operation",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/apps/files_accesscontrol/lib/StorageWrapper.php",
          "line": 58,
          "function": "checkFileAccess",
          "class": "OCA\\FilesAccessControl\\StorageWrapper",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/Storage/Wrapper/Wrapper.php",
          "line": 69,
          "function": "mkdir",
          "class": "OCA\\FilesAccessControl\\StorageWrapper",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/View.php",
          "line": 1136,
          "function": "mkdir",
          "class": "OC\\Files\\Storage\\Wrapper\\Wrapper",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/View.php",
          "line": 208,
          "function": "basicOperation",
          "class": "OC\\Files\\View",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/apps/files_versions/lib/Storage.php",
          "line": 959,
          "function": "mkdir",
          "class": "OC\\Files\\View",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/apps/files_versions/lib/Versions/LegacyVersionsBackend.php",
          "line": 150,
          "function": "createMissingDirectories",
          "class": "OCA\\Files_Versions\\Storage",
          "type": "::",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/example.com/apps/files_versions/lib/Versions/VersionManager.php",
          "line": 81,
          "function": "createVersion",
          "class": "OCA\\Files_Versions\\Versions\\LegacyVersionsBackend",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/example.com/apps/files_versions/lib/Storage.php",
          "line": 209,
          "function": "createVersion",
          "class": "OCA\\Files_Versions\\Versions\\VersionManager",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/example.com/apps/files_versions/lib/Listener/FileEventsListener.php",
          "line": 174,
          "function": "store",
          "class": "OCA\\Files_Versions\\Storage",
          "type": "::"
        },
        {
          "file": "/var/www/example.com/apps/files_versions/lib/Listener/FileEventsListener.php",
          "line": 80,
          "function": "write_hook",
          "class": "OCA\\Files_Versions\\Listener\\FileEventsListener",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/EventDispatcher/ServiceEventListener.php",
          "line": 68,
          "function": "handle",
          "class": "OCA\\Files_Versions\\Listener\\FileEventsListener",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
          "line": 230,
          "function": "__invoke",
          "class": "OC\\EventDispatcher\\ServiceEventListener",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
          "line": 59,
          "function": "callListeners",
          "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/EventDispatcher/EventDispatcher.php",
          "line": 67,
          "function": "dispatch",
          "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/EventDispatcher/EventDispatcher.php",
          "line": 79,
          "function": "dispatch",
          "class": "OC\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/Node/HookConnector.php",
          "line": 74,
          "function": "dispatchTyped",
          "class": "OC\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/legacy/OC_Hook.php",
          "line": 82,
          "function": "write",
          "class": "OC\\Files\\Node\\HookConnector",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/View.php",
          "line": 1252,
          "function": "emit",
          "class": "OC_Hook",
          "type": "::"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/View.php",
          "line": 1119,
          "function": "runHooks",
          "class": "OC\\Files\\View",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/View.php",
          "line": 644,
          "function": "basicOperation",
          "class": "OC\\Files\\View",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/Node/File.php",
          "line": 52,
          "function": "file_put_contents",
          "class": "OC\\Files\\View",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/apps/richdocuments/lib/Listener/FileCreatedFromTemplateListener.php",
          "line": 62,
          "function": "putContent",
          "class": "OC\\Files\\Node\\File",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/EventDispatcher/ServiceEventListener.php",
          "line": 68,
          "function": "handle",
          "class": "OCA\\Richdocuments\\Listener\\FileCreatedFromTemplateListener",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
          "line": 230,
          "function": "__invoke",
          "class": "OC\\EventDispatcher\\ServiceEventListener",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
          "line": 59,
          "function": "callListeners",
          "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/EventDispatcher/EventDispatcher.php",
          "line": 67,
          "function": "dispatch",
          "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/EventDispatcher/EventDispatcher.php",
          "line": 79,
          "function": "dispatch",
          "class": "OC\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Files/Template/TemplateManager.php",
          "line": 162,
          "function": "dispatchTyped",
          "class": "OC\\EventDispatcher\\EventDispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/apps/files/lib/Controller/TemplateController.php",
          "line": 69,
          "function": "createFromTemplate",
          "class": "OC\\Files\\Template\\TemplateManager",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/example.com/lib/private/AppFramework/Http/Dispatcher.php",
          "line": 208,
          "function": "create",
          "class": "OCA\\Files\\Controller\\TemplateController",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/example.com/lib/private/AppFramework/Http/Dispatcher.php",
          "line": 114,
          "function": "executeController",
          "class": "OC\\AppFramework\\Http\\Dispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/AppFramework/App.php",
          "line": 161,
          "function": "dispatch",
          "class": "OC\\AppFramework\\Http\\Dispatcher",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/lib/private/Route/Router.php",
          "line": 302,
          "function": "main",
          "class": "OC\\AppFramework\\App",
          "type": "::"
        },
        {
          "file": "/var/www/example.com/ocs/v1.php",
          "line": 43,
          "function": "match",
          "class": "OC\\Route\\Router",
          "type": "->"
        },
        {
          "file": "/var/www/example.com/ocs/v2.php",
          "line": 7,
          "args": [
            "/var/www/example.com/ocs/v1.php"
          ],
          "function": "require_once"
        }
      ],
      "File": "/var/www/example.com/apps/files_accesscontrol/lib/Operation.php",
      "Line": 137
    },
    "message": "substr(): Argument #3 ($length) must be of type ?int, bool given in file '/var/www/example.com/apps/files_accesscontrol/lib/Operation.php' line 137",
    "exception": {},
    "CustomMessage": "substr(): Argument #3 ($length) must be of type ?int, bool given in file '/var/www/example.com/apps/files_accesscontrol/lib/Operation.php' line 137"
  }
}
SystemKeeper commented 1 week ago

The same seems to also happen when copying an excel file and then trying to edit it with Nextcloud Office:

"app":"richdocuments",
"method":"POST",
"url":"/index.php/apps/richdocuments/wopi/files/112...8/contents?access_token=yED....&access_token_ttl=0"
{
    "Exception": "Exception",
    "Message": "substr(): Argument #3 ($length) must be of type ?int, bool given in file '/var/www/nextcloud/apps/files_accesscontrol/lib/Operation.php' line 137",
    "Code": 0,
    "Trace": [
        {
            "file": "/var/www/nextcloud/lib/private/AppFramework/App.php",
            "line": 161,
            "function": "dispatch",
            "class": "OC\\AppFramework\\Http\\Dispatcher",
            "type": "->"
        },
        {
            "file": "/var/www/nextcloud/lib/private/Route/Router.php",
            "line": 309,
            "function": "main",
            "class": "OC\\AppFramework\\App",
            "type": "::"
        },
        {
            "file": "/var/www/nextcloud/lib/base.php",
            "line": 996,
            "function": "match",
            "class": "OC\\Route\\Router",
            "type": "->"
        },
        {
            "file": "/var/www/nextcloud/index.php",
            "line": 24,
            "function": "handleRequest",
            "class": "OC",
            "type": "::"
        }
    ],
    "File": "/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php",
    "Line": 146,
    "Previous": {
        "Exception": "TypeError",
        "Message": "substr(): Argument #3 ($length) must be of type ?int, bool given",
        "Code": 0,
        "Trace": [
            {
                "file": "/var/www/nextcloud/apps/files_accesscontrol/lib/Operation.php",
                "line": 137,
                "function": "substr"
            },
            {
                "file": "/var/www/nextcloud/apps/files_accesscontrol/lib/Operation.php",
                "line": 63,
                "function": "translatePath",
                "class": "OCA\\FilesAccessControl\\Operation",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/files_accesscontrol/lib/StorageWrapper.php",
                "line": 43,
                "function": "checkFileAccess",
                "class": "OCA\\FilesAccessControl\\Operation",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/files_accesscontrol/lib/StorageWrapper.php",
                "line": 58,
                "function": "checkFileAccess",
                "class": "OCA\\FilesAccessControl\\StorageWrapper",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/View.php",
                "line": 1136,
                "function": "mkdir",
                "class": "OCA\\FilesAccessControl\\StorageWrapper",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/View.php",
                "line": 208,
                "function": "basicOperation",
                "class": "OC\\Files\\View",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/files_versions/lib/Storage.php",
                "line": 959,
                "function": "mkdir",
                "class": "OC\\Files\\View",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/files_versions/lib/Versions/LegacyVersionsBackend.php",
                "line": 150,
                "function": "createMissingDirectories",
                "class": "OCA\\Files_Versions\\Storage",
                "type": "::",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/nextcloud/apps/files_versions/lib/Versions/VersionManager.php",
                "line": 81,
                "function": "createVersion",
                "class": "OCA\\Files_Versions\\Versions\\LegacyVersionsBackend",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/nextcloud/apps/files_versions/lib/Storage.php",
                "line": 209,
                "function": "createVersion",
                "class": "OCA\\Files_Versions\\Versions\\VersionManager",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/nextcloud/apps/files_versions/lib/Listener/FileEventsListener.php",
                "line": 174,
                "function": "store",
                "class": "OCA\\Files_Versions\\Storage",
                "type": "::"
            },
            {
                "file": "/var/www/nextcloud/apps/files_versions/lib/Listener/FileEventsListener.php",
                "line": 80,
                "function": "write_hook",
                "class": "OCA\\Files_Versions\\Listener\\FileEventsListener",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/EventDispatcher/ServiceEventListener.php",
                "line": 68,
                "function": "handle",
                "class": "OCA\\Files_Versions\\Listener\\FileEventsListener",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
                "line": 230,
                "function": "__invoke",
                "class": "OC\\EventDispatcher\\ServiceEventListener",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/3rdparty/symfony/event-dispatcher/EventDispatcher.php",
                "line": 59,
                "function": "callListeners",
                "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/EventDispatcher/EventDispatcher.php",
                "line": 67,
                "function": "dispatch",
                "class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/EventDispatcher/EventDispatcher.php",
                "line": 79,
                "function": "dispatch",
                "class": "OC\\EventDispatcher\\EventDispatcher",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/Node/HookConnector.php",
                "line": 74,
                "function": "dispatchTyped",
                "class": "OC\\EventDispatcher\\EventDispatcher",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/legacy/OC_Hook.php",
                "line": 82,
                "function": "write",
                "class": "OC\\Files\\Node\\HookConnector",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/View.php",
                "line": 560,
                "function": "emit",
                "class": "OC_Hook",
                "type": "::"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/View.php",
                "line": 603,
                "function": "emit_file_hooks_pre",
                "class": "OC\\Files\\View",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/Node/File.php",
                "line": 52,
                "function": "file_put_contents",
                "class": "OC\\Files\\View",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/richdocuments/lib/Controller/WopiController.php",
                "line": 467,
                "function": "putContent",
                "class": "OC\\Files\\Node\\File",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/richdocuments/lib/Controller/WopiController.php",
                "line": 756,
                "function": "OCA\\Richdocuments\\Controller\\{closure}",
                "class": "OCA\\Richdocuments\\Controller\\WopiController",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/nextcloud/apps/richdocuments/lib/Controller/WopiController.php",
                "line": 733,
                "function": "retryOperation",
                "class": "OCA\\Richdocuments\\Controller\\WopiController",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Files/Lock/LockManager.php",
                "line": 68,
                "function": "OCA\\Richdocuments\\Controller\\{closure}",
                "class": "OCA\\Richdocuments\\Controller\\WopiController",
                "type": "->",
                "args": [
                    "*** sensitive parameters replaced ***"
                ]
            },
            {
                "file": "/var/www/nextcloud/apps/richdocuments/lib/Controller/WopiController.php",
                "line": 736,
                "function": "runInScope",
                "class": "OC\\Files\\Lock\\LockManager",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/apps/richdocuments/lib/Controller/WopiController.php",
                "line": 466,
                "function": "wrappedFilesystemOperation",
                "class": "OCA\\Richdocuments\\Controller\\WopiController",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php",
                "line": 208,
                "function": "putFile",
                "class": "OCA\\Richdocuments\\Controller\\WopiController",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/AppFramework/Http/Dispatcher.php",
                "line": 114,
                "function": "executeController",
                "class": "OC\\AppFramework\\Http\\Dispatcher",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/AppFramework/App.php",
                "line": 161,
                "function": "dispatch",
                "class": "OC\\AppFramework\\Http\\Dispatcher",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/lib/private/Route/Router.php",
                "line": 309,
                "function": "main",
                "class": "OC\\AppFramework\\App",
                "type": "::"
            },
            {
                "file": "/var/www/nextcloud/lib/base.php",
                "line": 996,
                "function": "match",
                "class": "OC\\Route\\Router",
                "type": "->"
            },
            {
                "file": "/var/www/nextcloud/index.php",
                "line": 24,
                "function": "handleRequest",
                "class": "OC",
                "type": "::"
            }
        ],
        "File": "/var/www/nextcloud/apps/files_accesscontrol/lib/Operation.php",
        "Line": 137
    }
nickvergessen commented 6 days ago

Managed to track it down. I was a bit confused as the code is the same for a long time, but

Without declare strict

<?php

$p = 'Templates/New text file.md';
var_dump(substr($p, 0, strrpos($p, '.v')));
āœ… string(0) ""

With declare strict which I added in July:

<?php

declare(strict_types=1);

$p = 'Templates/New text file.md';
var_dump(substr($p, 0, strrpos($p, '.v')));
šŸ’„ Fatal error: Uncaught TypeError: substr(): Argument #3 ($length) must be of type ?int, false given in /in/pTvaa:6
Stack trace:
#0 /in/pTvaa(6): substr('Templates/New t...', 0, false)
#1 {main}
  thrown in /in/pTvaa on line 6

Process exited with code 255.