# Technical information about Deark #

This document is a supplement to the information in the [readme.md](readme.md)
file.

## Mission statement ##

Deark has several related purposes:

* To find interesting things that are stored in files, but usually ignored,
such as thumbnail images and comments.

* To rescue data from uncommon file formats, and to be a convenient way to
decode many different formats.

* The "-d" option is a core feature, and can help to learn about a file and its
format, whether or not anything is extracted from it.

* Digital preservation of information about file formats. Its source code
encapsulates information about some formats that might otherwise be hard to
find.

There's not much rhyme or reason to the formats Deark supports, or to its
features. It exists mainly because I've written too many one-off programs to
decode file formats, and wanted to put everything in one place. Part of the
goal is to support (mainly old) formats that are under-served by other
open-source software. Many of the formats it currently supports are related to
either graphics or compression/archiving, but it is not limited to such
formats.

## Security ##

Deark is intended to be safe to use with untrusted input files, but there are
no promises. It is written in C, and vulnerabilities very likely exist.

A strategically-designed input file can definitely cause Deark to use a
disproportionate amount of system resources, such as disk space or CPU time.
Deark does enforce some resource limits, but not consistently. This is a
difficult problem to solve.

The best way to reduce the attack surface is to use the -onlymods option. Other
options that can improve security include -onlydetect, -m, -maxfiles,
-maxfilesize, -maxtotalsize, -zip.

## The filename problem ##

When Deark writes a file, it has to decide what to name it. This can be a very
difficult problem. For one thing, what is and is not a valid filename depends
on the user's platform, and the relevant filesystem type. For another thing,
there are security hazards everywhere. Deark should not try to write a file
named "/etc/passwd", for example.

Also, there are a near-limitless number of reasonable ways to construct an
output filename, with an elaborate decision tree to select the best behavior
in various circumstances.

Deark essentially throws up its hands and gives up. By default, it names all
output filenames to start with "output.". It overwrites existing files with no
warning (unless you use -n). It bans all ASCII characters that could
conceivably be problematical, as well as any non-ASCII characters that don't
appear on its whitelist.

When Deark writes to a ZIP or tar file (the "-zip"/"-tar" option), it doesn't
have to worry about what to name the internal files. It can palm that problem
off onto your unzip/untar program. It is more tolerant in this case.

Directory paths are only maintained as such if you use -zip/-tar (and you don't
use "-opt archive:subdirs=0"). Deark generally does not write a file anywhere
other than the current directory, though you can tell it to do so with -od, or
with other options such as -arcfn or -k3.

## The "Is this one format or two?" problem ##

It's often hard to decide whether a format should get its own module, or be a
part of some other module. Deark has some guidelines for this, but doesn't
always follow them consistently.

Modules are not supposed to make use of the input filename, except during
format detection. So if two formats can't be distinguished in any other way,
they generally have to be placed in separate modules. 

## Format detection ##

If the user does not use the "-m" option, then Deark will try to guess the best
module to use. It prefers to do this using only the contents of the file, but
unfortunately, there are many file formats that cannot realistically be
identified in such a way. So, in some cases, Deark also uses the filename,
especially the filename extension.

It does not use any other file attributes, such as the last-modified time or
the executable-flag; though this could change in future versions.

The filename is only used for format detection, and not for any other purpose.
This helps make its behavior safe and predictable. The options -m, -start, and
-fromstdin are among those that might need special cases added, if that were
not the case.

This behavior *might* be changed in the future (as an option?), because some
formats store important information in the filename, and having a separate
module for each possibility isn't always feasible. For example, with Unix
compress format, there is no other way to construct a good output filename, so
Deark has to settle for a generic name like "output.000.bin".

## Character encoding (console) ##

The "-d" option prints a lot of textual information to the console, some of
which is not ASCII-compatible. Non-ASCII text can sometimes cause problems.

On Windows, Deark generally does the right thing automatically. However, if you
are redirecting the output to a file or a pipe, there are cases where the
"-enc" option can be helpful. 

On Unix-like platforms, UTF-8 output will be written to the terminal,
regardless of your LANG (etc.) environment variable. You can use "-enc ascii"
to print only ASCII. (This is not ideal, but seriously, it's time to switch to
UTF-8 if at all possible.)

