<?xml version="1.0" standalone="no"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"/usr/share/sgml/docbook/dtd/xml/4.1.2/docbookx.dtd">
<article id="index">
	<articleinfo>
		<authorgroup>
			<corpauthor>
				<ulink url="http://www.freedesktop.org">
				X Desktop Group
				</ulink>
			</corpauthor>
			<author>
				<firstname>Thomas</firstname>
				<surname>Leonard</surname>
				<affiliation>
					<address><email>tal197@users.sf.net</email></address>
				</affiliation>
			</author>
			<author>
				<firstname>David</firstname>
				<surname>Faure</surname>
				<affiliation>
					<address><email>david@mandrakesoft.com</email></address>
				</affiliation>
			</author>
		</authorgroup>

		<title>Shared MIME-info Database</title>
		<date>26 April 2002</date>
	</articleinfo>
<sect1>
	<title>Introduction</title>
	<sect2>
		<title>Version</title>
		<para>
This is version 0.6 of the Shared MIME-info Database spec, last updated 26 April 2002.
		</para>
	</sect2>
	<sect2>
		<title>What is this spec?</title>
		<para>
Many programs and desktops use the MIME system to represent the types of
files. Frequently, it is necessary to work out the correct MIME type for
a file. This is generally done by examining the file's name or
contents, and looking up the correct MIME type in a database.
		</para>
		<para>
For interoperability, it is useful for different programs to use the same
database so that different programs agree on the type of a file and new
rules for determining the type apply to all programs.
		</para>
		<para>
This specification attempts to unify the type-guessing systems currently in
use by GNOME, KDE and ROX. Only the name-to-type and contents-to-type mappings
are covered by this spec; other MIME type information, such as the default
handler for a particular type, or the icon to use to display it in a file
manager, are not covered since these are a matter of style.
		</para>
	</sect2>
	<sect2>
		<title>Language used in this specification</title>
		<para>
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED",  "MAY", and "OPTIONAL" in this document are to be
interpreted as described in RFC 2119.  
		</para>
	</sect2>
</sect1>
<sect1>
	<title>Overview of previous systems</title>
	<sect2>
		<title>KDE</title>
		<para>
KDE uses <filename>.desktop</filename> files, with Type=MimeType, one file
per type to determine type from file name. The files are arranged in the
filesystem to mirror the two-level MIME type hierarchy.
The syntax is very similar to other <filename>.desktop</filename> files,
with Name=, Comment= etc.
		</para>
		<para>
Example file:
			<programlisting><![CDATA[
[Desktop Entry]
Encoding=UTF-8
MimeType=application/x-kword
Comment=KWord
Comment[af]=kword
[... etc. other translations ]
Icon=kword
Type=MimeType
Patterns=*.kwd;*.kwt;
X-KDE-AutoEmbed=false

[Property::X-KDE-NativeExtension]
Type=QString
Value=.kwd
]]></programlisting>
		</para>
		<para>
KDE does not have a separate system for specifying extension matches, but
uses case-sensitive glob patterns for everything.
		</para>
		<para>
A single file stores all the rules for recognising files by content. This
is almost identical to <citerefentry><refentrytitle>file</refentrytitle>
<manvolnum>1</manvolnum></citerefentry>'s <filename>magic.mime</filename>
database file, but without the encoding field.
		</para>
		<para>
The format is described in the file itself as follows:
		<programlisting><![CDATA[
# The format is 4-5 columns:
#    Column #1: byte number to begin checking from, ">" indicates continuation
#    Column #2: type of data to match
#    Column #3: contents of data to match
#    Column #4: MIME type of result
]]></programlisting>
		</para>
	</sect2>
	<sect2>
		<title>GNOME</title>
		<para>
GNOME uses the gnome-vfs library to determine the MIME type of a file.
This library loads name-to-type rules from files with a '.mime' extension
in a system-wide directory (set at install time), and merged with those in the
user's directory. It loads textual descriptions for the types from
files in the same directories, ending with '.keys'. The file
<filename>gnome-vfs.mime</filename> in the system directory is always loaded
first (allowing everything else to override it). The file
<filename>user.mime</filename> in the user's directory is always loaded
last, making these settings take precedence over all others.
		</para>
		<para>
The format of the .mime files are described as follows:
			<programlisting>
