1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534 |
- \input texinfo @c -*-texinfo-*-
- @c %**start of header
- @setfilename iksemel
- @setcontentsaftertitlepage
- @settitle Iksemel Programmers Manual
- @set VERSION 1.2
- @c %**end of header
- @titlepage
- @title iksemel programmers manual
- @subtitle A tutorial and API reference for the iksemel library @value{VERSION}
- @page
- @vskip 0pt plus 1filll
- Copyright @copyright{} 2001-2003 G@"urer @"Ozen
- This is a free document; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or
- (at your option) any later version.You may obtain a copy of the
- GNU General Public License from the Free Software Foundation
- by visiting their Web site or by writing to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
- @end titlepage
- @ifinfo
- @node Top, , , (dir)
- @top iksemel Programmers Manual
- Copyright @copyright{} 2001-2003 G@"urer @"Ozen
- This is a free document; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or
- (at your option) any later version.You may obtain a copy of the
- GNU General Public License from the Free Software Foundation
- by visiting their Web site or by writing to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
- @menu
- * Introduction::
- * Tutorials::
- * Development::
- * Datatype Index::
- * Function Index::
- @end menu
- @end ifinfo
- @node Introduction, Tutorials, ,Top
- @chapter Introduction
- iksemel is an XML (eXtensible Markup Language) parser library
- designed for Jabber applications. It is coded in ANSI C for POSIX
- compatible environments, thus highly portable. It is free software
- released under the GNU Lesser General Public License.
- The purprose of this manual is to tell you how to use the facilities
- of the iksemel library. Manual is written with the assumption that you
- are familiar with the C programming language, basic programming
- concepts, XML and Jabber protocol.
- @section Compiling the Library
- You need to install MinGW (@url{http://mingw.org}) under Windows to be able
- to compile iksemel. Although not tested by the author, Cygwin should
- work equally well.
- Library can be built with:
- @example
- ./configure
- make
- @end example
- If you want to make a self test:
- @example
- make test
- @end example
- Now you can install it with:
- @example
- make install
- @end example
- @section Using iksemel in Applications
- You need to include @file{iksemel.h} file in your source to access library API.
- You can do this with:
- @code{#include "iksemel.h"}
- Now you can use iksemel functions and compile your source. In able to link
- your compiled object files and generate your executable program, you have to
- link with iksemel library. This can be done with:
- @example
- gcc -o myprg src1.o src2.o src3.o -liksemel
- @end example
- iksemel registers itself with pkg-config while installing, so if you are using
- autotools in your program, you can simply check the availability of iksemel
- and configure your build process accordingly with:
- @example
- PKG_CHECK_MODULES(IKSEMEL,iksemel,,exit)
- @end example
- This would result in IKSEMEL_LIBS and IKSEMEL_CFLAGS substitution variables
- set to correct values.
- @node Tutorials,Development,Introduction,Top
- @chapter Tutorials
- @ifinfo
- @menu
- * Parsing an XML Document::
- * Working with XML Trees::
- * XML Streams::
- * Writing a Jabber Client::
- * Utility Functions::
- @end menu
- @end ifinfo
- @comment ============================================================
- @node Parsing an XML Document,Working with XML Trees,,Tutorials
- @section Parsing an XML Document
- iksemel parser sequentally processes the XML document. Each encountered XML
- element (i.e. tags, character data, comments, processing instructions, etc.)
- is reported to your application by calling the hook functions you have provided.
- This type of interface is called SAX (serial access) interface.
- @tindex iksparser
- Parser stores its state in a small structure. This structure is referenced by
- @code{iksparser} type, and managed with following functions:
- @deftypefun iksparser* iks_sax_new (void* @var{user_data}, iksTagHook* @var{tagHook}, iksCDataHook* @var{cdataHook});
- This function allocates and initializes a parser structure. If allocation fails,
- NULL value is returned. @var{user_data} is passed directly to hook functions.
- @end deftypefun
- @deftp Typedef iksTagHook
- int iksTagHook (void* @var{user_data}, char* @var{name}, char** @var{atts}, int @var{type});
- This function is called when a tag parsed. @var{name} is the name of the tag. If tag has
- no attributes @var{atts} is NULL, otherwise it contains a null terminated list of
- pointers to tag's attributes and their values. If return value isn't @code{IKS_OK},
- it is passed immediately to the caller of the @code{iks_parse}.
- @var{type} is one of the following:
- @table @code
- @item IKS_OPEN
- Opening tag, i.e. <tag attr='value'>
- @item IKS_CLOSE
- Closing tag, i.e. </tag>
- @item IKS_SINGLE
- Standalone tag, i.e. <tag attr='value'/>
- @end table
- @end deftp
- @deftp Typedef iksCDataHook
- int iksCDataHook (void* @var{user_data}, char* @var{data}, size_t @var{len});
- @var{data} is a pointer to the character data. Encoding is UTF-8 and it isn't terminated
- with a null character. Size of the data is given with @var{len} in bytes. This function
- can be called several times with smaller sized data for a single string. If
- return value isn't @code{IKS_OK}, it is passed immediately to the caller of the
- @code{iks_parse}.
- @end deftp
- @deftypefun int iks_parse (iksparser* @var{prs}, char *@var{data}, size_t @var{len}, int @var{finish});
- You give XML document to the parser with this function. @var{data}
- is a @var{len} bytes string. If @var{len} is zero, data must be a null
- terminated string.
- If @var{finish} value is zero, parser waits for more data later. If you
- want to finish parsing without giving data, call it like:
- @example
- iks_parse (my_parser, NULL, 0, 1);
- @end example
- You should check the return value for following conditions:
- @table @code
- @item IKS_OK
- There isn't any problem.
- @item IKS_NOMEM
- Not enough memory.
- @item IKS_BADXML
- Document is not well-formed.
- @item IKS_HOOK
- Your hook decided that there is an error.
- @end table
- @end deftypefun
- @deftypefun void iks_parser_delete (iksparser* @var{prs});
- This function frees parser structure and associated data.
- @end deftypefun
- Now we have learned how to create and use a sax parser. Lets parse a simple
- XML document. Write following code into a @file{test.c} file.
- @smallexample
- #include <stdio.h>
- #include <iksemel.h>
- int pr_tag (void *udata, char *name, char **atts, int type)
- @{
- switch (type) @{
- case IKS_OPEN:
- printf ("TAG <%s>\n", name);
- break;
- case IKS_CLOSE:
- printf ("TAG </%s>\n", name);
- break;
- case IKS_SINGLE:
- printf ("TAG <%s/>\n", name);
- break;
- @}
- if (atts) @{
- int i = 0;
- while (atts[i]) @{
- printf (" ATTRIB %s='%s'\n", atts[i], atts[i+1]);
- i += 2;
- @}
- @}
- return IKS_OK;
- @}
- enum ikserror pr_cdata (void *udata, char *data, size_t len)
- @{
- int i;
- printf ("CDATA [");
- for (i = 0; i < len; i++)
- putchar (data[i]);
- printf ("]\n");
- return IKS_OK;
- @}
- int main (int argc, char *argv[])
- @{
- iksparser *p;
- p = iks_sax_new (NULL, pr_tag, pr_cdata);
- switch (iks_parse (p, argv[1], 0, 1)) @{
- case IKS_OK:
- puts ("OK");
- break;
- case IKS_NOMEM:
- puts ("Not enough memory");
- exit (1);
- case IKS_BADXML:
- puts ("XML document is not well-formed");
- exit (2);
- case IKS_HOOK:
- puts ("Our hooks didn't like something");
- exit (2);
- @}
- iks_parser_delete (p);
- return 0;
- @}
- @end smallexample
- Now compile and test it with:
- @example
- gcc -o test test.c -liksemel
- ./test "<test>Hello<br/>World!</test>"
- ./test "<lala a='12' b='42'/>"
- @end example
- @heading Error Handling
- XML standart states that once an error is detected, the processor must not continue
- normal processing (i.e. it must not pass character data or markup information to
- the application). So iksemel stops processing immediately when it encounters a
- syntax error, or one of your hook functions return any one value than @code{IKS_OK},
- and @code{iks_parse} function returns with the error code.
- Since it is useful for debugging, iksemel provides functions to get position of
- the error. Position is usually at the starting character for syntax errors. Since
- your hooks are called after whole element (i.e. markup or character data) is
- passed, position is at the end of the erroneous element for @code{IKS_HOOK} errors.
- @deftypefun {unsigned long} iks_nr_bytes (iksparser* @var{prs});
- Returns how many number of bytes parsed.
- @end deftypefun
- @deftypefun {unsigned long} iks_nr_lines (iksparser* @var{prs});
- Returns how many number of lines parsed.
- @end deftypefun
- If you want to parse another document with your parser again, you should use
- the following function to reset your parser.
- @deftypefun void iks_parser_reset (iksparser* @var{prs});
- Resets the parser's internal state.
- @end deftypefun
- @comment ============================================================
- @node Working with XML Trees,XML Streams,Parsing an XML Document,Tutorials
- @section Working with XML Trees
- SAX interface uses very little memory, but it forces you to access XML
- documents sequentally. In many cases you want to keep a tree like
- representation of XML document in memory and want to access and
- modify its content randomly.
- iksemel provides functions for efficiently creating such trees either
- from documents or programmaticaly. You can access and modify this
- tree and can easily generate a new XML document from the tree.
- This is called DOM (Document Object Model) interface.
- @ifinfo
- @menu
- * Memory Management::
- * Creating a Tree::
- * Accessing the Tree::
- * Converting a Tree into an XML Document::
- * Parsing an XML Document into a Tree::
- @end menu
- @end ifinfo
- @comment ============================================================
- @node Memory Management,Creating a Tree,,Working with XML Trees
- @subsection Memory Management
- Since keeping whole document content uses a lot of memory and requires
- many calls to OS's memory allocation layer, iksemel uses a simple object
- stack system for minimizing calls to the @code{malloc} function and releasing
- all the memory associated with a tree in a single step.
- A parsed XML tree contains following objects:
- @table @samp
- @item Nodes
- These are basic blocks of document. They can contain a tag, attribute pair
- of a tag, or character data. Tag nodes can also contain other nodes as
- children. Node structure has a small fixed size depending on the node type.
- @item Names
- Names of tags and attributes. They are utf-8 encoded small strings.
- @item Character Data
- They are similar to names but usually much bigger.
- @end table
- iksemel's object stack has two separate areas for keeping these data objects.
- Meta chunk contains all the structures and aligned data, while the data chunk
- contains strings. Each chunk starts with a choosen size memory block, then
- when necessary more blocks allocated for providing space. Unless there is a big
- request, each block is double the size of the previous block, thus real memory
- needs are quickly reached without allocating too many blocks, or wasting
- memory with too big blocks.
- @deftp Typedef ikstack
- This is a structure defining the object stack. Its fields are private
- and subject to change with new iksemel releases.
- @end deftp
- @deftypefun {ikstack *} iks_stack_new (size_t @var{meta_chunk}, size_t @var{data_chunk});
- Creates an object stack. @var{meta_chunk} is the initial size of the
- data block used for structures and aligned data. @var{data_chunk} is
- the initial size of the data block used for strings. They are both in byte units.
- These two initial chunks and a small object stack structure is allocated in
- one @code{malloc} call for optimization purproses.
- @end deftypefun
- @deftypefun {void *} iks_stack_alloc (ikstack * @var{stack}, size_t @var{size});
- Allocates @var{size} bytes of space from the object stack's meta chunk.
- Allocated space is aligned on platform's default alignment boundary and
- isn't initialized. Returns a pointer to the space, or NULL if there isn't enough
- space available and allocating a new block fails.
- @end deftypefun
- @deftypefun {void *} iks_stack_strdup (ikstack * @var{stack}, const char * @var{src}, size_t @var{len});
- Copies given string @var{src} into the object stack's data chunk. Returns a
- pointer to the new string, or NULL if there isn't enough space in the stack.
- If @var{len} is zero string must be null terminated.
- @end deftypefun
- @deftypefun void iks_stack_delete (ikstack * @var{stack});
- Gives all memory associated with object stack to the system.
- @end deftypefun
- Since character data sections are usually parsed in separate blocks,
- a growable string implementation is necessary for saving memory.
- @deftypefun {char *} iks_stack_strcat (ikstack *@var{stack}, char *@var{old}, size_t @var{old_len}, const char *@var{src}, size_t @var{src_len});
- This function appends the string @var{src} to the string @var{old} in the
- stack's data chunk. If @var{old} is NULL it behaves like @code{iks_stack_strdup}.
- Otherwise @var{old} has to be a string created with @code{iks_stack_strdup}
- or @code{iks_stack_strcat} functions.
- If @var{old_len} or @var{src_len} is zero, corresponding string must be null
- terminated.
- Since string can be moved into another block of the data chunk, you must use the
- returned value for new string, and must not reference to @var{old} anymore.
- Return value can be NULL if there isn't enough space in stack, and allocating a
- new block fails.
- @end deftypefun
- @comment ============================================================
- @node Creating a Tree,Accessing the Tree,Memory Management,Working with XML Trees
- @subsection Creating a Tree
- @deftp Typedef iks
- This is a structure defining a XML node. Its fields are private and only
- accessed by following functions.
- @end deftp
- @deftypefun iks* iks_new (const char *@var{name});
- Creates an object stack and creates a IKS_TAG type of node with given
- tag name inside the stack. Tag name is also copied into the stack.
- Returns the node pointer, or NULL if there isn't enough memory.
- @end deftypefun
- @deftypefun iks* iks_new_within (const char *@var{name}, ikstack* @var{stack});
- Creates a IKS_TAG type of node with the given tag name. Node and tag
- name is allocated inside the given object stack. Returns the node
- pointer, or NULL if there isn't enough memory.
- @end deftypefun
- @deftypefun iks* iks_insert (iks *@var{x}, const char *@var{name});
- Creates a IKS_TAG type of node with the given tag name. Node and tag
- name is allocated inside the @var{x} node's object stack and linked
- to @var{x} as a child node. Returns the node pointer, or NULL if there
- isn't enough memory.
- @end deftypefun
- @deftypefun iks* iks_insert_cdata (iks* @var{x}, const char* @var{data}, size_t @var{len});
- Creates a IKS_CDATA type of node with given character data. Node is
- allocated inside the @var{x} node's object stack and linked to @var{x}
- as a child node. Data is copied as well. If @var{len} is zero data must
- be a null terminated string. Returns the node pointer, or NULL if
- there isn't enough memory.
- @end deftypefun
- @deftypefun iks* iks_insert_attrib (iks* @var{x}, const char* @var{name}, const char* @var{value});
- Creates a IKS_ATTRIBUTE type of node with given attribute name and the
- value. Node is allocated inside the @var{x} node's object stack and
- linked to @var{x} as an attribute node. Attribute name and value is
- copied as well. Returns the node pointer, or NULL if there isn't
- enough memory.
- Reinserting another value with same attribute name changes an attribute's
- value. If @var{value} is NULL, attribute is removed from the tag.
- @end deftypefun
- @deftypefun iks* iks_insert_node (iks* @var{x}, iks* @var{y});
- Links node @var{y} to node @var{x} as a child node. Nodes are not copied
- between object stacks, be careful.
- @end deftypefun
- @deftypefun void iks_hide (iks *@var{x});
- Changes the links of the other nodes so that @var{x} becomes invisible.
- It stays in the same object stack with neighbour nodes, be careful.
- @end deftypefun
- @deftypefun void iks_delete (iks *@var{x});
- Frees the object stack of the node @var{x}.
- @end deftypefun
- Now lets create a tree representation of following XML document:
- @example
- <message type='chat' from='bob@@bd.com'>
- <subject>song lyric</subject><priority>high</priority>
- <body>
- <em style='underline'>here is the correct version:</em>
- i just don't see why i should even care
- it's not dark yet, but it's getting there
- </body>
- </message>
- @end example
- here is the code:
- @example
- iks *x, *y, *z;
- x = iks_new ("message");
- iks_insert_attrib (x, "type", "chat");
- iks_insert_attrib (x, "from", "bob@@bd.com");
- iks_insert_cdata (x, "\n", 1);
- iks_insert_cdata (iks_insert (x, "subject"), "song lyric", 10);
- iks_insert_cdata (iks_insert (x, "priority"), "high", 4);
- iks_insert_cdata (x, "\n", 1);
- y = iks_insert (x, "body");
- iks_insert_cdata (y, "\n", 1);
- z = iks_insert (y, "em");
- iks_insert_attrib (z, "style", "underline");
- iks_insert_cdata (z, "here is the correct version", 0);
- iks_insert_cdata (y, "\n", 1);
- iks_insert_cdata (y, "i just don't see why", 0);
- iks_insert_cdata (y, "i should even care\n", 0);
- iks_insert_cdata (y, "it's not dark yet,", 0);
- iks_insert_cdata (y, "but it's getting there\n", 0);
- iks_insert_cdata (x, "\n", 1);
- @end example
- Notice how newlines are inserted for proper formatting of document. They aren't
- necessary for representing data, but they make it easier to read document for
- humans.
- Also notice how @code{iks_insert} and @code{iks_insert_cdata} chained.
- There are also functions for duplicating xml trees. They are:
- @deftypefun {iks *} iks_copy (iks* @var{x});
- Creates a full copy of the tree in a newly created object stack.
- @end deftypefun
- @deftypefun {iks *} iks_copy_within (iks* @var{x}, ikstack *@var{s});
- Creates a full copy of the tree in given object stack.
- @end deftypefun
- @comment ============================================================
- @node Accessing the Tree,Converting a Tree into an XML Document,Creating a Tree,Working with XML Trees
- @subsection Accessing a Tree
- Basic access functions allow you to move on the tree:
- @deftypefun iks* iks_next (iks* @var{x});
- @end deftypefun
- @deftypefun iks* iks_prev (iks* @var{x});
- @end deftypefun
- @deftypefun iks* iks_parent (iks* @var{x});
- @end deftypefun
- @deftypefun iks* iks_child (iks* @var{x});
- @end deftypefun
- @deftypefun iks* iks_attrib (iks* @var{x});
- @end deftypefun
- These functions return a pointer to the next, previous, parent, first child,
- and first attribute node of the given node @var{x}. If that node doesn't
- exist or @var{x} is NULL, a NULL value is returned.
- @deftypefun {iks *} iks_root (iks *@var{x});
- Returns the topmost parent node of the @var{x}.
- @end deftypefun
- @deftypefun iks* iks_next_tag (iks* @var{x});
- @end deftypefun
- @deftypefun iks* iks_prev_tag (iks* @var{x});
- @end deftypefun
- @deftypefun iks* iks_first_tag (iks* @var{x});
- @end deftypefun
- These functions return a pointer to the next, previous, first child node
- of the given node @var{x}. Only tag nodes are considered, other type
- of the nodes are skipped. If such a node doesn't exist or @var{x} is NULL,
- a NULL value is returned.
- Another group of functions allow you to access specific information and
- content of the nodes:
- @deftypefun ikstack* iks_stack (iks* @var{x});
- Returns the object stack which node @var{x} stays.
- @end deftypefun
- @deftypefun {enum ikstype} iks_type (iks* @var{x});
- Returns the type of the node.
- @tindex ikstype
- @table @code
- @item IKS_TAG
- Node is a tag and can contain child nodes and attributes.
- @item IKS_CDATA
- Node contains character data.
- @item IKS_ATTRIBUTE
- Node contains an attribute and its value.
- @end table
- @end deftypefun
- @deftypefun char* iks_name (iks* @var{x});
- Returns the name of the tag for nodes with the type @var{IKS_TAG}.
- Returns an attribute's name for nodes of type IKS_ATTRIBUTE.
- @end deftypefun
- @deftypefun char* iks_cdata (iks* @var{x});
- Returns a pointer to node's character data if available, NULL otherwise.
- Returns an attribute's value for nodes of type IKS_ATTRIBUTE.
- @end deftypefun
- @deftypefun size_t iks_cdata_size (iks *@var{x});
- Returns the size of the node's character data in bytes.
- @end deftypefun
- @deftypefun int iks_has_children (iks *@var{x});
- Returns a non-zero value if node @var{x} has a child node.
- @end deftypefun
- @deftypefun int iks_has_attribs (iks *@var{x});
- Returns a non-zero value if node @var{x} has attributes.
- @end deftypefun
- Last group of the functions simplifies finding and accessing the content
- of a specific node:
- @deftypefun iks* iks_find (iks *@var{x}, const char *@var{name});
- Searches a IKS_TAG type of node with @var{name} as tag name in child
- nodes of @var{x}. Returns a pointer to the node if found, NULL otherwise.
- @end deftypefun
- @deftypefun char* iks_find_cdata (iks* @var{x}, const char* @var{name});
- Searches a IKS_TAG type of node with @var{name} as tag name in child
- nodes of @var{x}. Returns a pointer to the character data of the node's
- first child node if found, NULL otherwise.
- @end deftypefun
- @deftypefun char* iks_find_attrib (iks* @var{x}, const char* @var{name});
- Searches an attribute with given name in attributes of the @var{x}.
- Returns a pointer to attribute value if found, NULL otherwise.
- @end deftypefun
- @deftypefun {iks *} iks_find_with_attrib (iks *@var{x}, const char *@var{tagname}, const char *@var{attrname}, const char *@var{value});
- Searches for a child tag of @var{x} which has an attribute with name
- @var{attrname} and value @var{value}. If @var{tagname} isn't NULL,
- name of the tag must also match. Returns a pointer to the node if found,
- NULL otherwise.
- @end deftypefun
- Here is an example which demonstrates accessing file names in a fictitious
- XML playlist file:
- @example
- <playlist>
- <item type='mpg'>
- <name>/home/madcat/download/matrix_rev_trailer.mpg</name>
- <duration>1:17</duration>
- </item>
- <item type='rm'>
- <name>/home/madcat/anim/clementine_ep1.rm</name>
- <duration>22:00</duration>
- </item>
- <item type='avi'>
- <name>/home/madcat/anim/futurama/ep101.avi</name>
- <subtitle>/home/madcat/subs/futurama/ep101.txt</subtitle>
- <duration>30:00</duration>
- </item>
- <repeat/>
- <fullscreen/>
- <noui/>
- </playlist>
- @end example
- and here is the code:
- @example
- #include <stdio.h>
- #include <iksemel.h>
- int main (int argc, char *argv[])
- @{
- iks *x, *y;
- int e;
- if (argc < 2) @{
- printf ("usage: %s <playlistfile>", argv[0]);
- return 0;
- @}
- e = iks_load (argv[1], &x);
- if (e != IKS_OK) @{
- printf ("parse error %d\n", e);
- return 1;
- @}
- if (iks_find (x, "repeat")) puts ("repeat mode enabled");
- y = iks_child (x);
- while (y) @{
- if (iks_type (y) == IKS_TAG
- && strcmp (iks_name (y), "item") == 0) @{
- printf ("Filename: [%s]\n", iks_find_cdata (y, "name"));
- @}
- y = iks_next (y);
- @}
- iks_delete (x);
- return 0;
- @}
- @end example
- @comment ============================================================
- @node Converting a Tree into an XML Document,Parsing an XML Document into a Tree,Accessing the Tree,Working with XML Trees
- @subsection Converting a Tree to an XML Document
- There is a function for converting given XML tree into a null terminated string.
- @deftypefun {char *} iks_string (ikstack* @var{stack}, iks* @var{x});
- Converts given tree into a string. String is created inside the given object
- stack. Returns a pointer to the string, or NULL if there isn't enough memory
- available.
- If @var{stack} is NULL, string is created inside an @code{iks_malloc}ed buffer.
- You can free it later with @code{iks_free} function.
- @end deftypefun
- Here is an example which builds a tree and print it.
- @example
- iks *x;
- char *t;
- x = iks_new ("test");
- iks_insert_cdata (iks_insert (x, "a"), "1234", 4);
- iks_insert (x, "br");
- iks_insert_cdata (x, "1234", 4);
- t = iks_string (iks_stack (x), x);
- puts (t);
- iks_delete (x);
- @end example
- @comment ============================================================
- @node Parsing an XML Document into a Tree,,Converting a Tree into an XML Document,Working with XML Trees
- @subsection Parsing a Document into a Tree
- If you want to automatically convert an XML document into a tree, you can use
- iksemel's DOM parser. It is created with following function:
- @deftypefun iksparser* iks_dom_new (iks **@var{iksptr});
- Creates a DOM parser. A pointer to the created XML tree is put into the
- variable pointed by @var{iksptr}. Returns a pointer to the parser, or NULL
- is there isn't enough memory.
- @end deftypefun
- Usage is same as SAX parser. You feed the data with @code{iks_parse}, and if
- there isn't an error, you can access to your tree from variable @code{*iksptr}.
- Here is a simple example:
- @example
- iks *x;
- iksparser *p;
- p = iks_dom_new (&x);
- if (IKS_OK != iks_parse (p, "<a>bcd</a>", 9, 1)) @{
- puts ("parse error");
- @}
- /* x is useable after that point */
- /* this will print 'bcd' */
- printf ("%s\n", iks_cdata (iks_child (x)));
- @end example
- If you know the size of the file ahead, or you have an approximate idea,
- you can tell this to the dom parser for choosing a better memory allocation
- strategy. Here is the function for this.
- @deftypefun void iks_set_size_hint (iksparser *@var{prs}, size_t @var{approx_size});
- Parser @var{prs} must be a dom type parser. @var{approx_size} is the
- expected size of the xml document. Parser chooses its chunk size
- based on this information. Helps performance while processing big files.
- @end deftypefun
- If you already have your XML document in memory, you can simply parse
- it with:
- @deftypefun {iks *} iks_tree (const char *@var{xml_str}, size_t @var{len}, int *@var{err});
- This function parses the buffer pointed by @var{xml_str}. If @var{len} is zero
- buffer is considered as a null terminated utf8 string. Returns the parsed tree,
- or NULL if there is an error. If @var{err} is not NULL, actual error code (returned
- by iks_parse) is put there.
- @end deftypefun
- Most of the times you want to load your configuration (or similar) files directly
- into trees. iksemel provides two functions to greatly simplify this:
- @deftypefun int iks_load (const char *@var{fname}, iks **@var{xptr});
- Loads the XML file. Tree is placed into the variable pointed by @var{xptr}.
- @end deftypefun
- @deftypefun int iks_save (const char *@var{fname}, iks *@var{x});
- Converts tree @var{x} into a string and saves to the file.
- @end deftypefun
- Both functions return same error codes as @code{iks_parse}. Some additional
- error codes are defined for indicating file problems. They are:
- @table @code
- @item IKS_FILE_NOFILE
- A file with the given name doesn't exist.
- @item IKS_FILE_NOACCESS
- Cannot open file. Possibly a permission problem.
- @item IKS_FILE_RWERR
- Read or write operation failed.
- @end table
- Here is a simple example which parses a file and saves it into another:
- @example
- iks *x;
- if (IKS_OK != iks_load ("file1.xml", &x)) @{
- puts ("loading error");
- @}
- if (IKS_OK != iks_save ("file2.xml", x)) @{
- puts ("saving error");
- @}
- @end example
- @comment ============================================================
- @node XML Streams,Writing a Jabber Client,Working with XML Trees,Tutorials
- @section XML Streams
- XML streams function as containers for any XML chunks sent asynchronously
- between network endpoints. They are used for asyncronously exchanging
- relatively small payload of structured information between entities.
- A stream is initiated by one of hosts connecting to the other, and sending a
- <stream:stream> tag. Receiving entity replies with a second XML stream
- back to the initiating entity within the same connection. Each unit of
- information is send as a direct child tag of the <stream:stream> tag.
- Stream is closed with </stream:stream>.
- XML streams use a subset of XML. Specifically they should not contain
- processing instructions, non-predefined entities, comments, or DTDs.
- Jabber protocol uses XML streams for exchanging messages, presence
- information, and other information like authorization, search, time and
- version queries, protocol extensions.
- iksemel provides you a stream parser, which automatically handles connection
- to the server, and calls your hook function with incoming information
- parsed and converted to an XML tree.
- You can create such a parser with:
- @deftypefun iksparser* iks_stream_new (char* @var{name_space}, void* @var{user_data}, iksStreamHook* @var{streamHook});
- Allocates and initalizes a stream parser. @var{name_space} indicates the
- stream type, jabber clients use "jabber:client" namespace. @var{user_data}
- is passed directly to your hook function.
- @end deftypefun
- @deftp Typedef iksStreamHook
- int iksStreamHook (void* @var{user_data}, int @var{type}, iks* @var{node});
- Depending on the value of the @var{type}, @var{node} contains:
- @table @code
- @item IKS_NODE_START
- Got the <stream:stream> tag, namespace, stream id and other information
- is contained in the @var{node}.
- @item IKS_NODE_NORMAL
- A first level child of the <stream:stream> tag is received. @var{node} contains
- the parsed tag. If you are connected to a jabber server, you can get <message>,
- <presence>, or <iq> tags.
- @item IKS_NODE_ERROR
- Got a <stream:error> tag, details can be accessed from @var{node}.
- @item IKS_NODE_STOP
- </stream:stream> tag is received or connection is closed, @var{node} is @code{NULL}.
- @end table
- Freeing the node with @code{iks_delete} is up to you.
- @end deftp
- You can manually feed this parser with @code{iks_parse} function, but using
- iksemel's connection facilities is easier for most of the cases.
- This functions return @code{IKS_OK} for success. Error codes of @code{iks_parse}
- are used in same manner. Following additional codes are defined for
- network related problems:
- @table @code
- @item IKS_NET_NODNS
- Hostname lookup failed. Possible reasons: hostname is incorrect,
- you are not online, your dns server isn't accessible.
- @item IKS_NET_NOSOCK
- Socket cannot created.
- @item IKS_NET_NOCONN
- Connection attemp failed. Possible reasons: host is not an XML stream
- server, port number is wrong, server is busy or closed for the moment.
- @item IKS_NET_RWERR
- @code{send} or @code{recv} call is failed when attempting to exchange
- the data with the server. You should close the connection with @code{iks_disconnect}
- after getting this error from data transfer functions.
- @end table
- @deftypefun int iks_connect_tcp (iksparser *@var{prs}, const char *@var{server}, int @var{port});
- This function connects the parser to a server and sends stream header for you.
- @var{server} is the host name of the server and @var{port} is the tcp port
- number which server is listening to. You can use @code{IKS_JABBER_PORT}
- macro for the default jabber client port (5222).
- @end deftypefun
- @deftypefun int iks_connect_fd (iksparser *@var{prs}, int @var{fd});
- Attaches parser to an already opened connection. @var{fd} is the socket
- descriptor. Note that @code{iks_disconnect} doesn't close the socket
- for this kind of connection, opening and closing of the socket is up to your
- application. Stream header is not sent automatically. You can use
- @code{iks_send_header} function for sending it.
- @end deftypefun
- @deftypefun void iks_disconnect (iksparser *@var{prs});
- Closes connection to the server, and frees connection resources.
- @end deftypefun
- After successfully connecting to a server, you can use following functions
- for exchanging information with server.
- @deftypefun int iks_recv (iksparser* @var{prs}, int @var{timeout});
- If @var{timeout} is @code{-1}, waits until some data arrives from server,
- and process the data. Your stream hook can be called if a complete
- chunk is arrived.
- If @var{timeout} is a positive integer, @code{iks_recv} returns if no data
- arrives for @var{timeout} seconds.
- If @var{timeout} is zero, @code{iks_recv} checks if there is any data
- waiting at the network buffer, and returns without waiting for data.
- @end deftypefun
- @deftypefun int iks_fd (iksparser* @var{prs});
- Returns the file descriptor of the connected socket. You can use this in
- your @code{select} function or some other input loop to act whenever
- some data from the server arrives. This value of only valid between
- a successful @code{iks_connect_tcp} and @code{iks_disconnect}.
- @end deftypefun
- @deftypefun int iks_send (iksparser* @var{prs}, iks* @var{x});
- Converts the tree given in @var{x} to a string, and sends to the server.
- String is created inside the object stack of @var{x}.
- @end deftypefun
- @deftypefun int iks_send_raw (iksparser* @var{prs}, char* @var{xmlstr});
- Sends the string given in @var{xmlstr} to the server.
- @end deftypefun
- @deftypefun int iks_send_header (iksparser *@var{prs}, char *@var{to});
- Sends the stream header. @var{to} is the name of the server.
- Normally @code{iks_connect_tcp} function calls this for you. This
- is only useful if you are using @code{iks_connect_fd}.
- @end deftypefun
- Sometimes it is useful to log incoming and outgoing data to your parser
- for debugging your applications. iksemel provides a logging facility for you.
- @deftypefun void iks_set_log_hook (iksparser* @var{prs}, iksLogHook* @var{logHook});
- Sets the log function for your stream parser. You can't use this function
- on any other type of parser.
- @end deftypefun
- @deftp Typedef iksLogHook
- void iksLogHook (void* @var{user_data}, const char* @var{data}, size_t @var{size}, int @var{is_incoming});
- @var{user_data} is same value which you give with @code{iks_stream_new}.
- @var{data} is @var{size} bytes of data. Be very careful that this data may be
- coming from other side of the connection and can contain malicius bytes. It isn't
- checked by iksemel yet, so you should check it yourself before displaying or
- passing to other systems in your application or computer. If @var{is_incoming}
- is a non-zero value, data is incoming from server, otherwise it is outgoing to the
- server.
- @end deftp
- @comment ============================================================
- @node Writing a Jabber Client,Utility Functions,XML Streams,Tutorials
- @section Writing a Jabber Client
- @ifinfo
- @menu
- * Security::
- * Packets::
- * Packet Filter::
- * Creating Common Packets::
- @end menu
- @end ifinfo
- @comment ============================================================
- @node Security,Packets,,Writing a Jabber Client
- @subsection Security
- iksemel supports TLS protocol for encrypted communication and SASL
- protocol for authentication. TLS is handled by gnutls library.
- @deftypefun int iks_has_tls (void);
- If iksemel is compiled with gnutls library, this function returns a non-zero
- value indicating you can try encrypted connection with the server.
- @end deftypefun
- @deftypefun int iks_start_tls (iksparser* @var{prs});
- Starts a TLS handshake over already connected parser. Returns IKS_OK or
- one of the IKS_NET_ errors. If handshake succeeds you'll get another
- stream header from server.
- @end deftypefun
- @deftypefun int iks_is_secure (iksparser* @var{prs});
- Returns a non-zero value if a secure connection is fully established
- between server.
- @end deftypefun
- @deftypefun int iks_start_sasl (iksparser* @var{prs}, enum ikssasltype @var{type}, char* @var{username}, char* @var{pass});
- Starts SASL operation.
- @end deftypefun
- See tools/iksroster.c for a good example.
- @comment ============================================================
- @node Packets,Packet Filter,Security,Writing a Jabber Client
- @subsection Packets
- iksemel can parse a jabber XML node and provide you a public packet
- structure which contains information like node type and subtype, id,
- namespace, sender's jabber id, etc.
- This handles a lot of node parsing for you. Packets are also used in
- the packet filter subsystem.
- @deftypefun {ikspak *} iks_packet (iks *@var{x});
- Takes a node from stream and extracts information from it to a packet structure.
- Structure is allocated inside the node's object stack.
- @end deftypefun
- @tindex ikspak
- @code{ikspak} structure has following fields:
- @table @code
- @item iks *x;
- This is a pointer to the node.
- @item iksid *from;
- Sender's jabber id in parsed form. See below for @code{iksid} structure.
- @item iks *query;
- A pointer to the <query> tag for IQ nodes.
- @item char *ns;
- Namespace of the content for IQ nodes.
- @item char *id;
- ID of the node.
- @item enum ikspaktype type;
- Type of the node. Possible types are:
- @table @code
- @item IKS_PAK_NONE
- Unknown node.
- @item IKS_PAK_MESSAGE
- Message node.
- @item IKS_PAK_PRESENCE
- Presence node with presence publishing operation.
- @item IKS_PAK_S10N
- Presence node with subscription operation.
- @item IKS_PAK_IQ
- IQ node.
- @end table
- @item enum iksubtype subtype;
- Sub type of the node. Sub types for message nodes:
- @table @code
- @item IKS_TYPE_NONE
- A normal message.
- @item IKS_TYPE_CHAT
- Private chat message.
- @item IKS_TYPE_GROUPCHAT
- Multi user chat message.
- @item IKS_TYPE_HEADLINE
- Message from a news source.
- @item IKS_TYPE_ERROR
- Message error.
- @end table
- Sub types for IQ nodes:
- @table @code
- @item IKS_TYPE_GET
- Asks for some information.
- @item IKS_TYPE_SET
- Request for changing information.
- @item IKS_TYPE_RESULT
- Reply to get and set requests.
- @item IKS_TYPE_ERROR
- IQ error.
- @end table
- Sub types for subscription nodes:
- @table @code
- @item IKS_TYPE_SUBSCRIBE,
- Asks for subscribing to the presence.
- @item IKS_TYPE_SUBSCRIBED,
- Grants subscription.
- @item IKS_TYPE_UNSUBSCRIBE,
- Asks for unsubscribing to the presence.
- @item IKS_TYPE_UNSUBSCRIBED,
- Cancels subscription.
- @item IKS_TYPE_ERROR
- Presence error.
- @end table
- Sub types for presence nodes:
- @table @code
- @item IKS_TYPE_PROBE,
- Asks presence status.
- @item IKS_TYPE_AVAILABLE,
- Publishes entity as available. More information can be found in @code{show} field.
- @item IKS_TYPE_UNAVAILABLE
- Publishes entity as unavailable. More information can be found in @code{show} field.
- @end table
- @item enum ikshowtype show;
- Presence state for the presence nodes.
- @table @code
- @item IKS_SHOW_UNAVAILABLE
- Entity is unavailable.
- @item IKS_SHOW_AVAILABLE
- Entity is available.
- @item IKS_SHOW_CHAT
- Entity is free for chat.
- @item IKS_SHOW_AWAY
- Entity is away for a short time.
- @item IKS_SHOW_XA
- Entity is away for a long time.
- @item IKS_SHOW_DND
- Entity doesn't want to be disturbed.
- @end table
- @end table
- iksemel has two functions to parse and compare jabber IDs.
- @deftypefun {iksid *} iks_id_new (ikstack *@var{s}, const char *@var{jid});
- Parses a jabber id into its parts. @code{iksid} structure is created inside
- the @var{s} object stack.
- @end deftypefun
- @tindex iksid
- @code{iksid} structure has following fields:
- @table @code
- @item char *user;
- User name.
- @item char *server;
- Server name.
- @item char *resource;
- Resource.
- @item char *partial;
- User name and server name.
- @item char *full;
- User name, server name and resource.
- @end table
- You can access this fields and read their values. Comparing two parsed jabber
- ids can be done with:
- @deftypefun int iks_id_cmp (iksid *@var{a}, iksid *@var{b}, int @var{parts});
- Compares @var{parts} of @var{a} and @var{b}. Part values are:
- @table @code
- @item IKS_ID_USER
- @item IKS_ID_SERVER
- @item IKS_ID_RESOURCE
- @end table
- @sp 1
- You can combine this values with @code{or} operator. Some common combinations
- are predefined for you:
- @table @code
- @item IKS_ID_PARTIAL
- @code{IKS_ID_USER | IKS_ID_SERVER}
- @item IKS_ID_FULL
- @code{IKS_ID_USER | IKS_ID_SERVER | IKS_ID_RESOURCE}
- @end table
- Return value is @code{0} for equality. If entities are not equal a combination of
- part values showing different parts is returned.
- @end deftypefun
- @comment ============================================================
- @node Packet Filter,Creating Common Packets,Packets,Writing a Jabber Client
- @subsection Packet Filter
- Packet filter handles routing incoming packets to related functions.
- @tindex iksfilter
- @deftypefun {iksfilter *} iks_filter_new (void);
- Creates a new packet filter.
- @end deftypefun
- @deftypefun void iks_filter_packet (iksfilter *@var{f}, ikspak *@var{pak});
- Feeds the filter with given packet. Packet is compared to registered rules and
- hook functions of the matching rules are called in most matched to least
- matched order.
- @end deftypefun
- @deftypefun void iks_filter_delete (iksfilter *@var{f});
- Frees filter and rules.
- @end deftypefun
- Rules are created with following function:
- @tindex iksrule
- @deftypefun {iksrule *} iks_filter_add_rule (iksfilter *@var{f}, iksFilterHook *@var{filterHook}, void *@var{user_data}, @dots{});
- Adds a rule to the filter @var{f}. @var{user_data} is passed directly to your
- hook function @var{filterHook}.
- A rule consist of one or more type and value pairs. Possible types:
- @table @code
- @item IKS_RULE_ID
- Compares @code{char *} value to packet ids.
- @item IKS_RULE_FROM
- Compares @code{char *} value to packet senders.
- @item IKS_RULE_FROM_PARTIAL
- Compares @code{char *} value to packet sender. Ignores resource part of jabber id.
- @item IKS_RULE_NS
- Compares @code{char *} value to namespace of iq packets.
- @item IKS_RULE_TYPE
- Compares @code{int} value to packet types.
- @item IKS_RULE_SUBTYPE
- Compares @code{int} value to packet sub types.
- @item IKS_RULE_DONE
- Terminates the rule pairs.
- @end table
- @end deftypefun
- Here is an example which creates a filter and adds three rules:
- @example
- iksfilter *f;
- f = iks_filter_new ();
- iks_filter_add_rule (f, on_msg, NULL,
- IKS_RULE_TYPE, IKS_PAK_MESSAGE,
- IKS_RULE_DONE);
- iks_filter_add_rule (f, on_auth_result, NULL,
- IKS_RULE_TYPE, IKS_PAK_IQ,
- IKS_RULE_SUBTYPE, IKS_TYPE_RESULT,
- IKS_RULE_ID, "auth",
- IKS_RULE_DONE);
- iks_filter_add_rule (f, on_roster_push, NULL,
- IKS_RULE_TYPE, IKS_PAK_IQ,
- IKS_RULE_SUBTYPE, IKS_TYPE_SET,
- IKS_RULE_NS, "jabber:iq:roster",
- IKS_RULE_DONE);
- @end example
- @deftp Typedef iksFilterHook
- int iksFilterHook (void *user_data, ikspak *pak);
- Your hook is called with your @var{user_data} and matching packet @var{pak}.
- You can return two different values from your hook:
- @table @code
- @item IKS_FILTER_PASS
- Packet is forwarded to least matching rules.
- @item IKS_FILTER_EAT
- Filtering process for the packet ends.
- @end table
- @end deftp
- You can remove the rules with following functions:
- @deftypefun void iks_filter_remove_rule (iksfilter *@var{f}, iksrule *@var{rule});
- Removes the rule from filter.
- @end deftypefun
- @deftypefun void iks_filter_remove_hook (iksfilter *@var{f}, iksFilterHook *@var{filterHook});
- Remove the rules using @var{filterHook} function from filter.
- @end deftypefun
- @comment ============================================================
- @node Creating Common Packets,,Packet Filter,Writing a Jabber Client
- @subsection Creating Common Packets
- A usual jabber network traffic contains many similar XML constructs. iksemel
- provides several utility functions for creating them. They all generate an XML
- tree, so you can add or modify some parts of the tree, and send to server then.
- @deftypefun {iks *} iks_make_auth (iksid *@var{id}, const char *@var{pass}, const char *@var{sid});
- Creates an authorization packet. @var{id} is your parsed jabber id, and @var{pass}
- is your password.
- If stream id @var{sid} isn't NULL, SHA1 authentication is used, otherwise password
- is attached in plain text. You can learn stream id from @code{IKS_STREAM_START}
- packet in your stream hook like this:
- @example
- char *sid;
- if (type == IKS_STREAM_START) @{
- sid = iks_find_attrib (node, "id");
- @}
- @end example
- @end deftypefun
- @deftypefun {iks *} iks_make_msg (enum iksubtype @var{type}, const char *@var{to}, const char *@var{body});
- Creates a message packet. @var{type} is the message type, @var{to} is jabber id
- of the recipient, @var{body} is the message.
- @end deftypefun
- @deftypefun {iks *} iks_make_s10n (enum iksubtype @var{type}, const char *@var{to}, const char *@var{msg});
- Creates a presence packet for subscription operations. @var{type} is operation,
- @var{to} is jabber id of the recipient, @var{msg} is a small message for
- introducing yourself, or explaning the reason of why you are subscribing or
- unsubscribing.
- @end deftypefun
- @deftypefun {iks *} iks_make_pres (enum ikshowtype @var{show}, const char *@var{status});
- Creates a presence packet for publishing your presence. @var{show} is your
- presence state and @var{status} is a message explaining why you are not
- available at the moment, or what you are doing now.
- @end deftypefun
- @deftypefun {iks *} iks_make_iq (enum iksubtype @var{type}, const char *@var{xmlns});
- Creates an IQ packet. @var{type} is operation type and @var{xmlns} is the
- namespace of the content. You usually have to add real content to the <query>
- tag before sending this packet.
- @end deftypefun
- @comment ============================================================
- @node Utility Functions,,Writing a Jabber Client,Tutorials
- @section Utility Functions
- @subsection Memory Utilities
- @deftypefun {void *} iks_malloc (size_t @var{size});
- @end deftypefun
- @deftypefun void iks_free (void *@var{ptr});
- @end deftypefun
- These are wrappers around ANSI malloc and free functions used by the
- iksemel library itself. You can free the output of iks_string (only if you
- passed it a NULL stack) with iks_free for example. That is important
- if you are using a malloc debugger in your application but not in iksemel
- or vice versa.
- @comment ============================================================
- @subsection String Utilities
- @deftypefun {char *} iks_strdup (const char *@var{src});
- @end deftypefun
- @deftypefun int iks_strcmp (const char *@var{a}, const char *@var{b});
- @end deftypefun
- @deftypefun int iks_strcasecmp (const char *@var{a}, const char *@var{b});
- @end deftypefun
- @deftypefun int iks_strncmp (const char *@var{a}, const char *@var{b}, size_t @var{n});
- @end deftypefun
- @deftypefun int iks_strncasecmp (const char *@var{a}, const char *@var{b}, size_t @var{n});
- @end deftypefun
- @deftypefun size_t iks_strlen (const char *@var{src});
- @end deftypefun
- These functions work exactly like their ANSI equivalents except that they allow
- NULL values for string pointers. If @var{src} is NULL, iks_strdup and iks_strlen
- returns zero. If @var{a} or @var{b} is NULL in string comparisation functions
- they return -1.
- Their usefulness comes from the fact that they can chained with DOM traversing
- functions like this:
- @smallexample
- if (iks_strcmp (iks_find_attrib (x, "id"), "x1") == 0) count++;
- @end smallexample
- That example works even x doesn't have an 'id' attribute and iks_find_attrib
- returns NULL. So you don't need to use temporary variables in such
- situations.
- @comment ============================================================
- @subsection SHA1 Hash
- Secure Hash Algorithm (SHA1) is used in the Jabber authentication
- protocol for encoding your password when sending to the server.
- This is normally handled by iks_make_auth() function, but if you
- want to handle it manually, or if you need a good hash function
- for other purproses you can use these functions.
- @deftypefun iksha* iks_sha_new (void);
- Allocates a structure for keeping calculation values and the state.
- @end deftypefun
- @deftypefun void iks_sha_reset (iksha *@var{sha});
- Resets the state of the calculation.
- @end deftypefun
- @deftypefun void iks_sha_hash (iksha *@var{sha}, const unsigned char *@var{data}, int @var{len}, int @var{finish});
- Calculates the hash value of the given data. If @var{finish} is non
- zero, applies the last step of the calculation.
- @end deftypefun
- @deftypefun void iks_sha_print (iksha *@var{sha}, char *@var{hash});
- Prints the result of a finished calculation into the buffer pointed by @var{hash}
- in hexadecimal string form. Buffer must be at least 40 bytes long. String
- is not null terminated.
- @end deftypefun
- @deftypefun void iks_sha (const char *@var{data}, char *@var{hash});
- Calculates the hash value of @var{data} and prints into @var{hash}.
- This is a helper function for simple hash calculations. It calls
- other functions for the actual work.
- @end deftypefun
- @comment ============================================================
- @node Development,Datatype Index,Tutorials,Top
- @chapter Development
- This chapter contains information on plan, procedure and standarts of
- iksemel development.
- @section Roadmap
- There are three main functions iksemel tries to provide to applications:
- @itemize @bullet
- @item
- A generic XML parser with SAX and DOM interfaces.
- @item
- XML stream client and server functionality.
- @item
- Utilities for Jabber clients.
- @end itemize
- Goal of the iksemel is providing these functions while supporting embedded
- environments, keeping usage simple, and having a robust implementation.
- Some decisions are made to reach this goal:
- Code is written in ANSI C with a single dependency on C library. Instead of
- using expat or libxml, a simple built-in parser is used. Similarly glib and
- gnu only features of glibc (like object stacks) are avoided and built-in
- memory and string utilities are used. This may seem like code duplication
- but since they are optimized for iksemel and only a few kb in size,
- it isn't a big disadvantage.
- Code is placed files in a modular fashion, and different modules don't depend
- on others' internal details. This allows taking unneeded functionality out when
- building for low resource situations.
- It is tried to give functions names which are consistent, clear and short.
- API is documented with texinfo for high quality printed output and info file
- output for fast and simple access during application development. Instead
- of using an autogenerated system or simply listing function descriptions,
- a task oriented tutorial approach is used.
- @section Coding Style
- Here is a short list describing preferred coding style for iksemel.
- Please keep in mind when sending patches.
- @itemize @bullet
- @item
- Indentation is done with tabs. Aligning is done with spaces.
- @item
- Placement of braces is K&R style.
- @item
- Function names are put at the start of line.
- @item
- Function names are lowercase.
- @item
- Words of the function names are separated with underscore character.
- @item
- Structure and variable names are lowercase.
- @item
- Macro and enumarations names are uppercase.
- @item
- Exported library API is contained in the single iksemel.h file.
- @item
- Exported function names start with iks_
- @item
- Exported structure and type names start with iks
- @item
- Exported macro and enumaration names start with IKS_
- @end itemize
- Here is an example:
- @smallexample
- int
- iks_new_func (char *text)
- @{
- int i;
- i = an_internal_func (text);
- if (IKS_SOME_VALUE == i) @{
- iks_some_func (text);
- i++;
- @}
- return i;
- @}
- @end smallexample
- @section Resources
- @itemize @bullet
- @item
- RFC 2279, UTF-8 format @url{http://www.ietf.org/rfc/rfc2279.txt}
- @item
- W3C Recommendation, Extensible Markup Language 1.0 @url{http://www.w3.org/TR/REC-xml}
- @item
- Annotated XML Specification @url{http://www.xml.com/axml/testaxml.htm}
- @item
- Jabber Protocol Documents @url{http://www.jabber.org/protocol/}
- @end itemize
- @comment ============================================================
- @node Datatype Index,Function Index,Development,Top
- @unnumbered Datatype Index
- @printindex tp
- @node Function Index,,Datatype Index,Top
- @unnumbered Function Index
- @printindex fn
- @contents
- @bye
|