--- /dev/null
+<ibex-doc title="The Ibex Reference">
+
+ Nitrogen Release
+
+ by <link url="mailto:adam@ibex.org" text="Adam Megacz"/>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Preface">
+
+ This document is a <b>reference</b>. It is not a
+ <b>specification</b> or a
+ <b>tutorial</b>.
+
+ This document does not guide the user gently through examples (as a
+ tutorial would), and it doesn't provide enough detail and formality
+ for a third party to construct a compatible re-implementation of the
+ Ibex Core (as a specification would).
+
+ Rather, the goal of this document is to completely describe every
+ aspect of the environment that the Ibex Core provides to client
+ applications, from the bottom up. If you want to be an Ibex expert,
+ this is the right document to read. It is assumed that you are already
+ familiar with XML and with either JavaScript or ECMAscript. If
+ you are not familiar with ECMAscript, some reference materials are
+ provided in <link section="Appendix G"/>
+
+ The <i>shoehorn sequence</i> (how the Ibex Core gets onto the
+ client's computer, and how it knows where to download the initial .ibex
+ from) is not described in this document, since it will be different
+ for every platform that Ibex is ported to.
+
+ If you need to use or rely on some behavior you notice in the Ibex
+ Core, but which is not clearly defined here, please post to <link
+ url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Key Concepts">
+
+ <section title="Definitions">
+
+ <definition term="The Core">
+ Ibex itself; the native code (or Java bytecode) that runs on
+ the client. This term does not include the <i>shoehorn</i>
+ or the <i>UI</i></definition>
+
+ <definition term="The UI / The Application">
+ a set of files (mostly XML, JavaScript, and PNG images)
+ bundled up in a zip archive, ending with the "..ibex"
+ extension. Together, these files specify the appearance and
+ behavior of the application's user interface. Sometimes
+ we'll refer to this as the ".ibex" to be clear that we're
+ talking about the actual zip archive, rather than its visual
+ appearance when rendered on the screen.</definition>
+
+ <definition term="The Server">
+ We will use the term "the server" to refer to any other
+ computer which the client makes XML-RPC or SOAP calls
+ to. Note that it is possible for the client and server to be
+ the same machine.</definition>
+
+ <definition term="The Shoehorn">
+ this is a very small piece of code that is downloaded the
+ first time a client uses Ibex. It downloads the Ibex core,
+ verifies its signature, and launches it with the appropriate
+ parameters indicating where to find the initial UI. The
+ Shoehorn works differently on every platform, and is outside
+ the scope of this document.</definition>
+
+ <definition term="put/write">
+ In ECMAscript, when you change the value of a property on an
+ object, you are <i>putting</i> to that property, or
+ <i>writing</i> to it. For example, the ECMAscript expression
+ "<tt>foo.bar = 5</tt>" <i>puts</i> the value 5 to the bar
+ property on object foo.</definition>
+
+ <definition term="get/read">
+ In ECMAscript, when you access the value of a property on an
+ object, you are <i>getting</i> that property, or
+ <i>reading</i> from it. For example, the ECMAscript
+ expression "<tt>return (3 + foo.bar)</tt>" <i>gets</i> the
+ value of bar property on object foo and then adds 3 to it
+ before returning the result.</definition>
+
+ <definition term="JavaScript">
+ We will use the terms JavaScript and ECMAScript
+ interchangeably in this document. The Ibex interpreter is not
+ completely ECMA-compliant, however (see <link
+ section="Appendix C"/> for details). </definition>
+
+ </section>
+
+ <section title="Surfaces">
+
+ Each top-level window in an Ibex UI is called a
+ <i>surface</i>. There are two kinds of surfaces: <i>frames</i>, which
+ usually have a platform-specific titlebar and border, and
+ <i>windows</i>, which never have any additional platform-specific
+ decorations.
+
+ Whenever we refer to the size or position of a surface, we are
+ referring to the size or position of the UI-accessible portion of the
+ surface; this does not include any platform-specific decorations. This
+ means that if you set the position of a frame to (0,0), the
+ platform-specific titlebar will actually be off the screen on most
+ platforms (it will be above and to the left of the top-left corner of
+ the screen).
+
+ Surfaces are not actual JavaScript objects; you cannot obtain a
+ reference to a surface. However, each surface is uniquely identified
+ by its <i>root box</i>, described in the next section.
+
+ </section>
+
+ <section title="Boxes">
+
+ A <i>box</i> is the fundamental unit from which all Ibex user
+ interfaces are built. Boxes can contain other boxes (known as
+ <i>children</i>). Each Surface has a single box associated with it
+ called the <i>root box</i>; the root box and its children (and its
+ children's children, and so on) form the surface's <i>box tree</i>.
+
+ There are three ways to think of a box: as a rendered visualization on
+ the screen (the "Visual Representation"), as a JavaScript object (the
+ "Object Representation"), and as an XML tag (the "XML
+ Representation").
+
+ <font color=red>FIXME: diagram here</font>
+
+ All three representations are equally valid, and being able to figure
+ out what an action in one representation would mean in terms of the other
+ two representations is crucial to a solid understanding of Ibex.
+
+ </section>
+
+ <section title="The Object Representation">
+
+ Each box is a full-fledged ECMAscript object, and can store key-value
+ pairs as properties. Some of these keys have special meaning, which
+ will be explained later. Each box's numeric properties hold its
+ <i>child boxes</i>.
+
+ </section>
+
+ <section title="The Visual Representation">
+
+ Each box occupies a rectangular region on the surface. The visual
+ appearance of a surface is created by rendering each box in its tree.
+ Unless the <tt>clip</tt> attribute is <tt>false</tt>, each box will
+ clip its childrens' visual representations to its own, so that the
+ children appear "confined to" the parent. Children are rendered after
+ their parents so they appear "on top of" their parents (they obscure
+ them).
+
+ Each box has two major visual components, each with subcomponents:
+
+ <font color=red>FIXME: diagram</font>
+
+ <list type="unordered">
+
+ A <b>path</b>, which consists of zero or more lines and
+ curves. The path may be filled with a color, gradient, or
+ texture, and may be stroked with a line of a given thickness
+ and color. If the path is not specified, it defaults to the
+ perimiter of the box.
+
+ The path has an associated <b>strokecolor</b>, which is a
+ color
+
+ The path has an associated <b>strokewidth</b>, which is a
+ number specifying the width of the stroke.
+
+ The path also has a <b>fill</b>, which is either a color, gradient, or
+ texture
+
+ A single line of <b>text</b>, which can be rendered in
+ different fonts, colors, and sizes.
+
+ The text has an associated <b>font</b>, which currently can be
+ any font supported by the <link url="http://www.freetype.org"
+ text="FreeType2"/> library.
+
+ The text also has an associated <b>fontsize</b>
+
+ The text is drawn in an associated <b>textcolor</b>
+
+ </list>
+
+ These eight components plus the size of a box fully specify its
+ appearance. Every single box you see in Ibex is drawn only on the
+ basis of these components and its size.
+
+ </section>
+
+ <section title="The XML Representation">
+
+ A template (discussed in the next section) is an XML file which acts
+ as a blueprint for constructing a tree of boxes. We call this
+ construction process <i>applying</i>, since unlike
+ <i>instantiation</i>, you always apply a template to a pre-existing
+ box, and you can apply multiple templates to the same box. Each XML
+ tag corresponds to a single box, or to another template which will be
+ applied to that box. For example, a <tt>scrollbar</tt> template, when
+ applied, will construct a tree of boxes which has the visual
+ appearance and behavior of a scrollbar.
+
+ Although it is useful to think of the XML tags as being boxes, keep in
+ mind that the XML representation is only a blueprint for constructing
+ a tree of JavaScript objects. Once the template has been
+ instantiated, the XML is effectively "thrown away", and JavaScript code is
+ free to alter the boxes.
+
+ </section>
+
+ <section title="Templates">
+
+ Each template is an XML document whose root element
+ is <tt><ibex></tt>. Any text content of the root element is
+ ignored, and may safely be used for comments. The root element may
+ have any of the following elements as children, each of which may
+ appear no more than once, and which must appear in this order:
+
+ Here is a sample Ibex file:
+
+ <pre>
+ <ibex xmlns="ibex.widget" xmlns:lib="ibex.lib">
+ This is a sample Ibex file. Text up here is ignored.
+ Copyright (C) 2004 Mustapha Mond.
+ <static>
+ // code here will be executed only once
+ </static>
+ <template cols="5">
+ <box id="container"/>
+ <checkbox/>
+ <box>
+ /* This has to be commented out or else it
+ will be treated as a script */
+ <lib:scrollbar/>
+ </box>
+ </template>
+ </ibex>
+ </pre>
+
+ </section>
+
+ <section title="Applying an XML tag to a box">
+
+ The following description of the box application is extremely detailed
+ and precise; it is intended for UI designers who need to know the
+ exact order in which each event happens. <font color=RED>FIXME:
+ easier description</font>. While this whole process sounds very
+ complex, it actually works pretty intuitively. The description below
+ is given in great detail since most applications will wind up being
+ unintentionally dependent on subtle features of this process.
+ However, most of the time you can just pretend that the XML tags and
+ the boxes are the same thing.
+
+ To apply an XML tag <b>X</b> to a box <b>B</b>, perform the following
+ operations, in this order:
+
+ <list type="ordered">
+
+ Allocate a fresh scope <b>s</b> whose parent scope is
+ <b>B</b>.
+
+ Process each child element or text segment of <b>X</b> in the
+ order they appear in the document: For each <i>text
+ segment</i> <b>t</b>:
+
+ Treat <b>t</b> a JavaScript script, and execute it
+ with <b>s</b> as the root scope.
+
+ For each <i>child element</i> <b>x</b> of <b>X</b>:
+
+ Create a new box <b>b</b>.
+
+ If the name of tag <b>x</b> is not <tt>"box"</tt> (in the
+ default XML namespace), prepend the tag's namespace
+ identifier uri (if any) to the name of the tag, and use
+ the result as a key to retrieve a property from the root
+ stream (defined later). Interpret the resulting stream as
+ a template and apply that template to <b>b</b>.
+
+ (recursively) apply <b>x</b> to <b>b</b>.
+
+ If <b>x</b> has an <tt>id</tt> attribute, declare a variable
+ in <b>s</b> whose name is the value of the <tt>id</tt>
+ attribute, prefixed with the <tt>$</tt> character, and whose
+ value is <b>b</b>
+
+ Copy any <tt>$</tt>-variables created during the application
+ of <b>x</b> into scope <b>s</b>.
+
+ Append <b>b</b> as the last child of <b>B</b>.
+
+ Apply any attributes on <b>X</b> to <b>B</b>, except for
+ <tt>id</tt>. Since XML specifies that the order of attributes
+ cannot be significant, Ibex processes attributes in
+ alphabetical order by attribute name. For example, if
+ <b>X</b> has the attribute <tt>foo="bar"</tt>, then the
+ equivalent of the statement <tt>B.foo="bar";</tt> will be
+ performed, with the following exceptions:
+
+ If the value portion of the attribute is the string
+ <tt>"true"</tt>, put the boolean <tt>true</tt>. If the
+ value is <tt>"false"</tt>, put the boolean <tt>false</tt>.
+
+ If the value is a valid ECMAscript number, put it as a
+ number (instead of a string).
+
+ If the value begins with a dollar sign (<tt>$</tt>),
+ retrieve the value of the corresponding variable in
+ <b>s</b> and use that value instead.
+
+ If the value begins with a dot (<tt>.</tt>), prepend the
+ attributes' namespace identifier uri (if any) and
+ interpret the remainder as a property to be retrieved from
+ the root stream (defined later).
+ </list>
+
+ The last two steps are referred to as the <i>initialization</i> of the
+ node. There are two important aspects of this ordering to be aware of:
+
+ <list type="unordered">
+
+ A given box will be fully initialized before its parent is
+ given a reference to that box. This way, parents can be
+ certain that they will never wind up accessing a box when it
+ is in a partially-initialized state.
+
+ Attributes are applied <i>after</i> scripts are run so that
+ the attributes will trigger any <i>traps</i> (defined later)
+ placed by the script.
+
+ </list>
+
+ </section>
+
+ <section title="Life Cycle of an Ibex Application">
+
+ A user begins by specifying the URL of an Ibex application run.
+ Usually this is done by visiting a web page which uses the
+ <i>shoehorn</i> to install the core if it is not already on the user's
+ machine, but you can also supply the URL on the command line.
+
+ The Ibex Core downloads the .ibex for the application, loads it, applies
+ the <tt>main.ibex</tt> template and renders it onto the screen, running
+ any associated ECMAscript code.
+
+ The user interacts with the application by clicking and moving the
+ mouse, and by pressing keys on the keyboard. These actions trigger
+ fragments of JavaScript code which are designated to handle events.
+ This JavaScript code can then relay important information back to the
+ server using XML-RPC or SOAP, or it can modify the structure and
+ properties of the user interface to change its appearance, thereby
+ giving feedback to the user.
+
+ <font color="red">
+ DIAGRAM: graphic here showing the circular feedback cycle.
+ </font>
+
+ The Ibex core quits when the last remaining surface has been destroyed.
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Layout and Rendering">
+
+ The size and position of every other box is determined
+ by its properties, its childrens' sizes, and its parent's size and position.
+ Box layout and rendering happens in four phases: <i>packing</i>,
+ <i>constraining</i>, <i>placing</i>, and <i>rendering</i>. The Core is careful to only
+ perform a phase on a box if the box has changed in a way that
+ invalidates the work done the last time that phase was performed.
+ The
+ packing and constraining phases are performed in a single traversal of
+ the tree (packing is preorder, constraining is postorder), and the
+ placing and rendering phases are performed in a second traversal of
+ the tree (first placing, then rendering, both preorder).
+
+ For brevity, the rest of this chapter deals only with width and
+ columns. Height and rows is treated identically and independently.
+ Also, it is important to note that the term <i>minimum width</i> is
+ not the same thing as the property <tt>minwidth</tt>, although they
+ are closely related.
+
+ <section title="The size of the root box">
+
+ When the user resizes a window, Ibex changes the root box's
+ <tt>maxwidth</tt> and <tt>maxheight</tt> to match the size chosen by
+ the user and then determines the root box's size using the same sizing
+ rules it uses for other boxes.
+
+ Ibex will always attempt to prevent the
+ user from making the surface smaller than the root box's
+ <tt>minwidth</tt> and <tt>minheight</tt>. If the <tt>hshrink</tt> or
+ <tt>vshrink</tt> flag is set, Ibex will try to prevent the user from
+ resizing the surface at all. However, not all platforms give Ibex
+ enough control to do this.
+
+ </section>
+
+ <section title="The alignment point">
+
+ When talking about positioning, we will often refer to the
+ <i>alignment point</i>.
+
+ <list type="unordered">
+
+ If the <tt>align</tt> property is <tt>"center"</tt>, then the
+ alignment point is the center of the box.
+
+ If the <tt>align</tt> property is <tt>"topleft"</tt>,
+ <tt>"bottomleft"</tt>, <tt>"topright"</tt>, or
+ <tt>"bottomright"</tt>, then the alignment point is
+ corresponding corner of the box.
+
+ If the <tt>align</tt> property is <tt>"top"</tt>,
+ <tt>"bottom"</tt>, <tt>"right"</tt>, or <tt>"left"</tt>, then
+ the alignment point is middle of the corresponding edge of the
+ box.
+
+ </list>
+
+ <font color=red>FIXME: diagram</font>
+
+ When positioning a child box, the alignment point is determined by the
+ <i>parent's</i> <tt>align</tt> property. When positioning a visual
+ element (a texture, path, or text string) within a box, the alignment
+ point is determined by the <i>box's own</i> <tt>align</tt> property.
+
+ A simple way to think about this is that whenever there are two boxes
+ involved in the decision, you should use the parent's alignment point.
+
+ </section>
+
+ <section title="Packing">
+
+ of <i>cells</i> is created within the parent. If the parent's
+ <tt>cols</tt> property is set to 0, the cell grid has an infinite
+ number of columns. Either <tt>cols</tt> or <tt>rows</tt> must be
+ zero, but not both.
+
+ If a child's <tt>visible</tt> property is <tt>false</tt>, it does
+ not occupy any cells (and is not rendered). Otherwise, each child
+ occupies a rectangular set of cells <tt>child.colspan</tt> cells
+ wide and <tt>child.rowspan</tt> cells high.
+
+ The Core iterates over the cells in the grid in the following
+ order: if <tt>rows</tt> is 0, the Core iterates across each column
+ before proceeding to the next row; otherwise rows come before
+ columns. At each cell, the Core attempts to place the <i>first
+ remaining unplaced child's</i> top-left corner in that cell (with
+ the child occupying some set of cells extending down and to the
+ right of that cell). If the parent has a fixed number of columns
+ and the child's <tt>colspan</tt> exceeds that limit, the child is
+ placed in column zero regardless, but only occupies the available
+ set of cells (it does not "hang off the end" of the box).
+
+ <img src="image/layout.png">
+
+ <pre>
+ <box cols="3">
+ <box id="1" />
+ <box id="2" rowspan="2" />
+ <box id="3" colspan="2" />
+ <box id="4" />
+ <box id="5" colspan="2" />
+ </box>
+ </pre>
+
+ Notes on the layout example:
+
+ <list type="ordered">
+
+ Box '3' doesn't fit in the gap after '2', nor in the gaps either
+ side of '2' on the next row, hence it is pushed onto the 3rd row.
+
+ Box '4' would fit in the gaps around '2', but must be placed
+ <i>after</i> it's preceeding box, '3'.
+
+ </list>
+
+ </section>
+
+ <section title="Constraining">
+
+ <list type="ordered">
+
+ Each box's minimum width is computed recursively as the
+ maximum of:
+
+ Its <tt>minwidth</tt>
+
+ The width of the box's <tt>text</tt> (after applying the
+ box's <tt>transform</tt>).
+
+ The width of the box's path (after applying the box's
+ <tt>transform</tt>) <i>if the box is <tt>packed</tt></i>.
+
+ The width of the bounding box enclosing the box's cells.
+ </list>
+
+ The minimum width of each cell is computed as the minimum
+ width of the box occupying it divided by the box's
+ <tt>colspan</tt>.
+
+ If a box's <tt>hshrink</tt> property is set to
+ <tt>true</tt>, the box's maximum width is the same as its
+ minimum width; otherwise it is the box's
+ <tt>maxwidth</tt>.
+
+ The maximum width of each cell is the <tt>maxwidth</tt> of
+ the box occupying it divided by the box's
+ <tt>colspan</tt>.
+
+ </list>
+
+ </section>
+
+ <section title="Placing">
+
+ <list type="ordered">
+
+ Each column's <i>actual width</i> is set to the maximum
+ <i>minimum width</i> of all the cells in that column.
+ <b>NOTE:</b> although a column or row can be sized smaller
+ than its "minimum width" or larger than its "maximum width", a
+ box will <i>never</i> be smaller than its <tt>minwidth</tt> or
+ larger than its <tt>maxwidth</tt>.
+
+ Each column's maximum width is the largest maximum width of
+ the cells in that column, but no smaller than the column's
+ minimum width.
+
+ The <i>slack</i> is the difference between the parent's width
+ and the sum of its columns' actual width. The slack is
+ divided equally among the columns. Any column which has
+ exceeded its maximum width is set to its maximum width, and
+ the difference is returned to the slack. This process is
+ repeated until the slack is zero or all columns are at their
+ maximum width.
+
+ Next, the rows and columns are positioned within the parent
+ box. The rows and columns are transformed according to the
+ parent's <tt>transform</tt> property, and the bounding box of
+ the resulting cells are placed such that the cells' alignment
+ point coincides with the parent's alignment point (both
+ alignment points are determined by the parent's <tt>align</tt>
+ property). <font color=red>FIXME: diagram</font>
+
+ <b>Packed boxes:</b> Each packed box's actual position
+ and size is then set to the aggregation of the actual sizes of
+ the cells it spans. If this size exceeds the box's maximum
+ width, the box is sized to its maximum width and centered
+ horizontally within the space occupied by its cells.
+ <b>Non-packed boxes</b>: each non-packed box is transformed
+ according to the parent's <tt>transform</tt> property and then
+ positioned so that its alignment point is <tt>(child.x,
+ child.y)</tt> pixels from the parent's alignment point (both
+ alignment points are determined by the parent's <tt>align</tt>
+ property).
+
+ </list>
+
+ </section>
+
+ <section title="Rendering">
+
+ Boxes are rendered in a depth-first, pre-order traversal. Note that
+ this may cause a non-packed box to overlap its siblings.
+
+ <list type="ordered">
+
+ If the box's <tt>transform</tt> property is non-null, the
+ coordinate space is transformed accordingly for the rest of
+ this phase and for the rendering of all children.
+
+ If the box is packed and has a non-<tt>null</tt> path, the
+ path is translated such that the alignment point of the path's
+ bounding box coincides with the box's alignment point (both
+ alignment points are determined by the box's <tt>align</tt>
+ property).
+
+ If a box has a path, that path is filled with the color,
+ gradient, or image specified by the <tt>fill</tt> property and
+ stroked with the color and width specified by the
+ <tt>strokecolor</tt> and <tt>strokewidth</tt> properties.
+
+ If the box has a non-<tt>null</tt> <tt>text</tt> attribute,
+ the text is rendered in <tt>font</tt> with size
+ <tt>fontsize</tt> and color <tt>textcolor</tt>. The text is
+ then translated such that the alignment point of the text's
+ bounding box coincides with the box's alignment point (both
+ alignment points are determined by the box's <tt>align</tt>
+ property).
+
+ The box's children are rendered (pre-prder traversal).
+
+ </list>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Box Properties">
+
+ <section title="Rendering Properties">
+
+ Every box has several special properties which control how it is
+ drawn. In general, if you put an
+ invalid value to a special property, no action will be taken -- the
+ put will be ignored.
+
+ <property name="strokecolor" type="string" default="clear">
+ If the value is a 5-character hex string (<tt>#RGB</tt>),
+ 7-character hex string (<tt>#RRGGBB</tt>), 9-character hex
+ string (<tt>#AARRGGBB</tt>), the box's stroke color will be set
+ to that color.
+ If the value is one of the <link url="http://www.color.org/ICC-1A_1999-04.PDF" text="ICC"/> colors
+ (the same set of color names supported by SVG), the stroke
+ color be set to that color.
+ If the value is <tt>null</tt>, the stroke color will be set to
+ clear (<tt>#00000000</tt>).
+ </property>
+
+ <property name="strokewidth" type="int" default="1">
+ The width (in pixels) to stroke the path with.
+ </property>
+
+ <property term="fill">
+ This property can be set to any of the values specified for
+ <tt>strokecolor</tt>.
+ Alternatively, if the value written is an object, its stream
+ will be read and interpreted as a PNG, GIF, or JPEG image,
+ which will become the texture for this box, and the box's
+ <tt>minwidth</tt> and <tt>minheight</tt> properties will be
+ automatically set to the dimensions of the image.
+ </property>
+
+ <property name="path" type="string" default="""">
+ The box's path. The grammar and feature set
+ supported are identical to that specified in <link url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1, section
+ 8"/>.
+ </property>
+
+ <property name="text" type="string" default="""">
+ The box's text; writing <tt>null</tt> to this property sets it
+ to <tt>""</tt>.
+ </property>
+
+ <property name="font" type="stream" default="<tt>.ibex.font.sansserif</tt>">
+ When an object is written to this property, its stream is read
+ using the <link url="http://www.freetype.org" text="freetype2
+ library"/>, and the resulting font is used to render the
+ box's <tt>text</tt>.
+ </property>
+
+ <property name="fontsize" type="number" default="<tt>10</tt>">
+ The size (in points) to render the text.
+ </property>
+
+ <property name="textcolor" type="number" default="black">
+ The color in which to render the font; accepts the same values as <tt>strokecolor</tt>.
+ </property>
+
+ </section>
+
+ <section title="Layout Properties">
+
+ <property name="shrink" type="boolean" default="<tt>false</tt>">
+ If set to <tt>true</tt>, this box will shrink
+ (horizontally/vertically/both) to the smallest size allowed by
+ its children and the bounding box of its path.
+ </property>
+
+ <property name="x" type="integer" default="<i>varies</i>">
+ If the box is a root box, this is the (x/y)-coordinate of the
+ surface; otherwise it is the distance between the parent's
+ alignment point and this box's alignment point.
+ </property>
+
+ <property name="globalx" type="integer" default="<i>varies</i>">
+ The distance between this box's (left/top) edge and the root
+ box's (left/top) edge. A put to this property has the same
+ effect as a put to the (<tt>x</tt>/<tt>y</tt>) property,
+ except that it is relative to the root box rather than to this
+ box's parent. <font color=red>FIXME is this fakeable? How is
+ distance measured?</font>
+ </property>
+
+ <property name="minwidth" type="integer" default="<tt>0</tt>">
+ The desired minimum width and height.
+ </property>
+
+ <property name="maxwidth" type="integer" default="<tt>ibex.maxint</tt>">
+ The desired maximum width and height.
+ </property>
+
+ <property name="width" type="integer" default="<i>varies</i>">
+ When read, this is the (width/height) of this box. Writing to
+ this property is equivalent to writing to <i>both</i> the
+ minimum and maximum (width/height).
+ </property>
+
+ <property name="cols" type="integer" default="<tt>0</tt>">
+ The number of (columns/rows) in which to lay out the children of this
+ box. If set to zero, the number of (columns/rows) is unconstrained.
+ Either <tt>rows</tt> or <tt>cols</tt> must be zero. If
+ <tt>0</tt> is written to <tt>cols</tt> when <tt>rows</tt> is
+ <tt>0</tt>, the write is ignored. If a nonzero value is
+ written to <tt>cols</tt> when <tt>rows</tt> is nonzero,
+ <tt>rows</tt> is set to <tt>0</tt>, and vice versa.
+ </property>
+
+ <property name="colspan" type="integer" default="<tt>1</tt>">
+ The number of (columns/rows) that this box spans within its parent.
+ </property>
+
+ <property name="align" type="string" default="<tt>"center"</tt>">
+ Determines the box's alignment point for positioning its text,
+ texture, path, and children.
+ </property>
+
+ <property name="visible" type="boolean" default="<tt>true</tt>">
+ If set to false, this box will be rendered as if its width and
+ height were zero. If this is a root box, the associated surface
+ will be hidden.
+ When reading from this property, the value
+ <tt>false</tt> will be returned if this box <i>or any of its
+ ancestors</i> is not visible. Thus it is possible to write
+ <tt>true</tt> to a box's <tt>visible</tt> property and then
+ read back <tt>false</tt>.
+ </property>
+
+ <property name="packed" type="boolean" default="<tt>true</tt>">
+ The layout strategy for this box.
+ </property>
+
+ </section>
+
+ <section title="Child Control Properties">
+
+ During a box initialization, script-private references to a box's
+ descendants with <tt>id</tt> attributes are placed on the box. These
+ references allow scripts on that box to easily refer to descendant
+ nodes created by the template in which the script appears. For
+ example, these two blocks of code have exactly the same effect:
+
+ <pre>
+ <box> <box>
+ <box id="foo"/> <box/>
+ $foo.color = "red"; var $foo = this[0];
+ $foo.color = "red";
+ </box> </box>
+ </pre>
+
+ The following special properties control how a box's children are laid
+ out. If a box has a non-null redirect target, reads and writes to these
+ properties will be forwarded to the redirect target.
+
+ The <tt>redirect</tt> attribute is very useful for hiding the
+ internal structure of a widget, and for allowing widgets to act as
+ "smart" containers for other widgets. For example, a menu widget might
+ have an invisible child as its redirect target; this way, when boxes
+ representing items on the menu are added as children of the menu
+ widget, they do not appear until the menu is pulled down.
+
+ <property name="numeric properties" type="int" default="">
+ The <i>n</i>th child of box <tt>b</tt> can be accessed by reading from
+ <tt>b[n]</tt>. The <i>n</i>th child can be removed by writing
+ <tt>null</tt> to <tt>b[n]</tt> (the child will become parentless). A
+ new child can be inserted <i>before</i> the <i>n</i>th child by
+ writing it to <tt>b[n]</tt>; if the value written is already a child of
+ <tt>b</tt>, it will be removed from <tt>b</tt> first. It is important
+ to note that this behavior is different from ECMAscript arrays --
+ writing a non-<tt>null</tt> value to <tt>b[n]</tt> does not eliminate
+ the <i>n</i>th child; it merely shifts it over one position.
+ <b>Note:</b> Unlike most JavaScript objects, enumerating a Box's
+ properties with the JavaScript <tt>for..in</tt> construct will
+ enumerate <i>only</i> the box's children and not any other properties.
+ </property>
+
+ <property name="clip" type="boolean" default="<tt>true</tt>">
+ If <tt>true</tt>, the visual representation of this box's
+ children will be clipped to the boundaries of this box.
+ <b>Note:</b> setting this property to <tt>false</tt> imposes a
+ substantial performance penalty.
+ </property>
+
+ <property name="numchildren" type="integer" default="<tt>0</tt>">
+ The number of children this box has.
+ </property>
+
+ <property name="redirect" type="box" default="<tt>thisbox</tt>">
+ Writing to this property sets the box's redirect
+ target. This property cannot be read from, and can only be
+ written to once.
+ </property>
+
+ <property name="surface" type="" default="<tt>null</tt>">
+ If this box has a parent, this property returns
+ <tt><i>parent</i>.surface</tt>; otherwise it returns null.
+ This property is a simple building block that the widget
+ library uses to implement more complex functionality such as
+ focus control and popups.
+ </property>
+
+ </section>
+
+ <section title="Other Box Properties">
+
+ <property name="cursor" type="string" default="<tt>null</tt>">
+ The shape that the cursor should take when inside this
+ box. Valid values are: <tt>"default"</tt>, <tt>"wait"</tt>,
+ <tt>"crosshair"</tt>, <tt>"text"</tt>, <tt>"hand"</tt>, and
+ <tt>"move"</tt>, as well as resizing cursors<tt>"east"</tt>,
+ <tt>"west"</tt>, <tt>"north"</tt>, <tt>"south"</tt>,
+ <tt>"northwest"</tt>, <tt>"northeast"</tt>,
+ <tt>"southwest"</tt>, and <tt>"southeast"</tt>. Note that on
+ some platforms, resize cursors for opposite directions (such
+ as <tt>northwest</tt> and <tt>southeast</tt> are the
+ same).
+ If a box's cursor is <tt>null</tt>, its parent's cursor will
+ be used. If the root box's cursor is null, the
+ <tt>"default"</tt> cursor will be used.
+ </property>
+
+ <property name="mouse.x" type="integer" default="<i>varies</i>">
+ The (horizontal/vertical) distance between the mouse cursor and this
+ box's (left/top) edge. Puts to this property are ignored. This
+ value will not be updated if the mouse is outside the root
+ box of the surface and no button was pressed when it left.
+ </property>
+
+ <property name="mouse.inside" type="boolean" default="<tt>false</tt>">
+ True if the mouse is inside the rendered region of this box or
+ any of its children. This value will be false if the mouse is
+ inside a portion of this box which is covered up by one of
+ this box's siblings, or one of its ancestors' descendants. Puts
+ to this value are ignored.
+ </property>
+
+ <property name="static" type="object" default="N/A">
+ Reading from this property will return the parent scope used
+ to execute the <tt><static/></tt> block of the template
+ in which the currently-executing code resides.
+ </property>
+
+ <property name="thisbox" type="box" default="<tt> </tt>">
+ Returns a reference to the box itself.
+ If <tt>null</tt> is written to this property, and this box is
+ the root box of a surface, the box will be detached and the
+ surface destroyed. If this box has a parent, it will be
+ detached from its parent.
+ </property>
+
+ <property name="indexof()" type="function" default="<tt> </tt>">
+ This property is actually a function; invoking
+ <tt>parent.indexof(child)</tt> will return the numerical index
+ of <tt>child</tt> in <tt>parent</tt> if <tt>child</tt> is a
+ child of <tt>parent</tt> (or <tt>parent</tt>'s redirect
+ target), and <tt>-1</tt> otherwise. Writing to this property
+ has no effect.
+ </property>
+
+ <property name="childadded" type=" " default="<tt> </tt>">
+
+ These properties are meant to be trapped on <font
+ color=red>FIXME defined later?</font>. Placing a trap on
+ <tt>childadded/childremoved</tt> lets a box receive
+ notification when a child is added/removed. In either
+ situation, the child will be passed as an argument to the trap
+ function <i>after</i> the addition or removal has been
+ performed.
+
+ Note that if the parent's redirect target is set to another
+ box, these traps will only be invoked when children are
+ manipulated by reading and writing to the parent. Reads and
+ writes directly to the redirect target will <i>not</i> trigger
+ the traps.
+
+ Note also that these traps are still triggered if a box's
+ <tt>redirect</tt> target is <i>null</i>. This is useful for
+ boxes that need to accept children and then relocate them
+ elsewhere.
+ </property>
+
+ </section>
+
+ <section title="Notification Properties">
+
+ The following properties are used to notify a box of changes specific
+ to that particular box.
+
+ <property name="Enter">
+ The value <tt>true</tt> is written to this property when the mouse enters the box.
+ </property>
+
+ <property name="Leave">
+ The value <tt>true</tt> is written to this property when the mouse leaves the box.
+ </property>
+
+ <property name="SizeChange">
+ The value <tt>true</tt> is put to this property after the size
+ of this box changes.
+ </property>
+
+ </section>
+
+ <section title="Root Box Properties">
+
+ The following special properties are only meaningful on the root box
+ of a surface.
+
+ <property name="Focused">
+ The value <tt>true</tt> is put to this property on the root box
+ when the surface gains the input focus, and <tt>false</tt> when
+ the surface loses the input focus. Reading from this value will
+ return <tt>true</tt> if the surface is focused and <tt>false</tt>
+ if it is not. Putting <tt>true</tt> to this property will
+ <i>not</i> cause the surface to "steal" the input focus from other
+ windows.
+ </property>
+
+ <property name="Maximized">
+ The value <tt>true</tt> is put to this property on the root box
+ when the surface is maximized, and <tt>false</tt> when the surface
+ is un-maximized. Reading from this value will return <tt>true</tt>
+ if the surface is maximized and <tt>false</tt> if it is
+ not. Putting <tt>true</tt> to this property will maximize the
+ window, and putting <tt>false</tt> to this property will
+ unmaximize the window.
+ Note that not all platforms support maximization.
+ </property>
+
+ <property name="Minimized">
+ The value <tt>true</tt> is put to this property on the root box
+ when the surface is minimized, and <tt>false</tt> when the surface
+ is unminimized. Reading from this value will return <tt>true</tt>
+ if the surface is minimized and <tt>false</tt> if it is
+ not. Putting <tt>true</tt> to this property will minimize the
+ window, and putting <tt>false</tt> will unminimize it.
+ </property>
+
+ <property name="Close">
+ When the user attempts to close a surface, the value
+ <tt>true</tt> will be put to this property. Scripts may trap
+ this property <font color=red>FIXME defined later?</font> to
+ prevent the window from closing. Putting the value
+ <tt>true</tt> to this property on a root box has the same
+ effect as putting <tt>null</tt> to the <tt>thisbox</tt>
+ property.
+ </property>
+
+ <property name="icon">
+ The surface's icon. This is usually displayed on the titlebar of a
+ window. The value should be the stream name of a PNG image. Note
+ that not all platforms support this property.
+ </property>
+
+ <property name="titlebar">
+ The surface's titlebar text. Note that not all platforms support
+ this property. Only ASCII characters 0x20-0x7F are permitted.
+ </property>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="Streams">
+
+ <section title="Every object has a stream...">
+
+ Every object has a <i>stream</i> associated with it. A stream is a
+ sequence of bytes that can be read or written to.
+
+ By default an object has an empty stream (zero bytes). However, some objects
+ (returned from special methods on the <tt>ibex</tt> object) have
+ streams yielding data read from an url, file, or a component of a zip
+ archive. In a future release, the stream associated with a box will
+ be an .ibex template which, when applied, will fully reconstitute the
+ box's state.
+
+ </section>
+
+ <section title="...but streams are not objects">
+
+ Despite the ubiquity of streams, you cannot actually reference a
+ stream, since it is not an object. Instead, you simply reference the
+ object it belongs to. If you are familiar with Java, this is similar
+ to how every Java object has a monitor associated with it, but you
+ cannot directly manipulate the monitor (you can't pass around a
+ reference to just the monitor).
+
+ In the rest of the section we will sometimes refer to "getting
+ properties from a stream" or "passing a stream to a function"; this is
+ just shorthand for saying to perform those actions on the object the
+ stream belongs to.
+
+ </section>
+
+ <section title="Creating Streams from URLs">
+
+ You can create a stream from a URL by calling
+
+ <pre>
+ var r = ibex.stream.url("http://...");
+ </pre>
+
+ This will return an object whose stream draws data from the specified
+ URL. Streams are loaded lazily whenever possible.
+
+ </section>
+
+ <section title="Getting Substreams">
+
+ Most stream objects let you access
+ substreams using the usual JavaScript operators <tt>[]</tt> and
+ <tt>.</tt>, as well as the <tt>for..in</tt> syntax.
+
+ <pre>
+ // r1 and r2 are equivalent but not equal (!=)
+ var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
+ var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
+ </pre>
+
+ </section>
+
+ <section title="The Root Stream">
+
+ The empty-string property on the <tt>ibex</tt> object is called the
+ <i>root stream</i>. You can access this object as <tt>ibex..</tt> or
+ <tt>ibex[""]</tt>. Additionally, any expression which starts with a
+ dot is treated as property to be retrieved from the root stream. The
+ following three expressions are equivalent:
+
+ <pre>
+ ibex..foo
+ ibex[""].foo
+ .foo
+ </pre>
+
+ </section>
+
+ <section title="Static Blocks">
+
+ You can access variables within the static block of a template by
+ appending a double period (<tt>..</tt>) and the variable name to the
+ stream used to load that template:
+
+ <pre>
+ <!-- org/ibex/themes/monopoly/scrollbar.ibex -->
+ <ibex>
+ <static>
+ foo = 12;
+ ...
+ // elsewhere
+ ibex.log.print(org.ibex.themes.monopoly.scrollbar..foo); // prints "12"
+ </pre>
+
+ </section>
+
+ <section title="Formatting Streams">
+
+ If you attempt to send a stream as part of an XML-RPC call, the
+ stream will be read in its entirity, Base64-encoded, and transmitted
+ as a <tt><base64/></tt> element.
+
+ Ibex supports two special URL protocols. The first is <tt>data:</tt>,
+ which inteprets the rest of the URL as a Base64 encoded sequence of
+ bytes to use as a source. The other is <tt>utf8:</tt> which
+ interpretets the rest of the string as a Unicode character sequence to
+ be UTF-8 encoded as a string of bytes to use as a source.
+
+ <pre>
+ var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
+ var r6 = ibex.stream.url("utf8:this is a test");
+ </pre>
+
+ You can read a UTF-8 encoded string from a stream like this:
+
+ <pre>
+ var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:this is a test"));
+ </pre>
+ You can also parse XML from a stream using SAX like this:
+
+ <pre>
+ ibex.stream.xml.sax(ibex.stream.url("http://foo.com/foo.xml"),
+ { beginElement : function(tagname, attributeKeyValuePairs) { ... },
+ endElement : function(tagname) { ... },
+ content : function(contentString) { ... }
+ whitespace : function(whitespaceString) { ... }
+ });
+ </pre>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="The Ibex object">
+
+ The <tt>ibex</tt> object is present in the top-level scope of every
+ script. It has the following properties:
+
+ <section title="General">
+
+ <table class="props">
+ <tr><td><tt>ibex.box</tt></td> <td>reading from this property returns a new box</td></tr>
+ <tr><td><tt>ibex.clone(o)</tt></td> <td>creates a clone of object <i>o</i></tr>
+ <tr><td><tt>ibex.bless(s)</tt></td> <td>returns a blessed clone of stream <i>s</i></tr>
+ </table>
+
+ </section>
+
+ <section title="ECMA Library Objects">
+
+ <table class="props">
+ <tr><td><tt>ibex.date</tt></td> <td>reading from this property returns a new date</td></tr>
+ <tr><td><tt>ibex.math</tt></td> <td>this object contains the ECMA math functions</td></tr>
+ <tr><td><tt>ibex.regexp(s)</tt></td> <td>return a regexp object corresponding to string <i>s</i></td></tr>
+ <tr><td><tt>ibex.string</tt></td> <td>this object contains the ECMA string manipulation functions</td></tr>
+ </table>
+
+ </section>
+
+ <section title="Logging">
+
+ <property name="ibex.log.debug(m, o)">
+ log the debug message <i>m</i>, optionally dumping object
+ <i>o</i>
+ </property>
+
+ <property name="ibex.log.info(m, o)">
+ log the informational message <i>m</i>, optionally dumping
+ object <i>o</i>
+ </property>
+
+ <property name="ibex.log.warn(m, o)">
+ log the warning message <i>m</i>, optionally dumping object
+ <i>o</i>
+ </property>
+
+ <property name="ibex.log.error(m, o)">
+ log the error message <i>m</i>, optionally dumping object
+ <i>o</i>
+ </property>
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="User Interface">
+
+ <property name="ibex.ui.browser(u)">
+ opens a new browser window with URL <i>u</i>
+ </property>
+
+ <property name="ibex.ui.key.control">
+ true if the control key is depressed
+ </property>
+
+ <property name="ibex.ui.key.shift">
+ true if the shift key is depressed
+ </property>
+
+ <property name="ibex.ui.key.alt">
+ true if the alt key is depressed
+ </property>
+
+ <property name="ibex.ui.key.name.alt">
+ the name of the "alt" key (usually either "alt", "meta", or
+ "option")
+ </property>
+
+ <property name="ibex.ui.clipboard">
+ the contents of the clipboard; can be read and written to
+ </property>
+
+ <property name="ibex.ui.maxdim">
+ the maximum dimension of any UI element; usually
+ 2<sup>31</sup>, but may be smaller
+ </property>
+
+ <property name="ibex.ui.screen.width">
+ the width of the screen, in pixels
+ </property>
+
+ <property name="ibex.ui.screen.height">
+ the height of the screen, in pixels
+ </property>
+
+ <property name="ibex.ui.mouse.button">
+ either 0, 1, 2, or 3, indicating the mouse button currently
+ being pressed
+ </property>
+
+ <property name="ibex.ui.frame">
+ when a box is written to this property, it becomes the root
+ box of a new window
+ </property>
+
+ <property name="ibex.ui.window">
+ when a box is written to this property, it becomes the root
+ box of a new frame
+ </property>
+
+ <property name="ibex.ui.font.serif">
+ an object whose stream is a a builtin serif font
+ </property>
+
+ <property name="ibex.ui.font.sansserif">
+ an object whose stream is a builtin sans-serif font
+ </property>
+
+ <property name="ibex.ui.font.monospace">
+ an object whose stream is a a builtin fixed-width font
+ </property>
+
+ <section title="Networking">
+
+ <property name="ibex.net.http">
+ <font color=red><i>not yet implemented</font>
+ </property>
+
+ <property name="ibex.net.rpc.xml(u)">
+ return an XML-RPC call object with endpoint URL <i>u</i>
+ </property>
+
+ <property name="ibex.net.rpc.soap(u,">
+ return a SOAP call object with endpoint URL <i>u</i>,
+ SoapAction <i>a</i>, and XML Namespace <i>n</i>
+ </property>
+
+ </section>
+
+ <section title="Threads">
+
+ <property name="ibex.thread">
+ when a function is written to this property, a new thread is
+ forked to call it
+ </property>
+
+ <property name="ibex.thread.yield()">
+ yield the current thread
+ </property>
+
+ <property name="ibex.thread.sleep(n)">
+ sleep for <i>n</i> milliseconds
+ </property>
+
+ </section>
+
+ <section title="Streams">
+
+ <property name="ibex.stream.url(u)">
+ returns a new object whose stream is drawn from URL <i>u</i>
+ </property>
+
+ <property name="ibex.stream.unzip(s)">
+ unpacks a zip archive from <i>s</i>'s stream
+ </property>
+
+ <property name="ibex.stream.uncab(s)">
+ unpacks a cab archive from <i>s</i>'s stream
+ </property>
+
+ <property name="ibex.stream.cache(s,k)">
+ valign=top>wraps a disk-backed read cache keyed on <i>k</i>
+ around <i>s</i>'s stream
+ </property>
+
+ <property name="ibex.stream.watch(s,f)">
+ returns an object whose stream is drawn from <i>s</i>'s
+ stream, but invokes <i>f(n,d)</i> as it is read from.
+ </property>
+
+ <property name="ibex.stream.parse.xml(s, h)">
+ Use SAX to parse the XML document on stream <i>s</i> with
+ handler <i>h</i>
+ </property>
+
+ <property name="ibex.stream.parse.html(s, h)">
+ Same as <tt>parse.xml()</tt>, but tries to fix broken HTML.
+ </property>
+
+ <property name="ibex.stream.parse.utf8(s)">
+ </property>
+ treat <i>s</i>'s stream as a string encoded as a UTF-8 byte stream and return the string</tr>
+
+ <property name="ibex.stream.homedir">
+ <tt>ibex.stream.tempdir</tt>
+ </property>
+
+ </section>
+
+ <section title="Cryptography">
+
+ <property name="ibex.crypto.rsa(k,s)">
+ <i><font color=red>not implemented yet:</font></i> return a
+ stream which rsa-decrypts stream <i>s</i> with key <i>k</i>
+ </property>
+
+ <property name="ibex.crypto.rc4(k,s)">
+ <i><font color=red>not implemented yet:</font></i> return a
+ stream which rc4-decrypts stream <i>s</i> with key <i>k</i>
+ </property>
+
+ <property name="ibex.crypto.md5(s)">
+ <i><font color=red>not implemented yet:</font></i> immediately
+ MD5-hash stream <i>s</i>
+ </property>
+
+ <property name="ibex.crypto.sha1(s)">
+ <i><font color=red>not implemented yet:</font></i> immediately
+ SHA1-hash stream <i>s</i>
+ </property>
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Traps">
+
+ <section title="Simple Traps">
+
+ You can add a trap to a property by applying the <tt>++=</tt> operator
+ to a function with one argument. The trap will be invoked whenever
+ that property is written to.
+
+ <pre>
+ <box>
+ foo ++= function(z) {
+ ibex.log.info("foo is " + z);
+ }
+ </box>
+ </pre>
+
+ If another script were to set the property <tt>"foo"</tt>
+ on the box above to the value <tt>5</tt>, the function above would be
+ invoked with the argument <tt>5</tt>. The function would then log
+ the string <tt>"foo is 5"</tt>.
+
+ Within a trap, the expression <tt>trapee</tt> can be used to
+ get a reference to the box on which the trap was placed.
+
+ The expression <tt>trapname</tt> returns the name of the
+ trap executing the current function. This is useful when a function
+ is applied to multiple traps. For example:
+
+ <pre>
+ <box>
+ func ++= function(z) {
+ ibex.log.info("called trap " + trapname);
+ }
+ foo ++= func;
+ bar ++= func;
+ </box>
+ </pre>
+
+ </section>
+
+ <section title="Removing Traps">
+
+ You can remove a trap by using the <tt>--=</tt> operator with the same
+ function you added as a trap:
+
+ <pre>
+ <box>
+ var myfunc = function(z) { /* ... */ }
+ // add the trap
+ func ++= myfunc;
+ // ...
+ // remove the trap
+ func --= myfunc;
+ </box>
+ </pre>
+
+ </section>
+
+ <section title="Multiple Traps on the Same Property">
+
+ When the property is <i>written</i> to, each of the trap functions placed
+ on it will be invoked in the opposite order that they were placed on
+ the box -- the most recently placed trap will execute first. This
+ last-to-first execution of traps is called <i>cascading</i>. After the
+ last trap is invoked, the value is stored on the box (remember, boxes
+ are objects, so they can hold properties just like all other
+ ECMAscript objects).
+
+ </section>
+
+ <section title="Manual Cascades">
+
+ There are two additional tricks you can use when placing traps. The
+ first is a <i>manual cascade</i>. If you want to cascade to lower
+ traps in the middle of a function, or you want to cascade with a
+ different value than the value passed to you (in effect "lying" to
+ lower traps), you can use <tt>cascade</tt>. For example:
+
+ <pre>
+ <box color="black">
+ color ++= function(c) {
+ ibex.log.info("refusing to change colors!");
+ cascade = "black";
+ }
+ </box>
+ </pre>
+
+ This effectively creates a box whose color cannot be changed, and
+ which complains loudly if you try to do so.
+
+ Do <i>not</i> try to do something like this:
+
+ <pre>
+ <box color="black">
+ color ++= function(z) {
+ color = "black"; // INFINITE LOOP! BAD!!!
+ }
+ </box>
+ </pre>
+ To prevent automatic cascading, return <tt>true</tt> from your function:
+
+ <pre>
+ <box color="black">
+ color ++= function(z) {
+ return true; // the box's color will not change
+ }
+ </box>
+ </pre>
+
+ </section>
+
+ <section title="Read Traps">
+
+ The other trick is a <i>read-trap</i>. Read traps are just like normal
+ traps, except that you use a function that takes zero arguments instead of one. Read traps
+ also do not automatically cascade.
+
+ <pre>
+ <box>
+ doublewidth <tt>++=</tt> function() { return 2 * width; }
+ </box>
+ </pre>
+
+ If another script attempts to read from the <tt>doublewidth</tt>
+ property on this box, the value it gets will be twice the actual width
+ of the box. Note that
+ the actual <tt>doublewidth</tt> property on the box never gets written
+ to, since the trap does not cascade.
+
+ You can manually cascade on read traps as well:
+
+ <pre>
+ <box>
+ text <tt>++=</tt> function() { return "my text is " + cascade; }
+ </box>
+ </pre>
+
+ Read traps are only rarely needed -- most of the time a write trap
+ should be enough.
+
+ </section>
+
+ <section title="Prohibited Traps">
+
+ To prevent confusing and hard-to-debug behaviors, scripts may not
+ place traps on any of the properties described in the sections
+ <link section="Box Layout Properties"/>, <link
+ section="Child-Control Properties"/>, or <link section="Other Box
+ Properties"/> except for <tt>childadded</tt>,
+ <tt>childremoved</tt> and <tt>surface</tt>. <font
+ color=red>FIXME: remove?</font>
+
+ </section>
+
+ <section title="Exceptions and Traps ">
+
+ If an uncaught exception is thrown from a trap, Ibex will log the
+ exception, but will <i>not</i> propagate it to the code which
+ triggered the trap. If the trap was a read trap, the value
+ <tt>null</tt> will be returned.
+ <font color=red>FIXME: is this right?</font>
+
+ </section>
+
+ <section title="Architectural Significance of Traps">
+
+ Traps are the backbone of Ibex. Since almost all UI programming is
+ event/demand driven, traps eliminate the need for separate
+ member/getter/setter declarations, often cutting the amount of typing
+ you have to do to a third of what it would normally be.
+
+ </section>
+
+ <section title="Cloning">
+
+ <I>Cloning</i> is a companion technique for traps; together they can
+ be used to simulate any sort of environment you might need. When you
+ call <tt>ibex.clone(o)</tt>, Ibex returns a new object (called the
+ <i>clone</i>) which compares with equality (<tt>==</tt>) to the
+ original object. Furthermore, both objects are "equal" as keys in
+ hashtables, so:
+
+ <pre>
+ var hash = {};
+ var theclone = ibex.clone(o);
+ hash[o] = 5;
+ ibex.log.info(hash[theclone]); // prints "5"
+ </pre>
+
+ Any writes to properties on the clone will actually write to
+ properties on the original object, and reads from properties on the
+ clone will read properties on the original object. In fact, the only
+ thing that can be used to distinguish the original from the clone is
+ traps -- a trap placed on the clone is <i>not</i> placed on the
+ original object as well.
+
+ </section>
+
+ <section title="Ibex self-emulation">
+
+ When the core first starts up, it clones the <tt>ibex</tt> object,
+ creates a stream for the initial .ibex, and then places a trap on the
+ cloned <tt>ibex</tt> object so that its empty-string property returns
+ the .ibex stream. The cloned Ibex object is then passed as the third
+ (optional) argument to <tt>ibex.apply()</tt>, making it the default
+ <tt>ibex</tt> object for the scripts that are executed as part of the
+ template instantiation.
+
+ <pre>
+ var new_ibex = ibex.clone(ibex);
+ var stream = ibex.bless(ibex.stream.url("http://..."));
+ new_ibex[""] ++= function() { return stream; }
+ ibex.apply(ibex.box, new_ibex..main, new_ibex);
+ </pre>
+
+ Note that we called <tt>ibex.bless()</tt> on the stream before tacking
+ it on to the new Ibex object. The bless function returns a clone of
+ the object passed to it, with a few traps which are explained below.
+ Additionally, any sub-streams retrieved by accessing properties of the
+ blessed stream will also automatically be blessed (blessed streams are
+ <i>monadic</i>).
+
+ Blessing a stream serves three purposes:
+
+ <list type="unordered">
+
+ Blessed clones always return the appropriate static block when
+ their empty property is accessed; this ensures that references
+ to the static blocks of other templates work properly.
+
+ Blessed substreams can return their parent stream by accessing
+ a hidden property which is reserved for internal use by Ibex.
+ This ensures that Ibex can automatically add filename
+ extensions where needed, according to the following rules:
+
+ If the stream is a template to be applied, the string
+ <tt>".ibex"</tt> is appended.
+
+ If the stream is an image, the string <tt>".png"</tt> is
+ appended. If no stream is found, <tt>".jpeg"</tt> and
+ <tt>".gif"</tt> are tried, in that order.
+
+ If the stream is an font, the string <tt>".ttf"</tt> is
+ appended.
+
+ Every call to <tt>ibex.bless()</tt> returns a different object
+ (which happens to be a clone of the object passed to it) with
+ a completely separate set of static blocks.
+
+ </list>
+
+ Ibex can self-emulate by using <tt>ibex.clone()</tt> on the Ibex object;
+ this technique is very similar to the use of ClassLoaders in
+ Java. This is useful for a number of applications, including
+ debuggers, IDEs, sandboxing untrusted code, remote-control, and
+ others. For example:
+
+ <pre>
+ var newLoadFunction = function(url) { /* ... */ };
+ var new_ibex = ibex.clone(ibex);
+ new_ibex.load ++= function() { return newLoadFunction; }
+ ibex.apply(ibex.box, .main, new_ibex);
+ </pre>
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Contexts and Threading">
+
+ <section title="Contexts">
+
+ From the perspective of an application writer, Ibex is strictly
+ single-threaded. Ibex is always in exactly one of the following three
+ <i>contexts</i>:
+
+ <list type="unordered">
+
+ <b>Rendering Context</b> (redrawing the screen)
+
+ <b>Event Context</b> (executing javascript traps triggered by an event)
+
+ <b>Thread Context</b> (executing a background thread spawned with <tt>ibex.thread</tt>)
+
+ </list>
+
+ There are two important restrictions on what can be done in particular contexts:
+
+ <list type="unordered">
+
+ The <tt>box.mouse</tt> property and its subproperties
+ (<tt>x</tt>, <tt>y</tt>, and <tt>inside</tt>) can only be read
+ from within the Event Context, or in a thread context
+ <i>after</i> a the <tt>box.mouse</tt> property on this box or
+ an ancestor box has been written to.
+
+ Blocking operations (anything that accesses the network or
+ disk) can only be performed in the Thread Context.
+
+ </list>
+
+ </section>
+
+ <section title="Background Threads">
+
+ Ibex offers easy access to threads. Spawning a background thread is as
+ simple as writing a function to the <tt>ibex.thread</tt> property:
+
+ <pre>
+ ibex.thread = function() {
+ ibex.log.info("this is happening in a background thread!");
+ }
+ </pre>
+
+ The argument set passed to the function is currently undefined and is
+ reserved for use in future versions of Ibex. Scripts should not
+ depend on the number or content of these arguments.
+
+ Ibex is <i>cooperatively multitasked</i>, so threads must not process
+ for too long. This was a deliberate choice; cooperatively
+ multitasked environments do not require complex locking primitives
+ like mutexes and semaphores which are difficult for novices to
+ understand. The disadvantage of cooperative multitasking is that one
+ thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
+ first, all blocking I/O operations <i>automatically</i> yield the CPU,
+ so the overall user interface never becomes unresponsive because it is
+ waiting for a disk or network transfer. Second, since Ibex is strictly
+ a user interface platform, Ibex scripts are unlikely to perform highly
+ compute-intensive operations that keep the CPU busy for more than a
+ few milliseconds.
+
+ </section>
+
+ <section title="Events">
+
+ Every execution of the Event Context begins with an event, which
+ consists of a key/value pair, and a mouse position, which consists of
+ an x and y coordinate. The possible keys are <tt>_Press[1-3]</tt>,
+ <tt>_Release[1-3]</tt>, <tt>_Click[1-3]</tt>, <tt>_DoubleClick[1-3]</tt>,
+ <tt>_Move</tt>, <tt>_KeyPressed</tt>, and <tt>_KeyReleased</tt>.
+
+ Here are two example events:
+
+ An event is triggered by writing the key to the value on a box. This
+ triggers any trap handlers which may be present. Once these handlers
+ have executed, Ibex figures out which child of the current box contains
+ the mouse (taking into account that some boxes may cover up others)
+ and writes the key and value to that box. If none of the box's
+ children contain the mouse position, Ibex removes the leading
+ underscore from the key name and writes the value to
+ <i>that</i> property. Once all the traps on that property have
+ executed, the value is written to the box's parent.
+
+ Intuitively, Ibex delivers the underscored event to every box from the
+ root to the target, and then delivers the non-underscored event to
+ that same set of boxes in reverse order. So the event travels down
+ the tree to the target, and then back up to the root. The following
+ example prints out "first second third fourth" in that order.
+
+ <pre>
+ <box>
+ _Press1 ++= function(b) { ibex.log.info("first"); }
+ Press1 ++= function(b) { ibex.log.info("fourth"); }
+ <box>
+ _Press1 ++= function(b) { ibex.log.info("second"); }
+ Press1 ++= function(b) { ibex.log.info("third"); }
+ </box>
+ </box>
+ </pre>
+
+ In general, you should use the <i>non-underscore</i> names to respond
+ to user input and use the underscored names when you want to override
+ child boxes' behavior or route events to particular boxes (for
+ example, when implementing a focus protocol). This is why the
+ underscored elements are delivered to parents before children (so
+ parents can override their childrens' behavior), but non-underscored
+ events are delivered to children before parents (since, visually, a
+ mouse click is usually "intended" for the leaf box underneath the
+ cursor).
+
+ </section>
+
+ <section title="Stopping the Process">
+
+ At any point in this sequence, a trap handler can choose not to
+ cascade (by returning <tt>true</tt> from the trap handler function).
+ This will immediately cease the propagation of the event. This is how
+ you would indicate that an event has been "handled".
+
+ </section>
+
+ <section title="Re-routing events">
+
+ At any point in the Event Context, you can write to the <tt>mouse</tt>
+ property on any box. The value written should be an object with two
+ properties, <tt>x</tt> and <tt>y</tt>. For example:
+
+ <pre>
+ _Press1 ++= function(p) {
+ mouse = { x: 32, y: 77 };
+ }
+ </pre>
+
+ The coordinates specified are relative to the box whose <tt>mouse</tt>
+ property is being written to. There is no need to supply the
+ <tt>inside</tt> property; it is computed automatically. Writing to
+ the <tt>mouse</tt> property causes Ibex to recompute the eventual
+ target box, and also alter the values returned by <tt>mouse.x</tt>,
+ <tt>mouse.y</tt>, and <tt>mouse.inside</tt> for any <i>descendants</i>
+ of the current box. Writing to the <tt>mouse</tt> property also
+ automatically prevents the event from returning to the box's parents
+ -- it is equivalent to not cascading on the non-underscored event.
+ This ensures that child boxes cannot trick their parent boxes into
+ thinking that the mouse has moved.
+
+ If you want the event to "skip over" the boxes between the trapee
+ and the target, or if you want to re-route an event to a box which
+ is not a descendant of the current box, simply write the value to
+ the proper key on the target box.
+
+ <pre>
+ <box>
+ _KeyPressed = function(k) { ibex.log.info("first"); }
+ KeyPressed = function(k) { ibex.log.info("sixth"); }
+ $recipient.target = $target;
+ <box id="recipient">
+ _KeyPressed = function(k) {
+ ibex.log.info("second");
+ thisbox.target.KeyPressed = k;
+ // inhibit cascade to keep the event from going to $excluded
+ return true;
+ }
+ KeyPressed = function(k) { ibex.log.info("fifth"); }
+ <box id="excluded">
+ _KeyPressed = function(k) { ibex.log.info("this never happens"); }
+ </box>
+ </box>
+ <box id="target">
+ _KeyPressed = function(k) { ibex.log.info("third"); }
+ KeyPressed = function(k) { ibex.log.info("fourth"); }
+ </box>
+ </box>
+ </pre>
+
+ </section>
+
+ <section title="Synthesizing Your Own Events">
+
+ You can create "fake events" by simply writing to the <tt>mouse</tt>
+ property and then writing a value to one of the underscored properties
+ on a box. This will have exactly the same effect as if the use had
+ actually pressed a key, clicked a button, or moved the mouse -- they
+ are indistinguishable.
+
+ </section>
+
+ <section title="Enter and Leave">
+
+ Ibex will trigger the <tt>Enter</tt> and <tt>Leave</tt> properties as
+ it walks down the tree, based on the position of the mouse (or the
+ faked position if the <tt>mouse</tt> property has been written to).
+ However, <tt>Enter</tt> and <tt>Leave</tt> are not events since they
+ do not implicitly cascade up or down the tree.
+
+ </section>
+
+ <section title="Detailed Description of Events">
+
+ <property name="Press1 / Press2 / Press3">
+ Indicates that the use has pressed a mouse button. On
+ platforms with three mouse buttons, the <i>middle</i> button
+ is button 3 -- this ensures that applications written to only
+ use two buttons (1 and 2) will work intuitively on three button
+ platforms.
+ </property>
+
+ <property name="Release1 / Release2 / Release3">
+ Indicates that the use has released a mouse button.
+ </property>
+
+ <property name="Click1 / Click2 / Click3">
+ Indicates that the user has pressed and released the
+ mouse button without moving the mouse much (exactly how
+ much is platform-dependent).
+ </property>
+
+ <property name="DoubleClick1 / DoubleClick2 / DoubleClick3">
+ Indicates that the user has clicked the
+ mouse button twice within a short period of time (exactly how long is platform-dependent).
+ </property>
+
+ <property name="Move">
+ Indicates that the mouse has moved while within this box, or that
+ the mouse while outside this box <i>if a button was pressed while within this box and has not yet been released</i>
+ </property>
+
+ <property name="KeyPressed KeyReleased">
+ A string is written to this property when a key is pressed or
+ released If the key was any other key, a multi-character
+ string describing the key will be put. For simplicity, we use
+ the VK_ constants in the <link
+ url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
+ text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
+ key is pressed or released, the string put will be the portion
+ of its VK_ constant after the underscore, all in lower case.
+ If the shift key was depressed immediately before the event
+ took place, then the string will be capitalized. Special
+ keynames are also capitalized; shift+home is reported as
+ "<tt>HOME</tt>". Symbols are capitalized as they appear on the
+ keyboard; for example, on an American QWERTY keyboard, shift+2
+ is reported as "<tt>@</tt>". If the alt, meta, or command key
+ was depressed immediately before this key was pressed, then
+ the string will be prefixed with the string "<tt>A-</tt>". If
+ the control key was depressed while this key was pressed, then
+ the string will be prefixed with the string "<tt>C-</tt>". If
+ both alt and control are depressed, the string is prefixed
+ with "<tt>C-A-</tt>". Ibex does not distinguish between a key
+ press resulting from the user physically pushing down a key,
+ and a 'key press' resulting from the keyboard's typematic
+ repeat. In the rare case that an application needs to
+ distinguish between these two events, it should watch for
+ KeyReleased messages and maintain an internal key-state
+ vector.
+ </property>
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Networking">
+
+ <section title="XML-RPC">
+
+ XML-RPC objects can be created by calling <tt>ibex.net.rpc.xml(<<i>XML-RPC
+ URL</i>>)</tt>, and then invoking methods on that object. For example,
+
+ <pre>
+ Press1 += function(v) {
+ ibex.thread = function() {
+ color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").color.getTodaysColor("Friday");
+ }
+ }
+ </pre>
+
+ When the user clicks the first mouse button on this box, it will
+ contact the server <tt>xmlrpc.ibex.org</tt>, route to the
+ <tt>/RPC2/</tt> handler and invoke the <tt>getTodaysColor()</tt>
+ method on the <tt>color</tt> object with a single string argument
+ <tt>"Friday"</tt>. The return value will be used to change the color
+ of the box the user clicked on.
+
+ Note that in this example we spawned a background thread to handle the
+ request -- the <tt>Press1</tt> event is delivered in the foreground
+ thread, and XML-RPC methods may only be invoked in background
+ threads. This is to prevent the UI from "locking up" if the server
+ takes a long time to reply.
+
+ If the XML-RPC method faults, an object will be thrown with two
+ properties: <tt>faultCode</tt> and <tt>faultString</tt>, as defined in
+ the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
+ Ibex encounters a network, transport, or session-layer error, it will
+ throw a <tt>String</tt> object describing the error in a
+ human-readable format. Scripts should not rely on the contents of
+ this string having any special structure or significance.
+
+ If an object with an associated non-empty stream is passed as an
+ argument to an XML-RPC method, it will be sent as a <base64>
+ element. If a <base64> element is found in the XML-RPC reply, it
+ will be returned as an object with a stream drawn from that byte sequence.
+
+ Each object returned by <tt>ibex.net.rpc.xml()</tt> represents a
+ single HTTP connection. The connection will be held open until
+ the object is garbage collected or the server closes the
+ connection. If a second call is issued on the object before the
+ first one returns (usually from a seperate thread), the two calls
+ will be <link
+ url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
+ text="pipelined"/>. This can dramatically improve performance.
+
+ Ibex supports HTTP Basic and Digest authentication. To use
+ authentication, pass <tt>ibex.net.rpc.xml()</tt> a URL in the form
+ <tt>http[s]://user:password@hostname/</tt>. Ibex will use Digest
+ authentication if the server supports it; otherwise it will use
+ Basic authentication. Please be aware that many XML-RPC server
+ implementations contain a <link
+ url="http://www.ibex.org/faq.html#auth" text="broken implementation
+ of Basic authentication"/>.
+
+ </section>
+
+ <section title="SOAP">
+
+ SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
+
+ <list type="ordered">
+
+ <tt>ibex.net.rpc.soap()</tt> is used instead of
+ <tt>ibex.net.rpc.xml()</tt>
+
+ Instead of specifying just the URL of the service itself, you
+ must specify the URL, the SOAPAction argument, and the
+ namespace to use.
+
+ The actual method invocation takes only one argument, which
+ must be an object. This is necessary since SOAP arguments are
+ specified by name, rather than ordering.
+
+ </list>
+
+ SOAP faults are handled the same way as XML-RPC faults except that the
+ capitalization of the <tt>faultstring</tt> and <tt>faultcode</tt>
+ members is all lower-case, to match the SOAP spec. Here is a
+ SOAP example:
+
+ <pre>
+ Press1 ++= function(v) {
+ ibex.thread = function() {
+ color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP", // endpoint
+ "GETTODAYSCOLOR", // SOAPAction header
+ "http://ibex.org/namespace" // namespace for SOAP-ENV
+ ).color.getTodaysColor( {
+ whichday : Friday
+ } );
+ }
+ }
+ </pre>
+
+ As you can see, SOAP is much more verbose, yet does not offer
+ substantially improved functionality. We recommend that XML-RPC be
+ used whenever possible, and that SOAP be reserved for legacy
+ applications.
+
+ The current Ibex SOAP stack does not support 'document style' or
+ multi-ref (<tt>href</tt>) data structures.
+
+ </section>
+
+ <section title="Security">
+
+ Applications downloaded from the network (as opposed to those loaded
+ from the filesystem) may only make certain kinds of connections to
+ certain hosts. See Appendix A for a detailed description of the
+ security policy.
+
+ </section>
+
+ </section>
+<!-- ----------------------------------------------------------------------- -->
+<section title="Error Handling">
+
+ If the Ibex Core encounters an error while servicing a function call
+ originating in JavaScript, the core will throw a string consisting of
+ an error code followed by a colon, a space, and a descriptive message.
+ For example:
+
+ <pre>
+ "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
+ </pre>
+
+ The code should be used to determine how the program should respond to
+ an error. The codes are organized in a hierarchy, so the
+ string.startsWith() method can be used to determine if an error lies
+ within a particular subhierarchy. The descriptive message portion of
+ the string may be shown to the user.
+
+ <property name="ibex.assertion.failed">
+ an assertion failed
+ </property>
+ <property name="ibex.io">
+ General I/O exceptions
+ </property>
+ <property name="ibex.io.encoding">
+ Error translating between character encodings.
+ </property>
+ <property name="ibex.io.zip">
+ Attempted to access a corrupt zip archive.
+ </property>
+ <property name="ibex.io.eof">
+ End of file encountered unexpectedly
+ </property>
+ <property name="ibex.net.security.prohibitedHost">
+ A piece of untrusted Ibex code attempted to contact a
+ restricted host. See Appendix A for details.
+ </property>
+ <property name="ibex.net.dns.temporaryFailure">
+ An attempt to resolve a hostname failed but it is not known
+ for certain that the hostname is invalid.
+ </property>
+ <property name="ibex.net.dns.unknownHost">
+ An attempt to resolve a hostname failed because the hostname
+ was invalid.
+ </property>
+ <property name="ibex.net.socket.closed">
+ A socket was closed unexpectedly.
+ </property>
+ <property name="ibex.net.socket.connectionFailed">
+ A connection could not be made to the remote host.
+ </property>
+ <property name="ibex.net.url.malformed">
+ Tried to parse a malformed URL.
+ </property>
+ <property name="ibex.net.ssl">
+ General SSL protocol errors.
+ </property>
+ <property name="ibex.net.ssl.untrustedCertificate">
+ The server's certificate was not signed by a CA trusted by Ibex.
+ </property>
+ <property name="ibex.net.http.">
+ Thrown when an HTTP error code is returned during an
+ operation. The three characters <tt><i>xyz</i></tt> will be
+ the three-digit HTTP status code.
+ </property>
+ <property name="ibex.net.xmlrpc.null">
+ The caller attempted to transmit the <tt>null</tt> value via XML-RPC.
+ </property>
+ <property name="ibex.net.xmlrpc.circular">
+ The caller attempted to transmit a circular data structure via XML-RPC.
+ </property>
+ <property name="ibex.net.xmlrpc.specialObject">
+ The caller attempted to transmit a "special" object via
+ XML-RPC (for example, a Box or the Ibex object).
+ </property>
+ <property name="ibex.null.put">
+ A JavaScript attempted to put to a property on the <tt>null</tt> value
+ </property>
+ <property name="ibex.null.get">
+ A JavaScript attempted to get from a property on the <tt>null</tt> value
+ </property>
+ <property name="ibex.null.call">
+ A JavaScript attempted to call the <tt>null</tt> value
+ </property>
+ </table>
+
+ If an exception is thrown inside a trap, the exception will propagate
+ to the script that triggered the trap.
+
+ If an uncaught exception is thrown while applying a template, or the
+ requested template could not be found, an error will be logged and the
+ box to which the template was being applied will be made invisible
+ (<tt>visible = false</tt>). This ensures that half-applied widgets are
+ never shown to the user.
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="A: Security Architecture and Considerations">
+
+ Due to the expense and hassle imposed by the commercial PKI code
+ signing architecture, and the fact that it <link
+ url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
+ really provide any security anyways"/>, Ibex user interfaces are
+ distributed as unsigned, untrusted code. As such, they are handled
+ very carefully by the Ibex Core, and assumed to be potentially
+ malicious.
+
+ Ibex's security architecture is divided into defenses against four
+ major classes of attacks:
+
+ <section title="Malicious UI attempts to acquire or alter data on the client">
+
+ Ibex user interfaces are run in an extremely restrictive sandbox. The
+ environment does not provide primitives for accessing any data outside
+ the Ibex core except via XML-RPC and SOAP calls. There are no
+ facilities to allow Ibex user interfaces to access the client's
+ operating system or to interact with other applications on the same
+ host (unless they provide a public XML-RPC or SOAP interface).
+ An Ibex script may only access a file on the user's hard disk if the
+ user explicitly chooses that file from an "open file" or "save file"
+ dialog. There is one exception to this rule: if all templates
+ currently loaded in the Ibex core originated from the local
+ filesystem, those templates can load additional .ibexs from the local
+ filesystem.
+
+ The Ibex Core is written in Java, so it is not possible for
+ scripts to perform buffer overflow attacks against the core
+ itself.
+
+ Ibex applications may only read from the clipboard when the user
+ middle-clicks (X11 paste), presses control-V (Windows paste), or
+ presses alt-V (Macintosh paste; the command key is mapped to Ibex
+ "alt"). This ensures that Ibex applications are only granted access to
+ data that other applications have placed on the clipboard when the user
+ specifically indicates that that information should be made available
+ to the Ibex application.
+
+ </section>
+
+ <section title="Malicious UI attempts to use client to circumvent firewalls">
+
+ Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
+ archives via HTTP; they cannot execute arbitrary HTTP GET's or open
+ regular TCP sockets.
+
+ Ibex will not allow a script to connect to a non-public IP address
+ (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
+ url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
+ 1918"/>). There is one exception -- if all templates currently loaded
+ in the core originated from the same IP address, those scripts may
+ make calls to that IP address regardless of whether or not it is
+ firewalled. If Ibex does not have access to a DNS resolver (because it
+ is using a proxy which performs DNS lookups), Ibex will provide the
+ proxy with the appropriate <link
+ url="http://www.ibex.org/x-requestorigin.html"
+ text=""/>X-RequestOrigin</tt></a> header that the proxy needs in order
+ to maintain security.
+
+ The only remaining possible attack is against a XML-RPC or SOAP
+ service running on a firewalled host with a public address. Assigning
+ such machines public IP addresses is a poor network security policy,
+ and doing so squanders scarce public IPv4 addresses. As such, the onus
+ is on the administrators of such machines to explicitly block access
+ to clients reporting a <tt>User-Agent:</tt> header beginning with the
+ three characters "<tt>Ibex</tt>".
+
+ </section>
+
+ <section title="Malicious UI attempts to trick user into divulging secret information">
+
+ All top-level windows created by Ibex are <i>scarred</i> -- a stripe
+ and a lock is drawn across the corner of the window. There is no way
+ for a user interface to remove this scar. Ibex user interfaces may not
+ create windows smaller than the size of the scar.
+
+ </section>
+
+ <section title="Malicious network attempts to snoop or man-in-the-middle transactions">
+
+ Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
+ for encryption. Ibex will attempt 128-bit encryption, but will
+ negotiate down to 40-bit if the server does not support strong
+ crypto. Ibex's SSL implementation is currently provided by <link
+ url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
+ url="http://www.bouncycastle.org" text="The Legion of the Bouncy
+ Castle."/>
+
+ All HTTPS connections must be authenticated by the server using a
+ certificate whose name matches the domain name of the HTTPS URL. The
+ certificate must be signed by a trusted root CA. Ibex trusts the same
+ 93 root CAs whose certificates are included as "trusted" in Microsoft
+ Internet Explorer 5.5 SP2. This provides a minimal level of protection
+ against man-in-the-middle attacks; you should not trust this
+ connection with any data you would not normally trust an SSL-enabled
+ web browser with.
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="B: ECMAscript compliance">
+
+ Ibex's scripts are written in a modified subset of ECMA-262, revision 3
+ (aka JavaScript 1.5). The interpreter strays from the spec in a few
+ ways.
+
+ <section title="Omissions">
+
+ The following ECMA features are not supported:
+
+ <list type="unordered">
+
+ The <tt>undefined</tt> value, <tt>===</tt>, and <tt>!==</tt>
+
+ The <tt>new</tt> keyword (and ECMAScript object inheritance)
+ <tt>eval</tt>
+
+ <tt>getter</tt> and <tt>setter</tt>
+
+ The ECMA <tt>this</tt> keyword.
+
+ The <tt>String</tt>, <tt>Number</tt>, and <tt>Boolean</tt>
+ classes. Note that <tt>string</tt>, <tt>number</tt>, and
+ <tt>boolean</tt> values are supported, however.
+
+ You may not <tt>throw</tt> the <tt>null</tt> value.
+
+ </list>
+
+ Additionally, you must declare all root-scope variables (with
+ <tt>var</tt>) before using them; failure to do so will result in an
+ exception. Box properties are pre-defined in the scope that scripts
+ are executed in.
+
+ </section>
+
+ <section title="Extensions">
+
+ <list type="unordered">
+
+ The token <tt>..</tt> is equivalent to <tt>[""]</tt>.
+
+ Trapping
+
+ Cloning
+
+ Extended <tt>catch</tt> syntax. The following code:
+ <pre>
+ } catch(e propname "foo.bar.baz") {
+ // ...
+ }
+ </pre>
+ Is equivalent to:
+ <pre>
+ } catch(e) {
+ if (e.propname != null && e.propname >= "foo.bar.baz" && e.propname < "foo.bar.baz/") {
+ // ...
+ }
+ }
+ </pre>
+ Multiple extended-catch blocks can appear at the end of a single try
+ block. However, at most one non-extended catch block may appear, and
+ if it does appear, it must be the last one.
+
+ Since Ibex ECMAscripts are wrapped in XML, the lexical token
+ "<tt>lt</tt>" is be interpreted as <tt><</tt>, the lexical
+ token "<tt>gt</tt>" is be interpreted as <tt>></tt>, and the
+ token "<tt>and</tt>" is interpreted as <tt>&&</tt>.
+ Thus these tokens cannot be used as variable names.
+
+ The identifier <tt>static</tt> is a reserved word in
+ ECMAScript, but not in Ibex.
+
+ Ibex defines an additional reserved word, "<tt>assert</tt>",
+ which will evaluate the expression which follows it, throwing
+ a <tt>ibex.assertion.failed</tt> exception if the expression
+ evaluates to <tt>false</tt>.
+
+ To ensure that Ibex files appear the same in all text editors, tab
+ characters are not allowed in Ibex files.
+
+ </list>
+
+ Some useful tutorials include:
+
+ <list type="unordered">
+
+ Netscape's <link
+ url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
+ text=" JavaScript 1.2 Reference"/>. Although this document is
+ out of date, it is arguably the best guide available for free
+ on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
+ r1) to 1.5 were minimal, and many of them were <link
+ url="ecmascriptcompliance" text="omitted"/> from Ibex.
+
+ O'Reilly's <link
+ url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
+ text=" JavaScript: The Definitive Guide"/>, by David Flanagan
+ and Paula Ferguson. The latest edition of this book covers
+ JavaScript 1.5 (ECMA-262 r3).
+
+ The official <link
+ url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
+ text="ECMA-262"/> specification. This is an extremely
+ technical document.
+
+ </list>
+
+ </section>
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+<section title="C: Logging and Command Line Invocation">
+
+ Very early in the loading process, Ibex begins logging messages about
+ what it is doing. Where this output is logged to differs by platform;
+ currently it goes to standard output when running inside a JVM, and to
+ <tt>$TMPDIR\ibex-log.txt</tt> on Win32 (where <tt>$TMPDIR</tt> is the
+ value returned by <tt>GetTempPath()</tt>). The logs contain a lot of
+ valuable debugging information and performance hints; if you are
+ having trouble developing an Ibex application, be sure to check the
+ logs.
+
+ If Ibex encounters a serious problem before it starts logging
+ information, or if it is unable to open the log file, it will abort
+ immediately with a critical abort, which will be displayed on the
+ console for POSIX-native cores and in a dialog box for JVM-based and
+ Win32-native cores.
+
+ You can invoke Ibex directly from the command line during
+ development. When using a JVM, the invocation format is:
+
+ <pre>
+ java -jar <i>path-to-ibex-jar</i> [-sv] <i>source-location</i> [<i>initial-template</i>]
+ </pre>
+
+ Where <tt><i>path-to-ibex-jar</i></tt> is the path to <tt>ibex.jar</tt>,
+ which can be downloaded <link url="http://www.ibex.org/dist/ibex.jar" text="here"/>.
+
+ On Win32, the invocation format is:
+
+ <pre>
+ ibex.exe [-v] <i>source-location</i> [<i>initial-template</i>]
+ </pre>
+
+ The file <tt>ibex.exe</tt> is placed in Windows' ActiveX cache
+ directory the first time Ibex is used on the machine. The ActiveX
+ cache location depends on what version of Windows you are using;
+ on newer versions of Windows it is <tt>C:\WINDOWS\DOWNLOADED
+ PROGRAM FILES\</tt>. You can also extract <tt>ibex.exe</tt> from
+ <tt>ibex.cab</tt>, which is available <link
+ url="http://www.ibex.org/dist/ibex.cab" text="here"/>.
+
+ The <tt><i>source-location</i></tt> parameter can be either the path
+ to an .ibex archive, the http url of an .ibex archive, or the path to a
+ directory comprising an unpacked .ibex archive.
+
+ The <tt><i>initial-template</i></tt> parameter is the stream name of
+ a template to be used as the initial template. If ommitted, it
+ defaults to <tt>main</tt>.
+
+ The <tt>-v</tt> option causes Ibex to enable verbose logging; this will
+ cause it to log <i>lots</i> of information to the log file. This
+ option will also substantially decrease Ibex's performance.
+
+ </section>
+
+<!-- ----------------------------------------------------------------------- -->
+ <!--
+<section title="E: Grammars">
+
+ <font color=red><i>Grammar support is experimental in this release
+ and may not work properly. It may change in incompatible ways or
+ disappear completely from future releases</i></font>
+
+ Grammars are defined with a statement in the following form:
+
+ <pre>
+ a ::= b { c }
+ </pre>
+ A grammar is really just another function; once defined you can't tell
+ it apart from an ordinary function. A grammar takes one argument,
+ which can be a string or stream. The argument is parsed and the
+ result of executing the code block 'c' is returned.
+
+ The property 'a' is read; if the value is a grammar, a new production
+ rule (ie a new alternative, as with '<tt>|</tt>') is added to that grammar
+ (this is a destructive update). This allows you to add productions to
+ pre-existing grammars (for example, adding a new type of expression to
+ a programming language by extending the 'expr' grammar). If the old
+ value is not a grammar, the value is discarded and a new grammar
+ object is created.
+
+ The value 'b' is a pattern, which may consist of seven simple
+ primitives:
+
+ <list type="unordered">
+ string literals
+
+ grouping parens <tt>()</tt>
+
+ combinators: <tt> | + * ?</tt>
+
+ references to other grammars
+ </list>
+
+ The value 'c' and the braces surrounding it are an *optional* code
+ block, in which the following identifiers are bound:
+
+ <list type="unordered">
+
+ The identifier 'whole' is bound to the string matched by the
+ entire expression. If the code block is omitted it behaves
+ as if it were <tt>"{ return whole; }"</tt>.
+
+ For every reference to another grammar which was matched in the
+ pattern, the *name used to reference that other grammar* will
+ be bound to the value returned by its code block. Here's an
+ example of this important distinction:
+
+ <pre>
+ var foo ::= 'a' | 'b';
+ var bar ::= foo;
+ var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
+ </pre>
+
+ On the last line, the identifier 'bar' serves two purposes: it
+ pulls in the definition of the pattern *and* acts as a binder
+ within the scope of the braces.
+
+ If a reference is matched multiple times (either because it
+ appears multiple times in the pattern or because the * or +
+ operator was applied to it) then its name will be bound to an
+ array containing the matches.
+
+ </list>
+
+ Here is the metacircular definition of the grammar facility:
+
+ <pre>
+ grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
+ identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
+ char ::= '\0x0000'..'\0xffff'
+ literal ::= '\'' char+ '\''
+ | '\'' char '\'' '..' '\'' char '\''
+ pattern ::= identifier
+ | literal
+ | '(' pattern ')'
+ | pattern '+'
+ | pattern '?'
+ | pattern '*'
+ | pattern pattern
+ | pattern '|' pattern
+ </pre>
+ -->
+
+<i>
+Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
+Ibex is a trademark of Adam Megacz
+</i>
+
+</ibex-doc>
\ No newline at end of file