# Mime types as provided by the GNOME libraries for GNOME.
#
# Applications can provide more mime types by installing other
# .mime files in the PREFIX/share/mime-info directory.
#
# The format of this file is:
#
# mime-type
#	ext[,prio]:	list of extensions for this mime-type
#	regex[,prio]:	a regular expression that matches the filename
#
# more than one ext: and regex: fields can be present.
#
# prio is the priority for the match, the default is 1. This is required
# to distinguish composed filenames, for example .gz has a priority of 1
# and .tar.gz has a priority of 2 (thus a file having the filename
# something.tar.gz will match the mime-type for tar.gz before the mime-type
# for .gz
#
# The values in this file are kept in alphabetical order for convenience.
# Please maintain this when adding new types. Also consider adding a
# human-readable description to gnome-vfs.keys when adding a new type here.
#
# Also do please not add illegal mime types, observe the mime standard when
# adding new types.
			</programlisting>
When looking up the type for a file, gnome-vfs looks first for an exact-case
match for the extension, then an all upper-case match, then an all lower-case
match. If no matches are found, or there is no '.' in the name, then the
regular expression matches are checked. It does this first for rules with
priority 2, then for those with priority 1. The modification time on the
<filename>mime-info</filename>
directories is used to detect changes.
		</para>
		<para>
The .keys files contain type-to-description rules, eg:
			<programlisting>
application/msword
	description=Microsoft Word document
	[de]description=Microsoft Word-Dokument
	...
			</programlisting>
Guidelines for writing descriptions can be found in the
<filename>mime-descriptions-guidelines.txt</filename> file.
		</para>

	</sect2>
	<sect2>
		<title>ROX</title>
		<para>
ROX searches <filename>MIME-info</filename> directories in
<envar>CHOICESPATH</envar> (<filename>~/Choices/MIME-info:/usr/local/share/Choices/MIME-info:/usr/share/Choices/MIME-info</filename> by
default). Files from earlier directories override those in later ones, but
the order within a directory is not specified.
		</para>
		<para>
The files are in the same format as GNOME, except:
			<itemizedlist>
				<listitem><para>
There are no .keys files, so files of all extensions are loaded.
				</para></listitem>
				<listitem><para>
The priority is ignored.
				</para></listitem>
				<listitem><para>
A case-sensitive match is tried first, then a lower-case match. No upper-case
match is tried.
				</para></listitem>
				<listitem><para>
Multiple extensions are allowed. Eg:
					<programlisting>
application/x-compressed-postscript
	ext: ps.gz eps.gz
					</programlisting>
				</para></listitem>
			</itemizedlist>
		</para>
		<para>
When looking up the type for a file, ROX starts with the first '.'
and tries a case-sensitive match of the remaining text against the extensions.
The it tries again with the filename in lower-case. It then tries again
from the second '.', and so on. If no type is found, it tries the regular
expressions.
		</para>
		<para>
ROX has no rules for determining a file's type from its contents.
		</para>
	</sect2>
</sect1>
<sect1>
	<title>Unified system</title>
	<para>
In discussions about these systems, it was clear that the differences between
the databases were simply a result of them being separate, and not due to any
fundamental disagreements between developers. Everyone is keen to see them
merged.
	</para>
	<para>
This spec proposes:

		<itemizedlist>
			<listitem><para>
A standard format for these files.
			</para></listitem>
			<listitem><para>
Standard locations for them.
			</para></listitem>
		</itemizedlist>

	</para>
	<sect2>
		<title>File format</title>
		<para>
The new format is very similar to the KDE format. However, only the tags used
in this example are valid:
			<programlisting><![CDATA[
[MIME-Info text/html]
Encoding=UTF-8
Comment=HTML document
Comment[af]=...
[... etc. other translations ]
Patterns=*.htm;*.html
Contents=(strcmp-at 0 "<HTML")
Hidden=false
]]></programlisting>
		</para>
		<para>
All KDE-specific tags have been removed, as well as the Icon field. Although
all desktops need a way to determine the icon for a particular type, the icon
used will depend on desktop, and not only on the file type.
		</para>
		<para>
The type should be a standard MIME type where possible. If a special media type
is required for non-file objects (directories, pipes, etc), then the media
type 'inode' may be used.
		</para>
		<para>
The entries in Patterns are separated by semicolons. There is no trailing
semicolon.
		</para>
		<para>
Although not part of the name-to-type mapping, the Comment field is left in
for the sake of not having too many files.
		</para>
		<para>
The Hidden field is usually not present. It is used to indicate that this entry
replaces all information for this MIME type read so far, instead of being
merged with other records for the same type. The intent is to let users
entirely replace existing types.
		</para>
	</sect2>
	<sect2>
		<title>Directory layout</title>
		<para>
Unlike the KDE system, the files are not arranged in the filesystem by type.
This approach is only possible for a tightly coordinated system. Consider,
for example, that ROX-Filer adds a mapping from
<filename>.DirIcon</filename> to 'image/png'. This cannot be specified in
a file called <filename>image/png.desktop</filename> without conflicting
with existing definitions for the type.
		</para>
		<para>
