termux / termux-app

Termux - a terminal emulator application for Android OS extendible by variety of packages.
https://f-droid.org/en/packages/com.termux
Other
34.12k stars 3.59k forks source link

[Bug]: The LICENSE file describing termux-shared does not appear to allow the use case described in the wiki. #3150

Open BLuFeNiX opened 1 year ago

BLuFeNiX commented 1 year ago

Problem description

Hi, I think I've identified an incompatibility with the termux-shared library's license and the instructions on the wiki here and also here.

Assumptions

  1. The Termux project intends for 3rd party apps to use the termux-shared library constants for integration.
  2. Integration with the library constants is not intended to cause the 3rd party app to adopt the GPLv3.

These assumptions seem clear based on the advice that:

Termux plugins and 3rd party apps only need to import termux-shared library for interacting with the termux-app, like for using TermuxConstants and all other utilities provided by it.`

And the license file specifies exceptions for the contants files by name:

GPLv3 only

The GPLv3 only license applies to all files unless specifically specified by a file/directory, like the src/main/java/com/termux/shared/termux/TermuxConstants.java and src/main/java/com/termux/shared/termux/settings/properties/TermuxPropertyConstants.java files are released under the MIT license.

It seems clear that you want people to use the constants files freely, since they are MIT licensed.

The Problem

The GPLv3 affects any software that is compiled with or linked to GPLv3-licensed code. The GPL uses a very broad definition for linking, including things like interpreted code and classpath resources. Specifically, this includes importing a GPLv3-licensed library via the wiki's suggestion of implementation 'com.termux.termux-app:termux-shared:0.117' or downloading the aar file directly. For this reason, there is a "classpath exception" that the author may apply to the GPLv3, but this is not currently the case for the files in src/main/java/com/termux/shared/termux.

This means that when including termux-shared in your project, you are linking to a GPLv3 library, and your application is now subject to the GPL. If the app is then distributed, it is not only redistributing termux-shared, but the app itself is also being conveyed as a modified version of termux-shared due to the classpath "linking" that occurs when importing the library. This results in the entire app being legally subject to the GPLv3, and any party that receives the application is now entitled to the entire source code, pursuant to the GPLv3 terms.

I tested to make sure there wasn't something prevented this, and I have confirmed that a sample Android app that merely declares implementation 'com.termux.termux-app:termux-shared:0.117' will contain GPLv3 Java bytecode in the resulting APK.

Workarounds

This issue can be avoided by doing one of the following:

Steps to reproduce the behavior.

N/A

What is the expected behavior?

A developer is provided a way to integrate with the Termux API without being forced to license their code under the GPLv3.

System information

agnostic-apollo commented 1 year ago

Thanks for opening this.

The TermuxConstants class does not import any other file, including any other GPLv3 file. I checked a built apk file as well that imported the latest lib and the TermuxConstants class and its the same.

However, something freaky is going on during build times of the app, possibly some optimization. For example, the MIT licensed com.termux.shared.file.FileUtilsErrno if used is importing the GPLv3 licensed com.termux.shared.termux.extrakeys.ExtraKeysView because they are both using the same 400 int value.

https://github.com/termux/termux-app/blob/2f5a6f7de663074df829a62e44a23ee70e932763/termux-shared/src/main/java/com/termux/shared/file/FileUtilsErrno.java#L83

https://github.com/termux/termux-app/blob/2f5a6f7de663074df829a62e44a23ee70e932763/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeysView.java#L137

Built apk

public static final Errno ERRNO_INVALID_FILE_PERMISSIONS_STRING_TO_CHECK = new Errno(TYPE, ExtraKeysView.FALLBACK_LONG_PRESS_DURATION, "The file permission string to check is invalid.");

The androidx.core.hardware.display.DisplayManagerCompat is importing ExtraKeyButton.KEY_DISPLAY_NAME because of same display constant string value, even though they are not even in the same library.

https://github.com/androidx/androidx/blob/95d27864018b07ad035a53710aaf761dd37dd37f/core/core/src/main/java/androidx/core/hardware/display/DisplayManagerCompat.java#L89

https://github.com/termux/termux-app/blob/2f5a6f7de663074df829a62e44a23ee70e932763/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeyButton.java#L23

Built apk

return Api17Impl.getDisplay((DisplayManager) this.mContext.getSystemService(ExtraKeyButton.KEY_DISPLAY_NAME), displayId);

I see similar usage in other files, causing GPLv3 code to be included in the apk. I don't know why that is happening, don't see anything related from a quick google search, will need investigation.

Termux can modify its license to clarify the issue (ex: with a classpath exception).

That can't be done. It will allow closed sourced apps to use GPLv3 code without having to release sources.

Termux can release a new library that only contains the MIT licensed files.

This is how its planned to be done in future. The termux-shared library is going to be split into multiple libraries and TermuxConstants and possibly other constants files moved to dedicated library.

BLuFeNiX commented 1 year ago

@agnostic-apollo Thanks so much for the reply.

I think the full library contents will always be packaged into the APK if the developer has set minify false (which is the default). So, the only foolproof solution is a different library (which I see you have acknowledged as a planned feature).

However, even when using minify true, it still might pull in GPLv3 code. For example, simply referencing TermuxConstants.TERMUX_API_APP_NAME will not pull in extra classes (the constant itself is moved into an inline string), but referencing TermuxConstants.class.getSimpleName() will force the class itself to be included, which then results in a large number of additional files in the APK.

As I was digging into this some more, I realized that the files in this repo do not seem to match the structure in the termux-shared library. For example, TermuxTerminalSessionClientBase can be found in com.termux.shared.termux.terminal in the repo, but the library has that same file in com.termux.shared.terminal (missing the second termux).

I'm not sure whether that is the cause of the problem, or is simply an extra confusing detail.