Xposed-Modules-Repo / com.github.dan.nostoragerestrict

NoStorageRestrict
https://github.com/Xposed-Modules-Repo/com.github.dan.nostoragerestrict
GNU General Public License v3.0
299 stars 15 forks source link

Bypass the LOCAL_ONLY restriction #6

Closed mariuszste closed 1 year ago

mariuszste commented 1 year ago

some apps se the Intent.EXTRA_LOCAL_ONLY that forces non-local storage providers to be hidden. An option to strip this flag would be awesome, It's a storage restriction after all ;). If you need an app to test with you can use obsidian

here is the code they are using (decompiled):

@PluginMethod
    public void choose(PluginCall pluginCall) {
        try {
            Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT_TREE");
            if (Build.VERSION.SDK_INT >= 26) {
                try {
                    Uri parse = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3ADocuments");
                    intent.putExtra("android.provider.extra.INITIAL_URI", DocumentsContract.buildDocumentUriUsingTree(parse, DocumentsContract.getTreeDocumentId(parse)));
                } catch (Exception unused) {
                }
            }
            if (Build.VERSION.SDK_INT >= 23) {
                intent.putExtra("android.provider.extra.PROMPT", "Allow Write Permission");
            }
            intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
            intent.putExtra("android.intent.extra.LOCAL_ONLY", true);
            intent.addFlags(195);
            startActivityForResult(pluginCall, intent, "onOpenDocumentTree");
        } catch (Exception e) {
            pluginCall.reject("Failed to choose folder: " + e.getLocalizedMessage());
        }
    }
DanGLES3 commented 1 year ago

some apps se the Intent.EXTRA_LOCAL_ONLY that forces non-local storage providers to be hidden. An option to strip this flag would be awesome, It's a storage restriction after all ;). If you need an app to test with you can use obsidian

here is the code they are using (decompiled):

@PluginMethod
    public void choose(PluginCall pluginCall) {
        try {
            Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT_TREE");
            if (Build.VERSION.SDK_INT >= 26) {
                try {
                    Uri parse = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3ADocuments");
                    intent.putExtra("android.provider.extra.INITIAL_URI", DocumentsContract.buildDocumentUriUsingTree(parse, DocumentsContract.getTreeDocumentId(parse)));
                } catch (Exception unused) {
                }
            }
            if (Build.VERSION.SDK_INT >= 23) {
                intent.putExtra("android.provider.extra.PROMPT", "Allow Write Permission");
            }
            intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
            intent.putExtra("android.intent.extra.LOCAL_ONLY", true);
            intent.addFlags(195);
            startActivityForResult(pluginCall, intent, "onOpenDocumentTree");
        } catch (Exception e) {
            pluginCall.reject("Failed to choose folder: " + e.getLocalizedMessage());
        }
    }

I'll consider, tho to my limited skills it may be easier to just block the behavior from the provider itself, then again I'll have to look into the code to see what I can do

DanGLES3 commented 1 year ago

some apps se the Intent.EXTRA_LOCAL_ONLY that forces non-local storage providers to be hidden. An option to strip this flag would be awesome, It's a storage restriction after all ;). If you need an app to test with you can use obsidian

here is the code they are using (decompiled):

@PluginMethod
    public void choose(PluginCall pluginCall) {
        try {
            Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT_TREE");
            if (Build.VERSION.SDK_INT >= 26) {
                try {
                    Uri parse = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3ADocuments");
                    intent.putExtra("android.provider.extra.INITIAL_URI", DocumentsContract.buildDocumentUriUsingTree(parse, DocumentsContract.getTreeDocumentId(parse)));
                } catch (Exception unused) {
                }
            }
            if (Build.VERSION.SDK_INT >= 23) {
                intent.putExtra("android.provider.extra.PROMPT", "Allow Write Permission");
            }
            intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
            intent.putExtra("android.intent.extra.LOCAL_ONLY", true);
            intent.addFlags(195);
            startActivityForResult(pluginCall, intent, "onOpenDocumentTree");
        } catch (Exception e) {
            pluginCall.reject("Failed to choose folder: " + e.getLocalizedMessage());
        }
    }

In the case of this allow write permission i'm not sure how would Obsidian be able to handle cloud storage, i'll try on my end tho my suspicion is that it's likely to break the app as one isn't supposed to "grant write permissions" to cloud storage devices afaik

DanGLES3 commented 1 year ago

some apps se the Intent.EXTRA_LOCAL_ONLY that forces non-local storage providers to be hidden. An option to strip this flag would be awesome, It's a storage restriction after all ;). If you need an app to test with you can use obsidian

here is the code they are using (decompiled):