Since files are not named by type, each file may contain multiple types. The
files should instead be named by the package that they come from to avoid
conflicts and reduce loading times.
		</para>
		<para>
The directories to be used to load these files are:

			<itemizedlist>
				<listitem><para>
<filename>/usr/share/mime/mime-info</filename>
				</para></listitem>
				<listitem><para>
<filename>/usr/local/share/mime/mime-info</filename>
				</para></listitem>
				<listitem><para>
<filename>~/.mime/mime-info</filename>
				</para></listitem>
			</itemizedlist>
Each of these directories contains a number of files with the '.mimeinfo'
extension. Applications MUST NOT try to load other files. This is to allow for
future extensions.
		</para>
		<para>
Programs modifying any of these files MUST update the modification time on
the parent (<filename>mime-info</filename>) directory so that applications can
easily detect the change. The rules from the directories in this list take
precedence over conflicting rules from earlier directories. Thus, the user's
settings take precedence over all others.
		</para>
	</sect2>
	<sect2>
		<title>Pattern matching</title>
		<para>
KDE's Patterns field replaces GNOME's and ROX's ext/regex fields, since it
is trivial to detect a pattern in the form '*.ext' and store it in an
extension hash table internally. The full power of regular expressions was
not being used by either desktop, and glob patterns are more suitable for
filename matching anyway.
		</para>
		<para>
Applications MUST first try a case-sensitive match, then a case-insensitive
one. This is so that <filename>main.C</filename> will be seen as a C++ file,
but <filename>IMAGE.GIF</filename> will still use the *.gif pattern.
		</para>
	</sect2>
	<sect2>
		<title>Dealing with conflicts</title>
		<para>
If several patterns match then the longest pattern SHOULD be used. In
particular, files with multiple extensions (such as
<filename>Data.tar.gz</filename>) MUST match the longest sequence of extensions
(eg '*.tar.gz' in preference to '*.gz'). Literal patterns (eg, 'Makefile') must
be matched before all others. It is acceptable to match patterns of the form
'*.text' before other wildcarded patterns (that is, to special-case extensions
using a hash table).
		</para>
		<para>
If the same pattern is defined twice, then they MUST be ordered by the
directory the rule came from (this is to allow users to override the system
defaults if, for example, they are using a common extension to mean something
else). If they came from the same directory, either can be used.
		</para>
		<para>
If the same type is defined in several places, the Patterns and Comments
MUST be merged. If two different comments are provided for the same
MIME type in the same language, they should be ordered by directory as before.
		</para>
		<para>
Common types (such as MS Word Documents) will be provided in the X Desktop
Group's package, which SHOULD be required by all applications using this
specification. Since each application will then only be providing information
about its own types, conflicts should be rare.
		</para>
	</sect2>
	<sect2>
		<title>Contents matching</title>
		<para>
The value of the Contents attribute is a scheme-like expression. If the
expression evaluates to a true value then the file is assumed to be of this
type. Since scanning a file's contents can be very slow, applications may
choose to do pattern matching first and only fall back to content matching, or
not perform it at all.
		</para>
		<para>
An expression is a list of space-separated items surrounded by parenthesis, eg:
			<programlisting><![CDATA[
(strcmp-at 0 "<?xml ")
]]></programlisting>
The first element of the list (<userinput>strcmp-at</userinput> in this
example) is the name of a function. The remaining elements are its arguments.
The result of evaluating the expression is the result of applying the function
to the arguments. Each argument may be:
			<variablelist>
				<varlistentry><term>An integer</term>
					<listitem><para>
A 64-bit signed integer, such as <userinput>32</userinput>.
					</para></listitem>
				</varlistentry>
				<varlistentry><term>A string</term>
					<listitem><para>
A string of characters with C-style escaping. This string contains the
sequence of bytes &lt;0, 8, 9, 10&gt;: <userinput>"\0\010\t\xa"</userinput>.
					</para></listitem>
				</varlistentry>
				<varlistentry><term>A symbol</term>
					<listitem><para>
A symbol is a constant for the file being tested. For example,
<userinput>size</userinput> evaluates to the file's size.
					</para></listitem>
				</varlistentry>
				<varlistentry><term>A list</term>
					<listitem><para>
Lists may be nested. Each sub-list is evaluated in the same way as the top-level
list, eg <userinput>(+ (* 3 2) (* 4 3))</userinput> is 18.
					</para></listitem>
				</varlistentry>
			</variablelist>