On Unix-like platforms, command-line parameters are assumed to be in UTF-8.

## Character encoding (output files) ##

When Deark generates a text file, its preferred encoding is UTF-8, with a BOM
(unless you use "-nobom"). But there are many cases where it can't do that,
because the original encoding is undefined, unsupported, or incompatible with
Unicode. In such cases, it just writes out the original bytes as they are.

If the text was already encoded in UTF-8, Deark does not behave perfectly
consistently. Some modules copy the bytes as they are, while other sanitize
them first.

Deark keeps the end-of-line characters as they are in the original file. If it
has to generate end-of-line characters of its own, it uses Unix-style line-feed
characters.

## Executable output files ##

Most file attributes (such as file ownership) are ignored when extracting
files, but Deark does try to maintain the "executable" status of output
files, for formats which store this attribute. The Windows version of Deark
does not use this information, except when writing to a ZIP/tar file.

This is a simple yes/no flag. It does not distinguish between
owner-executable and world-executable, for example.

## Directory "files" and empty directories ##

Some archive formats contain independent representations of subdirectores,
allowing empty directories, and directory attributes, to be stored. By default,
Deark retains these entries when writing to a ZIP/tar file, and otherwise
ignores them. This behavior can be changed with "-opt keepdirentries". Even so,
Deark never creates directories directly. Instead, it may create marker files
with a ".dir" extension.

Note that this means the -zip/-tar option can affect the numbering of output
files used by, e.g., the -get option.

## Modification times ##

In certain cases, Deark tries to maintain the modification time (and to a
lesser degree, other timestamps) of the original file. This only happens with
timestamps contained inside the input file.

If a timestamp does not include a time zone, the time will be assumed to be in
Universal Time (UTC), unless the -intz option was used. Deark is expected to be
used with files that were created long ago and far away, so it never assumes
that the Deark user's time zone is relevant.

Note that if you are extracting to a system that does not store file times in
UTC (often the case on Windows), the timestamps may not be very accurate.

## Modification times and thumbnails ##

Some thumbnail image formats store the last-modified time of the original file.
This raises the question of whether Deark should use this as the last-modified
time of the extracted thumbnail file. Currently, Deark *does* do this, but it
must be acknowledged that there's something not quite right about it, because
the thumbnail may have been created much later than the original image.

## The .iptctiff and .8bimtiff formats ##

In some cases, Deark saves IPTC-IIM metadata, or Photoshop Resources (also
semi-incorrectly known as "8BIM"), to a file. These data formats don't have a
good *file* format to use, so Deark wraps them in a minimal TIFF-based
container. You can reprocess this container file with Deark, and it may decode
the data (use -d), or extract the raw data to a file.

## AppleDouble format ##

In most cases, Deark writes Macintosh resource forks to AppleDouble format. It
considers this to be its preferred format for resource forks. You have to use
an option, if you want it to write the fork in raw form.

It gives AppleDouble output files an ".adf" file extension. Although this is
one of the conventions suggested in the AppleDouble specification, it is not
commonly used. The other naming conventions don't play well with Deark's naming
conventions.

Another problem is that, because Deark gives each output file a unique prefix
like "output.NNN", the AppleDouble file and its associated data fork will not
have the same base filename, further reducing the chance that other systems
will treat them as a unit. There's no good fix for this, though you may be able
to avoid it by using the -zip option.

## PNG htSP chunks ##

When decoding mouse cursor graphics, Deark sometimes records the cursor's
"hotspot" in the resulting PNG image, in a custom "htSP" chunk. The htSP
chunk's format is explained here.

The chunk type is "htSP": hex [68 74 53 50].

The chunk data field length is 24 or more bytes. Encoders must write exactly 24
bytes. Decoders must ignore any bytes after the first 24.

The first 16 bytes of the data field are an arbitrary signature UUID: hex [b9
fe 4f 3d 8f 32 45 6f aa 02 dc d7 9c ce 0e 24]. This represents the UUID
b9fe4f3d-8f32-456f-aa02-dcd79cce0e24. If the first 16 bytes are not exactly
this signature, the chunk does not conform to this specification.

At most one htSP chunk with this signature may appear in a PNG file. The chunk
must appear before the IDAT chunks.

