Skip to main content
warning

There is a pending German patent application with the application number 10 2023 125 012.4. In order to use the TREND watermarker Software in the form published here, a patent license is required in addition to the license for the Software. See LICENSE for more information. In case of any questions or uncertainties, please contact us at trend@isst.fraunhofer.de.

info

This documentation is in a pretty early stage and updated continuously. Watch it!

Concepts

Overview

Kotlin Multiplatform

Our library is developed as Kotlin Multiplatform Library with support for Kotlin, Java, and JavaScript. This allows the library to be used in any JVM compatible language ( e.g., Java, Kotlin), Node.js, and in plain JavaScript (e.g., browsers).

In some cases, different code is required for different platforms. In such cases the expect and actual feature of Kotlin is used, or some features (like operating on files) are only available on some platforms. Because of this, code in the same package can be in different paths, depending on the compilation target. For this reason the following refers to packages instead of paths.

  • Example: when compiling for JVM, the package de.fraunhofer.isst.trend.watermarker.files contains *.kt files from src/commonMain/kotlin/files and src/jvmMain/kotlin/files.

Code Base

The watermarker library offers two main functionalities:

  1. Insert and extract watermarks: insert and extract additional information into/from files/data.
  2. Generate and parse watermarks: generate and parse information that are used as watermarks.

These tasks seem similar but are very independent of each other. The only requirement they share is the data format: the library inserts and extracts bytes as watermarks, therefore the generate and parse watermarks task must be able to generate and parse bytes.

The classes Watermarker and JvmWatermarker are designed to offer an easy entry point for users to insert and extract watermarks from all supported file types without requiring any additional configuration. Only users with special requirements should have to familiarize themselves with the individual classes.

Error Handling

We handle errors (and warnings) as values, not as exceptions. Our library should not throw any exceptions, instead functions which can fail should return a Status or a Result if they return a value. See Error Handling for details.


Insert and Extract Watermarks

The code in the package de.fraunhofer.isst.trend.watermarker.files is responsible to parse and generate supported file types in memory:

  • all classes adding support for a file type must implement the interface WatermarkableFile
  • the classes should offer functions to modify the contents of the file when possible
    • Example: ZipFile offers functions to add/remove extra fields into the header section of zip files
  • if the class allows customizing its behavior, a builder class should be implemented which allows generating an instance with default settings as well as specifying all its customization options.

The code in the package de.fraunhofer.isst.trend.watermarker.fileWatermarker is responsible to insert and extract watermarks into WatermarkableFiles:

  • for each instance of WatermarkableFile, a class implementing FileWatermarker for that specific instance should exist (e.g., ZipWatermarker for ZipFile) which is responsible to insert, extract and remove watermarks into/from that WatermarkableFile while maintaining a valid file.
  • if the class allows customizing its behavior, a builder class should be implemented which allows generating an instance with default settings as well as specifying all its customization options.

Generate and Parse Watermarks

The code in the package de.fraunhofer.isst.trend.watermarker.watermarks is responsible for generating watermarks and parsing extracted watermarks:

  • The class Watermark is the most basic watermark that offers very limited functionality but is used as a base class for many functions that expect a watermark as parameter and for more sophisticated watermarks. All watermarks should directly or indirectly inherit from this class.
  • The class Trendmark implements a watermark scheme that uses the first byte of the watermark as tag to identify the format of the watermark. The format defines if additional information about the watermark (e.g., size, checksums, or hashes) are included in the watermark. The format of the content itself is not defined in detail (e.g., text, certificate, image, ...), but general information about the content are defined (currently only whether the content is compressed). For more details see the Trendmark documentation section. This implies that a user extracting a Trendmark must know the type of content but not the format used to store the content.
    • To offer convenient functions to generate, modify, and parse Trendmarks with specific content (e.g., text, certificate, ...) the interface TrendmarkBuilder can be used to implement a class with a builder-like pattern (e.g., TextWatermark).

Error Handling

We handle errors (and warnings) as values, not as exceptions. Our library should not throw any exceptions, instead functions which can fail should return a Status or a Result if they return a value. This allows us to provide detailed reports what happened during the execution of a function, including warnings and custom success messages holding additional information, like the exact source of the message. Furthermore, this approach enforces explicit error handling, even if the dev decides to ignore the error, before accessing the return value of a function (because the type is different). To see an example how you can handle such return values see the CLI tool. For more advanced usages see Trendmark or TextWatermark.

Status

A Status represents the outcome of a function, without a return value, that is not guaranteed to succeed. To be able to report any issues (or just additional information) that occurred during the execution of a function, the class Status contains a list of Events that occurred during the execution. A Status that represents a success might not contain an Event. Multiple Status objects can be combined to propagate the reports.

Event

An Event represents different kinds of events that can occur during the execution of a function. There are 3 base variants:

The variants Warning and Error are abstract: For each event that can occur, a unique class must be created that overrides the function getMessage(): String to explain the event. If a success message with additional information is required, a new class inheriting from Success can be created. All variants, but the default Success variant, require a source string which should explain the origin of the event (e.g., className.functionName).

Result

A Result represents the outcome of a function, with a return value, that is not guaranteed to succeed. It functions like a Status (it uses a Status internally) but also has a generic member value that can contain the return value. When the Status is in success or warning state it must contain a value, otherwise it should not contain a value.