Functions may return integers or strings. 'True' is represented by the integer
1, and False by 0. The following functions and symbols are provided:
			<informaltable>
				<tgroup cols="3">
					<thead>
						<row>
<entry>Function example</entry><entry>Result</entry><entry>Description</entry>
						</row>
					</thead>
					<tbody>
						<row>
<entry>(+ 1 2 3)</entry><entry>6</entry>
<entry>The sum of the arguments</entry>
						</row>
						<row>
<entry>(- 10 6 6)</entry><entry>-2</entry>
<entry>The first argument minus the sum of the remaining arguments</entry>
						</row>
						<row>
<entry>(* 2 2 3)</entry><entry>12</entry>
<entry>The product of the arguments</entry>
						</row>
						<row>
<entry>(/ 20 2 2)</entry><entry>5</entry>
<entry>The first argument divided by the
product of the remaining arguments</entry>
						</row>
						<row>
<entry>(&gt; 1 2)</entry><entry>0</entry>
<entry>True iff the first argument is greater than the second</entry>
						</row>
						<row>
<entry>(&lt; 1 2)</entry><entry>1</entry>
<entry>True iff the first argument is less than the second</entry>
						</row>
						<row>
<entry>(= 1 2)</entry><entry>0</entry>
<entry>True iff the first argument is equal to the second</entry>
						</row>
						<row>
<entry>(not size)</entry><entry>1</entry>
<entry>True iff argument is false (0 or "")</entry>
						</row>
						<row>
<entry>(and "one" 2 3)</entry><entry>3</entry>
<entry>The first false argument, or the last argument if none are false</entry>
						</row>
						<row>
<entry>(or 0 "" 2 0)</entry><entry>2</entry>
<entry>The first true argument, or the last argument if none are true</entry>
						</row>
						<row>
<entry>(&amp; 3 6)</entry><entry>2</entry>
<entry>Bit-wise AND of the arguments</entry>
						</row>
						<row>
<entry>(| 3 6)</entry><entry>7</entry>
<entry>Bit-wise OR of the arguments</entry>
						</row>
						<row>
<entry>(^ 3 6)</entry><entry>5</entry>
<entry>Bit-wise XOR of the arguments</entry>
						</row>
						<row>
<entry>size</entry><entry>10</entry>
<entry>The size of the file in bytes</entry>
						</row>
						<row>
<entry>(strcmp-at 0 "Hello")</entry>
<entry>1</entry><entry>True iff the string starting at the file offset given by the
first argument matches the second argument</entry>
						</row>
						<row>
<entry>(byte-at 0)</entry>
<entry>72</entry><entry>The signed byte at the given file offset</entry>
						</row>
						<row>
<entry>(big-16 4)</entry>
<entry>28503</entry><entry>The big-endian 16-bit signed integer starting
at the given file offset.</entry>
						</row>
						<row>
<entry>(little-16 4)</entry>
<entry>22383</entry><entry>The little-endian 16-bit signed integer starting
at the given file offset.</entry>
						</row>
						<row>
<entry>(big-32 0)</entry>
<entry>1214606444</entry>
<entry>As above, but for a 32-bit big-endian integer</entry>
						</row>
						<row>
<entry>(little-32 0)</entry>
<entry>1819043144</entry>
<entry>As above, but for a 32-bit little-endian integer</entry>
						</row>
						<row>
<entry>(big-64 0)</entry>
<entry>5216694956358856562</entry>
<entry>As above, but for a 64-bit big-endian integer</entry>
						</row>
						<row>
<entry>(little-64 0)</entry>
<entry>8245905578810697032</entry>
<entry>As above, but for a 64-bit little-endian integer</entry>
						</row>
						<row>
<entry>(string-at 4 6)</entry>
<entry>"oWorld"</entry><entry>The string of bytes starting at the offset
given by the first argument and of length given by the second argument
</entry>
						</row>
					</tbody>
				</tgroup>
			</informaltable>
The <userinput>and</userinput> and <userinput>or</userinput> functions should only evaluate
as many arguments as are necessary to determine the result.
		</para>
	</sect2>
	<sect2>
		<title>Security implications</title>
		<para>
The system described in this document is intended to allow different programs
to see the same file as having the same type. This is to help interoperability.
The type determined in this way is only a guess, and an application MUST NOT
trust a file based simply on its MIME type. For example, a downloader should
not pass a file directly to a launcher application without confirmation simply
because the type looks `harmless' (eg, text/plain).
		</para>
		<para>
Do not rely on two applications getting the same type for the same file, even
if they both use this system. The spec allows some leeway in implementation,
and in any case the programs may be following different versions of the spec.
		</para>
	</sect2>
</sect1>
</article>

