Starting with the 1.0 series, the Ganymede server gains the ability to import and export data using XML. Like HTML, XML is a plain text data format with structural tagging. Unlike HTML, which has a predefined set of tags that represent the structuring and rendering facilities of modern web browsers, XML has no pre-defined document tags. Instead, XML allows applications to define their own sets of tags for use according to the XML syntactical rules. Ganymede uses XML for the definition, import and export of its schema and data in a way that is accessible to other software and even readable by humans. Before we get into discussing the custom tags used by Ganymede, it is worth setting forth a number of facts about XML in general that software needs to know about in order to properly communicate with Ganymede via XML.
A Brief Introduction to XML |
Facts about XML:
Tags are case-sensitive. <tag>, <Tag> and <TAG> are all separate tags, and will not be treated as equivalent by an XML parser.
All tags must come in pairs. HTML browsers can tolerate tags that stand alone, like <br> and <p>, but XML is more strict, and all elements must have an open tag (<element>) and a close tag (</element>).
The structure of XML files must be strictly tree-like. That is, XML structural elements can contain other XML structural elements, but one XML structural element may not be partially contained by another.
In other words,
<element1> <element2> </element1> </element2>
is an invalid XML sequence, as the element2 and element1 structural elements are intermingled.
In contrast,
<element1> <element2></element2> </element1>
is perfectly valid, because the entirety of element2 is contained within element1.
In cases like the above, where the element2 element's open and close tag are immediately adjacent, XML supports a special syntax for an Empty Element, that is, an element which does not contain anything between the open tag and close tag. The same legal XML structure shown above could be written as:
<element1> <element2/> </element1>
where the trailing slash in the element2 element indicates that there will be no matching close tag to come along. At any other time an element open tag (<element>) is seen, a compliant XML parser will expect and demand to see the matching close tag (</element>) for that element before it sees the close tag for any elements higher up in the document structure.
In XML, all XML documents contain a single element (the Document Element, in XML lingo) which contains in turn any other elements and character data. The start tag for the document element will generally be the first thing in an XML file's content proper, and the matching close tag for the document element will be the last thing in the XML file. For this reason, the following XML fragment could not be an entire XML file:
<element1> <element2/> </element1> <element3> <element4> <element5/> </element4> </element3>
Because element1 does not contain elements 3, 4, and 5.
In XML, all attribute data must be quoted, as in
<object label="labeldata">
The following is illegal:
<object label=labeldata>
All possible characters are legal within the double quotes surrounding an attribute's value except the '&' character and the double quotation mark itself. If you need to include a double quotation mark in an attribute's data field, you have to use "
For example, if you wanted the string 'He said "hi" & I waved back.' in an XML tag attribute, you would have to do it this way:
<sentence text="He said "hi" & I waved back."/>
Newlines and other whitespace are explicitly acceptable within the quoted value of an attribute.
Likewise, if you want to include the '<', '>', or '&' characters anywhere in the body of an XML document, for anything other than tag or special character definitions, you need to use '<', '>', and '&' instead, just as with HTML.
XML files use Unicode, with the UTF-8 encoding, typically. American 7-bit ASCII is a proper subset of Unicode and require no special handling in UTF-8 encoding. International characters may be used in XML files, but you must do so in a manner compliant with UTF-8. Ganymede will always emit XML files using the standard UNIX end-of-line character, but as with any XML parser, Ganymede can also handle DOS/Windows style line termination when reading XML files.
Ganymede allows any string that is valid for XML 1.1 / XML 1.0 (version 5) element names for object type and field names, but spaces in object type / field names are represented in XML as underscore ('_') characters. Because the Ganymede XML layer uses underscore as a stand-in for space characters in Ganymede object type and field names, you are not allowed to use underscores in Ganymede object type and field names.
This means that a field named 'Home Directory' will be represented in XML as an element named <Home_Directory>.
Unlike in HTML, the XML standard does not specify that whitespace can be ignored or contracted. For Ganymede's purposes, however, whitespace between tags is generally ignored, and newlines and indentation are nice for human readability but not necessary for Ganymede's input parsing. More on this as we discuss what Ganymede does with XML, below.
That's about all you should need to know about XML, at least as far as we'll need to talk about in discussing Ganymede. If you want to read about things like external reference entities, Document Type Definitions/DTD's, or the precise Backus-Naur style specification for what characters are allowed to go where when, you can probably find your way to the original XML standards documents over at www.XML.com.
On Ganymede and XML |
Ganymede exports and imports object and schema data using a simple XML format, in which the schema definition section and the object data sections comprise two separate elements. The basic structure of an XML file for Ganymede looks like this:
<ganymede major="1" minor="0" persona="supergash" password="testpass"> <ganyschema> -- Optional Ganymede Schema Definition Section Here -- </ganyschema> <ganydata> -- Optional Ganymede Object Data Section Here -- </ganydata> </ganymede>
The ganymede element is the XML file's Document Element, and has two mandatory attributes, major and minor, which specify the major and minor version numbers of the Ganymede XML file format the file adheres to, and two optional attributes, persona and password, which may be used to specify the username and password for the xmlclient to use in attempting to log into the server to apply the changes in the file.
The ganyschema element contains the schema definition for the Ganymede database. This section contains definitions of the types of objects that the Ganymede server knows about, including the fields defined for those objects and the constraints and relationships among those fields and objects. The field definitions in the Ganymede schema definition section control what fields may legally appear in the object data section of a Ganymede XML file, and what kind of data those fields are allowed to contain.
The optional ganydata element contains actual data records from the Ganymede database. The ganydata element contains a number of object elements, each of which contain the data for a single object in the Ganymede database.
Each of these two sections are optional, but an XML file without one of these two sections is pointless, as far as Ganymede is concerned. The sections below discuss these two components of a Ganymede XML file in detail.
Ganymede Schema Definition in XML |
The <ganyschema> element defines the structure of the Ganymede database, what types of objects are defined, what fields they have, what kind of data those fields can contained, and what everything is called.
The <ganyschema> element is optional. If you
run 'xmlclient -dumpschema
' or 'xmlclient -dump
', you will get
an XML file that includes the <ganyschema> element.
If you run xmlclient on an XML file that includes a <ganyschema>
element, xmlclient will attempt to edit the server's schema to
bring it into alignment with that described in the <ganyschema>
element.
The <ganyschema> element contains two other elements, <namespaces> and <object_type_definitions>.
<ganyschema> <namespaces> -- Optional Namespace Definitions -- </namespaces> <object_type_definitions> -- Object And Field Definitions -- </object_type_definitions> </ganyschema>
<namespaces> |
The <namespaces> element contains definition elements for all unique namespace structures in the server. A namespace is essentially a unique value index that the server uses to assure that, across all fields in the database connected to the namespace, no value is repeated. Namespaces are used to keep user, group, and system names unique, among other things.
Here is an example <namespaces> element that would be contained at the start of a <ganyschema> element:
<namespaces> <namespace name="username"/> <namespace name="groupname"/> <namespace name="IPspace"/> <namespace name="UserCategory" case-sensitive="true"/> <namespace name="systemtype" case-sensitive="true"/> </namespaces>
In this example, the username, groupname, and IPspace namespaces consider two strings to be equivalent for namespace conflict considerations even if two instances of the string have different capitalization. The UserCategory and systemtype name spaces will not consider two strings to be in conflict if they have different capitalizations.
Namespaces are only significant when they are attached to fields in the <object_type_definitions> section, as we will see shortly.
<object_type_definitions> |
In the Ganymede server, all data stored is stored in the form of fields, which are aggregated in objects. Each object stored in the Ganymede server is of a certain type, such as a user, group, system, network, or whatever else has been defined in the server's schema. The objects, in turn, may be grouped into categories. Categories are a way of grouping similar kinds of objects together so that they may be viewed or ignored in the client's tree view.
The <object_type_definitions> element under the <ganyschema> element contains the actual schema definition information in terms of categories, objects, and fields. The corresponding elements for these are the <category>, <objectdef>, and <fielddef> elements.
Here is an example:
<object_type_definitions> <category name="Categories"> <category name="Admin-Level Objects"> <category name="Events"> <objectdef name="System_Events" id="4"> <label fieldid="100"/> <classdef name="arlut.csd.ganymede.eventCustom"/> <tab name="General"/> <fielddef name="Event_Token" id="100"> <comment>Single-word token for this event class</comment> <typedef type="string"> <maxlength val="32"/> <badchars val=" |"/> <namespace val="eventtoken"/> </typedef> </fielddef> <fielddef name="Event_Mail" id="103"> <comment>If true, events of this type should be mailed</comment> <typedef type="boolean"/> </fielddef> <fielddef name="Mail_List" id="107"> <typedef type="string"> <vector/> </typedef> </fielddef> </tab> </objectdef> </category> </category> </category> </object_type_definitions>
This example is of a small portion of a Ganymede server's schema definition. This fragment shows an object type called 'System Events' which holds a single tab, 'General, containing three fields; a scalar string field called 'Event Token' which is connected to the 'eventtoken' namespace, a boolean checkbox field called 'Event Mail', and a vector string field called 'Mail List'.
The 'System Events' object is contained within an 'Events' category, which is contained in turn within a 'Admin-Level Objects' category. The 'Categories' category is itself simply a container for the other categories.. it is the category root node. All <object_type_definitions> elements in Ganymede XML schema definition sections should contain a top-level 'Categories' category, even if you don't want any categorical organization of object types in the client. Note that all <category> elements that are opened are properly closed before the close of the <object_type_definitions> element.
Whenever the Ganymede server refers to object or field names, any spaces in the object or field name is replaced by an underscore in the XML file. This is so that when actual instances of objects are recorded in the <ganydata> element, encoded field names can be used directly as element names. Category names are never referred to from elsewhere in the XML file, so the category names do not have spaces converted to underscores.
<objectdef> |
The objectdef element is used to define object types in the Ganymede server. Each object type has a name and a numeric id, which are defined in an open objectdef tag via the 'name' and 'id' attributes. Both of these values must be unique within the <ganyschema> section. The value of the 'id' attribute must be an integer number, and the value of the 'name' attribute must be a string which contains only the letters a-z, in upper or lower case, numbers, a period, a dash, or a space.
Example:
<objectdef name="User" id="3">
The objectdef element must contain the mandatory <label> element to control what namespace-controlled field will act as the object's label. There can also be an optional <classdef> element to define the Java plugin class used to control operations on the object, along with an optional <embedded> element to designate objects that are to be contained in other objects. After these two or three top-level elements, there will be a series of tab elements, which in turn will contain fielddef elements to define the tabs and fields in this object type.
The mandatory label element has a fieldid attribute which gives the numeric field id of the field within the object which is to serve as the label field. Objects must have one and only one designated label field and it must refer to a namespace-controlled String, IP, or Numeric field defined within the <objectdef> element. Float, Password, Permission Matrix, Object Reference, Field Option, and Boolean fields may not be specified as label fields. The label element must be empty.
Example:
<label fieldid="100"/>
The classdef element, if present, specifies the fully
qualified class name of a Java class to be loaded by the server to
manage server operations on objects of this type. As of version
2.0 of Ganymede, the classdef element has two
attributes. The name attribute whose value is the fully
qualified name of the Java class to be used. The
optionString attribute is provided to support the use of
Jython for writing DBEditObject subclass plugins. If present, the
optionString attribute should contain a URL where the
Jython program text for the plugin can be found. Note that the
optionString will be ignored unless the Java class named in
the classdef attribute knows to use it. In the case of the
Jython support, you'd need to set classdef to
arlut.csd.ganymede.server.JythonEditObjectFactory
.
See the DBEditObject subclassing guide for details on the use of custom classes in the Ganymede server. The classdef element must be empty. That is, it must not contain any other elements.
Example:
<classdef name="arlut.csd.ganymede.gasharl.userCustom"/>
Second Example:
<classdef name="arlut.csd.ganymede.server.JythonEditObjectFactory" optionString="file:///server/ganymede/jython/classplugin.py"/>
The optional embedded element, if present, indicates that the object is not a top-level object which will be shown in the client's object tree and which will have its ownership and permissions tracked independently, but rather is an embedded object which will be encapsulated in another object of a defined type. The embedded element must be empty and it takes no attributes.
Example:
<embedded/>
Once these top-level elements are out of the way, we get down to the meat of an object definition element.. the fields, and the tabs they are contained in. The objectdef element contains a series of one or more tab elements. These tab elements, in turn, contain fielddef elements, one for each field defined in this object type. These fielddef elements are listed in the order they should appear in the client. The first fielddef element in an tab element will appear at the top of the object editing window in the Ganymede client, with subsequent fielddef's in the same tab in order below the first.
<tab> |
The tab element is a container for fielddef elements. It has a single attribute, name, which contains the name of the tab.
If you define multiple named tab elements within an object definition, the Ganymede client will display the fields in each tab element in a separate graphical tab in the object viewing and editing window. This can be useful when you start getting too large a number of fields for a user to be able to conveniently deal with in a single scrolling panel.
In all other contents (logging, email, the contents of the XML <ganydata> element, and so forth), the tab information is irrelevant, and will not be used. In particular, this means that field names have to be unique across an entire object definition, and not merely unique within a tab.
<fielddef> |
The <fielddef> element is a complex one, with many possible component elements. There are currently 10 different kinds of fields supported by the Ganymede server, and each of these field types have different options available. The open tag for the fielddef element itself is fairly simple, however. It has just two attributes, both mandatory. These are the same as the ones used in the objectdef tag.. name and id. The contents of the name attribute is limited in precisely the same manner as the name attribute of the objectdef tag's name attribute. It must contain only letters in the standard ASCII set, a-z, the numbers 0-9, a period or dash, and an underscore in place of a space. The id attribute contains the field's number. Numbers between 0 and 99 are reserved for fields that are present in all Ganymede objects, and can only be allocated in the Ganymede server code. Numbers between 100 and 255 are reserved for fields that Ganymede relies on in the pre-defined object types. Numbers between 256 and 32767 are available for user-defined custom field.
Example of the fielddef element's open tag:
<fielddef name="Username" id="100">
The fielddef element can contain a couple of optional elements, comment, and invisible.
The comment element is a text containing element. All text between the opening <comment> tag and the closing </comment> tags is treated as a comment to attach to the field. The Ganymede GUI client will show this text as a pop-up tooltip if the user lets the mouse linger on the GUI component. Aside from some text, however, the comment element should not contain any subelements.
The invisible element is an optional empty element, signifying that the field defined by the containing fielddef element should not be visible in the Ganymede client. This is used to establish invisible scratch fields used by custom code associated with the containing objectdef element for various purposes. This is a rather unusual element to define in a fielddef element, and will only be present in special cases.
Here's a (contrived) example of these two optional elements in use.
<fielddef name="Hidden_Field" id="302"> <comment>This is a hidden field to be used for namespace manipulations.</comment> <invisible/> </fielddef>
Okay, with the two optional elements out of the way, it's time for the meat of the fielddef element, the typedef element. The typedef element specifies what kind of data field the containing fielddef field definition element defines, and has a single attribute, type. The type attribute can have any of the values listed in the following table:
Type | Explanation | Vector Allowed? |
---|---|---|
string | Unicode String | YES |
ip | I.P. Address (either IPv4 or IPv6) | YES |
invid | Object Reference | YES |
boolean | Boolean | NO |
date | Date/Timestamp | NO |
numeric | Integer Number Field | NO |
float | Double precision float | NO |
password | Password Field | NO |
permmatrix | Ganymede Permissions Matrix | NO |
options | Field Options Matrix | NO |
For example:
<typedef type="string">
After the typedef element open tag, there can be a variety of elements, depending on the element's type.
First off, the string, ip, and invid field types can be vector fields, in which a single data field can contain more than one value. In that case, the typedef element will contain a vector element.
The vector element is an empty element with a single attribute, maxSize, which has a numeric value specifying the maximum number of values that can be held in this field at a time. For example,
<typedef type="string"> <vector maxSize="100"/> </typedef>
would describe a vector string field that could contain up to 100 strings in the field. Vector fields in Ganymede can not hold more than 32767 elements, so if no maxSize attribute is defined, an implicit value of 32767 is still in effect.
After the optional vector element (for the string, ip, and invid types only), there are a number of optional field constraint elements which may be present within the <typedef> element. These differ according to the type of the field, and are summarized in the table below. The trickiest options conceptually are those associated with the invid field type. I need to link this material to a general discussion of invid fields.
field type | element name | element details | example | |
---|---|---|---|---|
string | ||||
minlength | The minlegth element is an empty element with a single attribute, val, which contains a numeric value specifying a mandatory minimum number of characters present in this string field. |
<minlength val="2"/> | ||
maxlength |
The maxlength element is an empty element with a single attribute, val, which contains a numeric value specifying the maximum number of characters allowed in this string field. The Ganymede server supports string values of up to 32767 characters in length, and this limit is present implicitly if the maxlength element is not present in a string field definition. |
<maxlength val="8"/> | ||
okchars | The okchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters allowed in this string field. If this optional element is defined in a string typedef element, no characters will be allowed in any field of this type unless that character is present in the val value. |
<okchars val="0123456789-"/> | ||
badchars | The badchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters not allowed in this string field. If this optional element is defined in a string typedef element, a character will not be allowed in any field of this type if that character is present in the val value. |
<badchars val=":"/> | ||
regexp |
The regexp element is an optional empty element with a pair of attributes, one mandatory and one optional. The mandatory attribute is val, which contains a string value which defines a Perl-style regular expression. The optional attribute is desc, which if present will be used as a textual description of the meaning of the regexp. The desc attribute will be provided to the user in an error dialog if they enter a string in the client which does not match the regexp. If no desc attribute is present, the user will be shown the regexp itself in the error message. regexp is an optional element in the string typedef element. If a regexp element is present, all strings entered into fields of this type will be checked against the regexp. The regexp check is made in addition to any okchars and badchars constraints that are defined in the same typedef. |
<regexp val="^[a-z]+[a-z|\d]*$" desc="Usernames may contain letters and numbers, but must begin with a letter."/> | ||
multiline | The multiline element is an empty element with no attributes. This element signifies that this field should be presented in the Ganymede client as a multiline string area rather than a single line text field. |
<multiline/> | ||
namespace | The namespace element is an empty element with a single attribute, val, which contains a string naming a namespace defined in the namespaces element contained in the top-level ganyschema element. If this optional element is defined in a string typedef element, all fields associated with the specified namespace will be constrained to contain unique values across the specified namespace. |
<namespace val="username"/> | ||
ip | ||||
namespace | The namespace element is an empty element with a single attribute, val, which contains a string naming a namespace defined in the namespaces element contained in the top-level ganyschema element. If this optional element is defined in an ip typedef element, all fields associated with the specified namespace will be constrained to contain unique values across the specified namespace. |
<namespace val="IPSpace"/> | ||
invid | ||||
targetobject |
The targetobject element is an empty element with a pair of attributes, name and id, which constrains the type of object this object reference field may point to in the server. The name attribute contains a string which has the encoded (underscores for spaces) name of the object type to point to, while the id attribute contains the integer numberic id of the object type pointed to. Both may be specified, in which case the Ganymede server will verify that both the id number and the object name are consistent, or either one alone may be used. If this invid field is intended to be able to point to any kind of object, this is specified by using the name attribute alone, with a value of "*any*". In this case, no id attribute should be specified. |
<targetobject name="User" id="3"/> | ||
targetfield |
The targetfield element is an optional empty element that specifies the field that this invid field is to be linked with. If a targetfield is specified, the Ganymede server will maintain a symmetric link between this invid field and the target field in objects linked to this field. The target field may be identified using either a name or an id attribute. The name attribute contains a string which has the encoded (underscores for spaces) name of the field to point to, while the id attribute contains the integer numberic id of the field pointed to. Both may be specified, in which case the Ganymede server will verify that both the id number and the field name are consistent, or either one alone may be used. |
<targetfield name="Username" id="103"/> | ||
embedded |
The embedded element is an optional empty element that specifies that this invid field is to be used as an edit-in-place field. That is, that objects linked by this field will be handled as if contained within the object which holds this field. |
<embedded/> | ||
boolean | ||||
labeled | The labeled element is an optional empty element with a pair of attributes, true and false. If this element is present, the client will present this boolean field as a pair of radio buttons rather than a single check-box. This can be useful when you've got a pair of choices that don't fit naturally into a yes/no dichotomy. In general, support for this option has not really been tested, and may not work well. |
<labeled true="Normal User" false="Custom Account"/> | ||
numeric | ||||
namespace | The namespace element is an optional, empty element with a single attribute, val, which contains a string naming a namespace defined in the namespaces element contained in the top-level ganyschema element. If this optional element is defined in a numeric typedef element, all fields associated with the specified namespace will be constrained to contain unique values across the specified namespace. |
<namespace val="uid"/> | ||
password | ||||
minlength | The minlegth element is an empty element with a single attribute, val, which contains a numeric value specifying a mandatory minimum number of characters present in this password field. This element only takes effect when users provide plaintext to the Ganymede server. If the xmlclient or custom client code is used to provide some form of pre-hashed password, this constraint can not be applied. |
<minlength val="2"/> | ||
maxlength |
The maxlength element is an empty element with a single attribute, val, which contains a numeric value specifying the maximum number of characters allowed in this password field. The Ganymede server supports string values of up to 32767 characters in length, and this limit is present implicitly if the maxlength element is not present in a password field definition. This element only takes effect when users provide plaintext to the Ganymede server. If the xmlclient or custom client code is used to provide some form of pre-hashed password, this constraint can not be applied. The crypt encryption hash method supported by Ganymede only considers the first 8 characters of the password in generating the authentication hash, so setting a maxlength larger than 8 characters will not guarantee that Ganymede will require the full password length for login authentication if the crypt method is used. |
<maxlength val="8"/> | ||
okchars | The okchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters allowed in this password field. If this optional element is defined in a password typedef element, no characters will be allowed in any field of this type unless that character is present in the val value. This element only takes effect when users provide plaintext to the Ganymede server. If the xmlclient or custom client code is used to provide some form of pre-hashed password, this constraint can not be applied. |
<okchars val="0123456789-"/> | ||
badchars | The badchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters not allowed in this password field. If this optional element is defined in a password typedef element, a character will not be allowed in any field of this type if that character is present in the val value. This element only takes effect when users provide plaintext to the Ganymede server. If the xmlclient or custom client code is used to provide some form of pre-hashed password, this constraint can not be applied. |
<badchars val=":"/> | ||
cracklib_check |
The cracklib_check element is an optional, empty element. If this element is present, the Ganymede server will use cracklib to perform quality checks on passwords entered in this field. If the attribute 'exception' has the value 'supergash', supergash-level accounts will be given a cracklib warning but will be allowed to ignore the warning. |
<cracklib_check exception="supergash"/> | ||
history_check |
The history_check element is an optional, empty element. If this element is present, the Ganymede server will keep a store of 'depth' hashes for previous passwords that the object has held. If the attribute 'exception' has the value 'supergash', supergash-level accounts will be given a history warning but will be allowed to ignore the warning. |
<history_check exception="supergash" depth="3"/> | ||
crypted |
The crypted element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in UNIX crypt() format. |
<crypted/> | ||
md5crypted |
The md5crypted element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in FreeBSD-style md5crypt() format. |
<md5crypted/> | ||
apacheMd5crypted |
The apacheMd5crypted element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in Apache-style md5crypt() format. |
<apacheMd5crypted/> | ||
winHashed |
The winHashed element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in the two Windows NT compatible hash formats used in the Samba encrypted password file. |
<winHashed/> | ||
sshaHashed |
The sshaHashed element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in the Salted SHA-1 format used by OpenLDAP. This is Netscape's salted variant of the FIPS SHA-1 standard. SHA-1 is described at http://en.wikipedia.org/wiki/SHA-1, while SSHA is described at http://www.openldap.org/faq/data/cache/347.html. |
<sshaHashed/> | ||
shaUnixCrypted |
The shaUnixCrypted element is an optional, empty element with two optional attributes: type and rounds. If this element is present, the Ganymede server will store the contents of this password in the scalable SHA256/SHA512 Unix Crypt algorithm recently implemented by the GNU C Library on Linux (and which is under consideration for adoption by Sun, IBM, and HP). See http://people.redhat.com/drepper/sha-crypt.html for complete details on this algorithm. Note that this algorithm is only starting to be supported. It works properly on Linux distributions running glibc versions 2.7 and later, such as Fedora 8. Attributes:
|
<shaUnixCrypted type="512" rounds="7500"/> | ||
bCrypted |
The bCrypted element is an optional, empty element with an optional attribute: rounds. If this element is present, the Ganymede server will store the contents of this password using the scalable OpenBSD BCrypt algorithm. Attributes:
|
<bCrypted rounds="15"/> | ||
plaintext |
The plaintext element is an optional, empty element. If this element is present, the Ganymede server will store the plaintext of passwords stored in this field to disk. Normally, if the Ganymede server has any of crypted, md5crypted, apacheMd5crypted, winHashed, sshaHashed, shaUnixCrypted, or bCrypted set, the server will never dump the plaintext of passwords in this field to disk, as it is capable of authenticating logins against any of the supported hash formats. If the plaintext element is present, the password will be preserved in plaintext form in the ganymede.db file, regardless of whether or not the password is also handled via one of the encryption hashes. |
<plaintext/> | ||
options | n/a | The field options field type supports no configurable elements within <typedef> | ||
permmatrix | n/a | The permissions matrix field type supports no configurable elements within <typedef> |
Schema Example Fragment |
The following is a transcript of the User object definition from the GASHARL schema kit in use at ARL. Notable features of this fragment include the Groups invid field which is bidirectionally linked with the Users field in the Groups object type, and the edit-in-place Directory Volume field which contains embedded Embedded Automounter Map Entry objects.
Note also the newline in the middle of the Groups field comment, which is actually preserved faithfully in the Ganymede database.
<objectdef name="User" id="3"> <label fieldid="100"/> <classdef name="arlut.csd.ganymede.gasharl.userCustom"/> <tab name="General"/> <fielddef name="Username" id="100"> <comment>User name for an individual privileged to log into Ganymede and/or the network</comment> <typedef type="string"> <maxlength val="8"/> <badchars val=" :"/> <namespace val="username"/> <regexp val="^[a-z]+[a-z|\d]*$" desc="User names may consist of letters and numbers, but must begin with a letter"/> </typedef> </fielddef> <fielddef name="UID" id="256"> <typedef type="numeric"> <namespace val="uid"/> </typedef> </fielddef> <fielddef name="Password" id="101"> <comment>Password for an individual privileged to log into Ganymede and/or the network</comment> <typedef type="password"> <minlength val="3"/> <maxlength val="32"/> <shaUnixCrypted type="512" rounds="5000"/> <plaintext/> </typedef> </fielddef> <fielddef name="Account_Category" id="273"> <typedef type="invid"> <targetobject name="User_Category"/> </typedef> </fielddef> <fielddef name="Full_Name" id="257"> <typedef type="string"> <maxlength val="64"/> <badchars val=":,"/> </typedef> </fielddef> <fielddef name="Social_Security" id="274"> <typedef type="string"> <okchars val="0123456789-"/> </typedef> </fielddef> <fielddef name="Division" id="258"> <typedef type="string"> <maxlength val="32"/> <badchars val=":,"/> </typedef> </fielddef> <fielddef name="Room" id="259"> <typedef type="string"> <maxlength val="32"/> <badchars val=": ,"/> </typedef> </fielddef> <fielddef name="Office_Phone" id="260"> <typedef type="string"> <maxlength val="16"/> <badchars val=":"/> </typedef> </fielddef> <fielddef name="Home_Phone" id="261"> <typedef type="string"> <maxlength val="16"/> <badchars val=":, "/> </typedef> </fielddef> <fielddef name="Groups" id="264"> <comment>List of non-primary groups the user is a member of. Limited to 16 for NFS.</comment> <typedef type="invid"> <vector maxSize="16"/> <targetobject name="Group"/> <targetfield name="Users"/> </typedef> </fielddef> <fielddef name="Home_Group" id="265"> <typedef type="invid"> <targetobject name="Group"/> <targetfield name="Home_Users"/> </typedef> </fielddef> <fielddef name="Login_Shell" id="263"> <typedef type="string"> <maxlength val="128"/> <badchars val=" :"/> </typedef> </fielddef> <fielddef name="Home_Directory" id="262"> <comment>UNIX default directory, normally assigned by Ganymede</comment> <typedef type="string"> <maxlength val="128"/> <badchars val=" :"/> </typedef> </fielddef> <fielddef name="Admin_Personae" id="102"> <comment>A list of admin personae this user can assume</comment> <typedef type="invid"> <vector/> <targetobject name="Admin_Persona"/> <targetfield name="User"/> </typedef> </fielddef> <fielddef name="Netgroups" id="266"> <typedef type="invid"> <vector/> <targetobject name="User_Netgroup"/> <targetfield name="Users"/> </typedef> </fielddef> <fielddef name="Directory_Volume" id="271"> <typedef type="invid"> <vector/> <targetobject name="Embedded_Automounter_Map_Entry"/> <targetfield name="Containing_Object"/> <embedded/> </typedef> </fielddef> <fielddef name="Email_Aliases" id="267"> <typedef type="string"> <vector/> <maxlength val="32"/> <badchars val="@"/> <namespace val="username"/> </typedef> </fielddef> <fielddef name="Signature_Alias" id="268"> <typedef type="string"> <maxlength val="32"/> <badchars val="@"/> </typedef> </fielddef> <fielddef name="Email_target" id="269"> <typedef type="string"> <vector/> <badchars val=":"/> </typedef> </fielddef> </tab> </objectdef>
Ganymede Object Data Import/Export Definition in XML |
While the Ganymede server is capable of expressing its schema definition information in the <ganyschema> section of its XML file, this aspect of Ganymede's XML support is bound to be much less used than the data dumping and loading support. This section discusses the <ganydata> element that may be present in the Ganymede XML file format.
<ganydata> | |
The <ganydata> element is a container for object data to be updated on the server. When exported, the <ganydata> element contains a complete dump of the server's data state. When imported, the <ganydata> element can contain an optional <comment> element describing the transaction to be committed, and a collection of <object> elements which specify the objects to be created, edited, inactivated, or deleted. | |
Parent(s) | Children |
ganymede |
<comment>, <object> |
Attributes | |
|
The <ganydata> element can contain an optional <comment> element containing text describing the purpose of the transaction to be committed by the Ganymede server on successful processing of the <object> elements. The text in the <comment> element will be included in all email generated by the Ganymede server in response to the transaction, and will be included in all logging related to the transaction.
<comment> | |
The optional <comment> element contains a text string describing the transaction to be performed. Any text contained by this element will be included in all email and logging generated for the transaction committed in response to the processing of the <ganydata> element. The <comment> element will never be generated when dumping data with xmlclient. It is only meaningful when submitting change requests to the Ganymede server. If the <comment> element contains anything other than character data, the contents of the <comment> element will be disregarded. You may not include HTML or other XML-formatted text within the <comment> element. |
|
Parent(s) | Children |
<ganydata> | Character data. |
Attributes | |
None | |
Example | |
<comment>This server was decommissioned three years back, but never removed from Ganymede.</comment> |
The <ganydata> element contains a series of <object> elements, each one corresponding to an object in the Ganymede database. The <object> element itself may contain one element for each field in the object. The open tag for the object element as exported contains possibly four attributes, those being type (required), id, num, and action.
<object> | |
The <object> element contains data for a single object. When exported, the <object> element contains a complete dump of the object's state, minus the historical fields (last modification data, etc.).When imported, the <object> element contains a collection of field elements whose contents are to be transmitted to the server to update the object identified by the <object>'s attributes. | |
Parent(s) | Children |
<ganydata> | Various field elements, each with a unique tag name based on the name of the corresponding server field |
Attributes | |
|
Aside from the special case of object inactivation or deletion, all <object> elements in a <ganydata> section will contain a set of elements that correspond to fields in the object to be created or edited on the server. The elements for these fields have no fixed tag name. Instead, each field element will start with an open tag that is named according to the name of the field, with spaces transformed into underscores.
For instance, a record to change the values of the "Room", "Groups", "Home Group" and "Email Aliases" fields in a pre-existing object on the server would be represented in the XML file as:
<object type="User" id="broccol" action="edit"> <Room>S321</Room> <Groups> <invid type="Group" id="omssys"/> <invid type="Group" id="omsnet"/> </Groups> <Home_Group><invid type="Group" id="omssys"/></Home_Group> <Email_Aliases> <string val="abbey"/> <string val="jonabbey"/> </Email_Aliases> </object>
An <object> element contains nothing but such field elements, all of which lack any sort of attributes. The field elements themselves, however, will contain a variety of kinds of elements, depending on the field type. In the above example, the "Room" field is a scalar String field, the "Groups" field is a vector Invid/object reference field, the "Home Group" field is a scalar Invid/object reference field, and the "Email Aliases" field is a vector String field.
In the above example, the Groups and Email_Aliases vector field elements both contain a couple of items. These items will be added to those fields if they are not already present, but the xmlclient will not remove any other items which may already be in those fields.
If you want to assure that after xmlclient finishes its work that there will only be a given list of items in a vector field, you need to do this:
<object type="User" id="broccol" action="edit"> <Room>S321</Room> <Groups> <set> <invid type="Group" id="omssys"/> <invid type="Group" id="omsnet"/> </set> </Groups> </object>
In this example, the <set> container element will force the xmlclient to set the Groups field to contain only the two items listed, adding or removing items as necessary.
You can also manually add or remove individual items, using <add>, <addIfNotPresent>, and <delete>:
<object type="User" id="broccol" action="edit"> <Room>S321</Room> <Groups> <add> <invid type="Group" id="omsovr"/> </add> <delete> <invid type="Group" id="omsnet"/> </delete> </Groups> </object>
This will cause the omsovr group to be added and the omsnet group to be removed. You can have as many <add>, <addIfNotPresent> and <delete> containers as you want within a vector field, but <add>, <addIfNotPresent> and <delete> are not compatible with <set>. If you use <set>, you may not use <add>, <addIfNotPresent> or <delete> as well.
If you don't specify <add>, <addIfNotPresent>, <delete>, or <set>, the xmlclient will treat the items as belonging to an <addIfNotPresent> container. For this reason, the following is not allowed:
<object type="User" id="broccol" action="edit"> <Room>S321</Room> <Groups> <invid type="Group" id="omsovr"/> <set> <invid type="Group" id="omssys"/> <invid type="Group" id="omsnet"/> </set> </Groups> </object>
because the omsovr element is considered to be in an <addIfNotPresent>, which may not co-exist with a <set> in a single field element.
There are presently ten different types of data fields supported by the Ganymede server, and each of these types has its own rules as to what kinds of elements are allowed within the field element and how they may be structured. For the most part, these rules are very similar for all field types, with just the value carrying element type differing. The following table shows the data carrying element types that correspond to the ten field types.
<string> | |
The <string> element contains data for Ganymede string fields, but is mandatory only for vector string fields. The <string> element is not necessary for scalar string fields, which support simply placing the content to be placed in the string field directly between the field element's open and close tags. If the <string> element is used for string field content, it must be empty. | |
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<string val="broccol"/> |
<boolean> | |
The <boolean> element is an optional data element for Ganymede boolean fields. Since Ganymede boolean fields are always scalar, you can simply place true, t, false or f (of whatever capitalization) between the field's start and end tags. If you do use the older <boolean> element as a data container, the <boolean> element must be empty. |
|
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<boolean val="true"/> |
<int> | |
The <int> element is an optional data element for Ganymede numeric fields. Since Ganymede numeric fields are always scalar, you can simply place a 32 bit signed integer value between the containing field's start and end tags. If you do use the older <int> element as a data container, the <int> element must be empty. |
|
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<int val="12042"/> |
<float> | |
The <float> element contains a 64 bit floating point value, corresponding to the IEEE 754-1985 specification, for use with Ganymede float fields. As float fields are scalar in Ganymede, only one <float> element at a time may be contained in a float field element. The <float> element must be empty. | |
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<float val="3.141596254"/> |
<ip> | |
The <ip> element contains an IPv4 or IPv6 address. IP fields may be scalar or vector in Ganymede. The <ip> element must be empty. | |
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<ip val="127.0.0.1"/> , <ip val="::1"/> , <ip val="::FFFF:127.0.0.1"/>
All of these examples encode a loopback address, in either IPv4 or IPv6 form. |
<date> | |
The <date> element contains a Java date value, which is effectively a 64 bit time stamp with millisecond resolution centered at Midnight, January 1, 1970, UTC. As date fields are scalar in Ganymede, only one <date> element at a time may be contained in a field element. The <date> element must be empty. | |
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<date val="Wed 28 Jun 2000 13:13:02" timecode="962215982000"/> |
<password> | |
The <password> element contains a Java password value. As password fields are scalar in Ganymede, only one <password> element at a time may be contained in a field element. The <password> element must be empty. The <password> element may contain any or all of the eight optional attributes: plaintext, crypt, md5crypt, apachemd5crypt, lanman, ntmd4, ssha, shaUnixCrypt and bCrypt. If the plaintext attribute is present, all other hashes will be ignored when the client submits a <password> element, and the Ganymede server will generate new hashes as needed from the plaintext given. If none of the optional attributes are present, the password field will be cleared. All of these options are explained below. If the plaintext attribute is not present but one or more of the hash attributes are, Ganymede will replace any previous information held in this field with information for the hashes you specified. If a Ganymede build process requires hash information that you did not provide when you submitted this <password> element, you may have problems. In general, it is best to pass plaintext information to Ganymede when you want to tell Ganymede about a password change, but you can provide pre-hashed password data to Ganymede if you are comfortable about the limitations you might run into. |
|
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<password md5crypt="$1$o8/.....$f398vnq51gnzf" shaUnixCrypt="$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5"/> |
<options> | |
The <options> element is similar to the <permmatrix> element, in that it provides a mapping for object and field types defined in the Ganymede server. While <permmatrix> provides a set of permission bits for each object or field for a Ganymede Role, the <options> element simply provides option strings for each object type and/or field. The main purpose of these option strings is to control what data triggers a Sync Channel, and what data is written out to an XML queue when a Sync Channel build is triggered. Note that the <options> element was introduced in Ganymede 2.0, and is only acceptable in a Ganymede XML file with a version of at least
|
|
Parent(s) | Children |
Various, based on the names of fields in an <object> | Various, based on the names of object and field types defined |
Attributes | |
None | |
Example | |
<options>
This simple example controls synchronization for User objects in a specific Sync Channel. An options element can contain elements for each object type defined in the server's schema, which in turn can contain nested elements for each custom field defined in that object's schema definition. Both the elements corresponding to object types and the elements corresponding to individual field definitions will have a single attribute, option, containing 0, 1, or (in the case of a field element) 2. These values correspond to the NEVER, WHENCHANGED, and ALWAYS elements in the SyncPrefEnum enum class. 0 stands for NEVER, and means that objects of the given type (or fields in an object type's definition) will never be synchronized to the enclosing Sync Channel. 1 stands for WHENCHANGED, and means that the object or field will be synchronized to the Sync Channel if the object or field was changed by a transaction. 2 stands for ALWAYS, which is only applicable for field elements. A field that is configured with a value of 2 will always be included when the containing object is modified by a transaction, whether or not that field was itself changed by the transaction. See the Ganymede 2.0 Sync Guide for more details on the configuration and operation of a Ganymede Sync Channel. Remember, as always with Ganymede object type and field names in XML, any spaces in an object type name or field name will be replaced by underscores when used as an element name in XML dumps and loads. In the above example, <Home_Group> refers to the "Home Group" field in the User object type. |
<permmatrix> | |
The <permmatrix> element contains a mapping of permission values for object and field types defined in the Ganymede server. The <permmatrix> element is present in the Ganymede Role object, and defines what objects and fields a given Role allows access to. As Permission Matrix fields are scalar in Ganymede, only one <permmatrix> element at a time may be contained in a field element. The <permmatrix> element is designed to contain elements for each object type and field that permissions are set for. | |
Parent(s) | Children |
Various, based on the names of fields in an <object> | Various, based on the names of object and field types defined |
Attributes | |
None | |
Example | |
<permmatrix>
This simple example sets permission bits on the User object itself, along with the Username and UID fields defined as part of the User object type. Object and field names contained within a <permmatrix> element are required to have a The reason that the D flag is not enabled for fields is that there is no discrete notion of 'deletion' that applies to fields. Deleting an object is a distinct operation from editing it, but deleting a field and editing a field to set its contents to empty or null amounts to the same thing in Ganymede, so we don't bother tracking delete permissions for fields. Remember, as always with Ganymede object type and field names in XML, any spaces in an object type name or field name will be replaced by underscores when used as an element name in XML dumps and loads. In the above example, <Home_Group> refers to the "Home Group" field in the User object type. |
<invid> | |
The <invid> element contains a Ganymede object reference value, which is used to identify an object pointer in an invid field on the Ganymede server. The <invid> element must be empty. | |
Parent(s) | Children |
Various, based on the names of fields in an <object> | None |
Attributes | |
|
|
Example | |
<invid type="User" id="broccol"/> |
Embedded Objects |
In addition to the ten field types listed above, there is one unique case, and that is the case of embedded objects. I need to write about this in exhaustive detail.
Example |
For example, a user object from the GASH schema kit might be represented in an XML file in the following fashion:
<object type="User" id="broccol"> <Username>broccol</Username> <UID>12003</UID> <Password><password crypt="j8hgwcyw232Jo"/></Password> <Account_Category><invid type="User_Category" id="normal"/></Account_Category> <Full_Name>Jonathan Abbey</Full_Name> <Division>CSD</Division> <Room>S321</Room> <Office_Phone>3199</Office_Phone> <Home_Phone>335-7681</Home_Phone> <Groups> <invid type="Group" id="omsprl"/> <invid type="Group" id="omsovr"/> <invid type="Group" id="omssys"/> <invid type="Group" id="genweb"/> <invid type="Group" id="gendof"/> <invid type="Group" id="omsnet"/> <invid type="Group" id="ganycvs"/> <invid type="Group" id="omjrst"/> </Groups> <Home_Group><invid type="Group" id="omssys"/></Home_Group> <Login_Shell>/bin/tcsh</Login_Shell> <Home_Directory>/home/broccol</Home_Directory> <Admin_Personae> <invid type="Admin_Persona" id="broccol:GASH Admin"/> <invid type="Admin_Persona" id="broccol:supergash"/> </Admin_Personae> <Netgroups> <invid type="User_Netgroup" id="omg-u"/> <invid type="User_Netgroup" id="omguse-u"/> <invid type="User_Netgroup" id="supad1-u"/> </Netgroups> <Directory_Volume> <object type="Embedded_Automounter_Map_Entry" id="103" num="103"> <Automounter_Map><invid type="Automounter_Map" id="2"/></Automounter_Map> <NFS_Volume><invid type="NFS_Volume" id="23"/></NFS_Volume> </object> </Directory_Volume> <Email_Aliases> <string val="jonabbey"/> <string val="abbey"/> <string val="rust-admin"/> </Email_Aliases> <Signature_Alias>jonabbey</Signature_Alias> <Email_target> <string val="broccol@arlut.utexas.edu"/> <string val="broccol@csdsun7.arlut.utexas.edu"/> </Email_target> <Owner_list> <invid type="Owner_Group" id="OMG"/> </Owner_list> </object>