After the signature are two 4-byte fields: the X coordinate at offset 16, then
the Y coordinate at offset 20. Each is stored as a "PNG four-byte signed
integer" (big-endian, two's complement).

The X coordinate is the number of pixels the hotspot is to the right of the
image's leftmost column of pixels. (If the hotspot is in the leftmost column,
then its coordinate is 0). The Y coordinate is the number of pixels the hotspot
is below the image's topmost row of pixels. It is legal for the hotspot to be
beyond the bounds of the image.

The hotspot is conceptually an entire pixel (or virtual pixel), not a specific
point in some coordinate system. If more precision is needed, assume the
hotspot is the center of that pixel. This means that if a 16x16-pixel image
with hotspot (0,0) were to be mirrored left-right, the new hotspot would be
(15,0), not (16,0) as it would be if the hotspot were the upper-left corner of
the pixel.

## I've never heard of that format! ##

For the identities of the formats supported by Deark, see

- [File format wiki: Electronic File Formats](http://fileformats.archiveteam.org/wiki/Electronic_File_Formats)
- [File format wiki: Graphics](http://fileformats.archiveteam.org/wiki/Graphics)

## Other information ##

By design, Deark does not look at any files that don't explicitly appear on the
command line. In the future, there might be an option to change this behavior,
and automatically try to find related files.

Most bitmap fonts are converted to images. The goal is that, eventually,
almost all of them will be converted to a more-portable font file format. But
that is difficult to do well.

## How to build ##

Deark is written in C. On a Unix-like system, typing "make" from a shell prompt
will (hopefully) be sufficient:

    $ make

This will build an executable file named "deark". Deark has no dependencies,
other than the standard C libraries.

One way to configure the build is by setting certain environment variables. See
the scripts at scripts/example-build-* for examples.

Another way is to create Makefile fragment files named local1.mk and/or
local2.mk.

Some C-language-level configuration can be done by creating a file named
src/deark-config2.h, and adding -DDE_USE_CONFIG2_H to the CFLAGS variable in
the Makefile.

It is safe to build Deark using "parallel make", i.e. "make -j". This will
speed up the build, in most cases.

If you want to install it in a convenient location, just copy the "deark" file.
For example:

    $ sudo cp deark /usr/local/bin/

or

    $ sudo make install

For Microsoft Windows, the project files in proj/vs2022 should work
for sufficiently new versions of Microsoft Visual Studio. Alternatively, you
can use Cygwin.

When doing a Windows (Win32 API) build, the Makefile is not intended to be used
directly (without configuration). For MinGW and similar compilers, it is
recommended to use a script (e.g. scripts/example-build-mingw.sh) or local*.mk
files.

Note that for Windows, Deark unconditionally uses Unicode API functions like
fputws() and GetFileAttributesW(), so it's not possible to do a "non-Unicode"
build.

## Developer notes ##

### Coding style and C language ###

The C language version that Deark uses is (semi-officially) C99, with a few
common extensions needed for things like querying a file's size.

It should be mostly compatible with most modern compilers, without special
options.

### Hard-coded CRCs ###

Some source code files contain hard-coded CRC-32 hashes, to help identify
certain things. The original data associated with the hashes may be found
in the separate
[Deark-extras project](https://github.com/jsummers/deark-extras).

### Other notes ###

Maximizing execution speed is not a goal of Deark. This is a deliberate
concession. The focus is on making the code easy to write, easy to read, and to
minimize the chance of bugs. (Serious performance issues will still be
addressed, though.)

The Deark executable size is a consideration. A suggested feature might be
declined if it would involve too much bloat.

Consistent behavior is a goal. Ideally, the files produced by a given version
of Deark should depend only on the contents of the input file. They should not
change if you update your computer, or change your time zone settings, or
whatever. There is an issue when using the -zip option, though. Consider using
"-opt archive:timestamp" to get reproducible results.

Deark is intended to be compiled as a 64-bit application. It uses 64-bit
integers pervasively. It can be compiled as a 32-bit app (provided the compiler
has a 64-bit integer type), and it will operate correctly. But it will be very
inefficient, and might run at less than half the 64-bit speed.

The Deark source code is structured like a library, but it's not intended to be
used as such. The error handling methods, and error messages, are not really
suitable for use in a library.

A regression test suite does exist for Deark, but is not available publicly at
this time.