@PluginMethod
    public void choose(PluginCall pluginCall) {
        try {
            Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT_TREE");
            if (Build.VERSION.SDK_INT >= 26) {
                try {
                    Uri parse = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3ADocuments");
                    intent.putExtra("android.provider.extra.INITIAL_URI", DocumentsContract.buildDocumentUriUsingTree(parse, DocumentsContract.getTreeDocumentId(parse)));
                } catch (Exception unused) {
                }
            }
            if (Build.VERSION.SDK_INT >= 23) {
                intent.putExtra("android.provider.extra.PROMPT", "Allow Write Permission");
            }
            intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
            intent.putExtra("android.intent.extra.LOCAL_ONLY", true);
            intent.addFlags(195);
            startActivityForResult(pluginCall, intent, "onOpenDocumentTree");
        } catch (Exception e) {
            pluginCall.reject("Failed to choose folder: " + e.getLocalizedMessage());
        }
    }

So yeah, turns out forcefully ignoring that flag with Xposed just results in all storage devices (except the internal storage) being hidden, and stripping the flag from Obsidian code seems to do absolutely nothing

After looking into it, it seems SAF indeed straight up lacks the capability of granting cloud access to third party apps

mariuszste commented 1 year ago

After looking into it, it seems SAF indeed straight up lacks the capability of granting cloud access to third party apps

nope, Titanium Backups can do it just fine. (Menu -> General/Preferences -> Backup settings/Backup folder location -> Storage framework (click to change) -> DocumentProvider storage -> select cloud service) The only bug with it is that it can not create a folder for the backups so you have to go and make one yourself and then pick the parent folder in the SAF prompt and the subfolder afterwards in the app. Create a backup of a app and the files will appear there just fine.

Edit: total commander can also do it just fine. Just add "user defined location", pick cloud, and you can read and write no problem, directory creation also works just fine

DanGLES3 commented 1 year ago

After looking into it, it seems SAF indeed straight up lacks the capability of granting cloud access to third party apps

nope, Titanium Backups can do it just fine. (Menu -> General/Preferences -> Backup settings/Backup folder location -> Storage framework (click to change) -> DocumentProvider storage -> select cloud service) The only bug with it is that it can not create a folder for the backups so you have to go and make one yourself and then pick the parent folder in the SAF prompt and the subfolder afterwards in the app. Create a backup of a app and the files will appear there just fine.

Edit: total commander can also do it just fine. Just add "user defined location", pick cloud, and you can read and write no problem, directory creation also works just fine

Wel, then they're doing something more than just not include the local only intent. Because I've even tried removing that flag from obsidian's code and it didn't work

DanGLES3 commented 1 year ago

After looking into it, it seems SAF indeed straight up lacks the capability of granting cloud access to third party apps

nope, Titanium Backups can do it just fine. (Menu -> General/Preferences -> Backup settings/Backup folder location -> Storage framework (click to change) -> DocumentProvider storage -> select cloud service) The only bug with it is that it can not create) a folder for the backups so you have to go and make one yourself and then pick the parent folder in the SAF prompt and the subfolder afterwards in the app. Create a backup of a app and the files will appear there just fine.

Edit: total commander can also do it just fine. Just add "user defined location", pick cloud, and you can read and write no problem, directory creation also works just fine

Also, I've just tried Total Commander here and it doesn't show cloud services when doing the steps mentioned

https://github.com/Xposed-Modules-Repo/com.github.dan.nostoragerestrict/assets/32078304/37d37055-d065-4c03-ad98-2c7773cff33a

mariuszste commented 1 year ago

So a few things:

  1. you are not seeing any cloud providers because the ones you have don't support OPEN_DOCUMENT_TREE (Nextcloud supports it for example, CIFS documents provider is also a good one I've used in the past to use network shares as storage)
  2. forcing LOCAL_ONLY to false with Frida for obsidian does show me my cloud provider that I want but after selecting it, it fails later down the line so this will require more patching to get working. (still, this could work for some aps but I'm guessing many more will also crash so probably best to leave it alone)

Sorry for wasting your your time, I should have tested a POC before saying anything.

DanGLES3 commented 1 year ago

So a few things:

  1. you are not seeing any cloud providers because the ones you have don't support OPEN_DOCUMENT_TREE (Nextcloud supports it for example, CIFS documents provider is also a good one I've used in the past to use network shares as storage)
  2. forcing LOCAL_ONLY to false with Frida for obsidian does show me my cloud provider that I want but after selecting it, it fails later down the line so this will require more patching to get working. (still, this could work for some aps but I'm guessing many more will also crash so probably best to leave it alone)

Sorry for wasting your your time, I should have tested a POC before saying anything.

Don't sorry, I'll keep looking into it whenever I can, if i make some progress I'll be sure to notify you