cgroggs.h

Go to the documentation of this file.
00001 /*
00002  * This file is part of Cgroggs.
00003  * Copyright (C) 2008 Richard Kettlewell
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00018  * USA
00019  */
00020 /** @mainpage Cgroggs
00021  *
00022  * Cgroggs is a C API for accessing RGTP servers.
00023  *
00024  * See:
00025  * - @ref cgroggs.h for the public API
00026  * - <a
00027  * href="http://www.greenend.org.uk/rjk/cgroggs/">http://www.greenend.org.uk/rjk/cgroggs/</a> for the Cgroggs home page.
00028  * - <a
00029  * href="http://www.groggs.group.cam.ac.uk/protocol.txt">http://www.groggs.group.cam.ac.uk/protocol.txt</a> for a description of the protocol
00030  * - @ref licence
00031  *
00032  */
00033 /** @page licence Cgroggs Licence
00034  *
00035  * cgroggs is (c) 2008 Richard Kettlewell.
00036  * 
00037  * This program is free software; you can redistribute it and/or modify
00038  * it under the terms of the GNU General Public License as published by
00039  * the Free Software Foundation; either version 2 of the License, or
00040  * (at your option) any later version.
00041  *
00042  * This program is distributed in the hope that it will be useful, but
00043  * WITHOUT ANY WARRANTY; without even the implied warranty of
00044  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00045  * General Public License for more details.
00046  *
00047  * You should have received a copy of the GNU General Public License
00048  * along with this program; if not, write to the Free Software
00049  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00050  * USA
00051  */
00052 
00053 /** @file cgroggs.h
00054  * @brief Cgroggs Public API
00055  *
00056  * See:
00057  * - @ref types
00058  * - @ref setup
00059  * - @ref indx
00060  * - @ref items
00061  * - @ref misc
00062  * - @ref mem
00063  *
00064  * Notes:
00065  * - All symbols in this header start @b cgroggs_ or @b CGROGGS_.
00066  * Symbols starting @b cgroggs__ are used internally but don't appear
00067  * in the header.
00068  * - This is a UTF-8 API.  Article data etc passed to or from these functions is
00069  * always encoded in UTF-8.  This is independent of RGTP's encoding: the
00070  * library will perform any translations necessary.
00071  */
00072 
00073 #ifndef CGROGGS_H
00074 #define CGROGGS_H
00075 
00076 #include <stddef.h>
00077 
00078 #ifdef __cplusplus
00079 extern "C" {
00080 #endif
00081 
00082 /** @defgroup types Data Types */
00083 
00084 /*@{*/
00085 
00086 /** @brief Handle type
00087  *
00088  * A handle represents a single server connection.  It's safe to use
00089  * multiple handles from multiple threads but not to use one handle
00090  * from multiple threads concurrently.
00091  *
00092  * Create a handle with cgroggs_new() and destroy it with cgroggs_destroy().
00093  */
00094 typedef struct cgroggs_data *cgroggs_handle;
00095 
00096 /** @brief Error codes
00097  *
00098  * Convert errors to strings with cgroggs_strerror().
00099  */
00100 typedef enum {
00101   /** @brief Success
00102    *
00103    * Guaranteed to be zero.
00104    */
00105   cgroggs_ok = 0,
00106 
00107   /** @brief Out of memory */
00108   cgroggs_nomem,
00109 
00110   /** @brief Lost connection to server */
00111   cgroggs_lostconn,
00112 
00113   /** @brief Bad response from server */
00114   cgroggs_badresponse,
00115 
00116   /** @brief Cannot resolve hostname */
00117   cgroggs_badhost,
00118 
00119   /** @brief System call failed */
00120   cgroggs_syscall,
00121 
00122   /** @brief Cannot connect */
00123   cgroggs_cantconn,
00124 
00125   /** @brief Access denied by server */
00126   cgroggs_accessdenied,
00127 
00128   /** @brief Error response from response */
00129   cgroggs_servererror,
00130 
00131   /** @brief Invalid argument to some function */
00132   cgroggs_invalidarg,
00133 
00134   /** @brief Server requested some unimplemented feature */
00135   cgroggs_serverunimplemented,
00136 
00137   /** @brief Invalid hex digit */
00138   cgroggs_badhex,
00139 
00140   /** @brief Hex string too long */
00141   cgroggs_hextoolong,
00142 
00143   /** @brief Authentication failed */
00144   cgroggs_authfailed,
00145 
00146   /** @brief Server failed to authenticate with client */
00147   cgroggs_servercompromised,
00148 
00149   /** @brief Input string encoding is not valid */
00150   cgroggs_invalidencoding,
00151 
00152   /** @brief Cannot convert UTF-8 to wire encoding */
00153   cgroggs_cannotencode,
00154 
00155   /** @brief No such item */
00156   cgroggs_nosuchitem,
00157   
00158 } cgroggs_error;
00159 
00160 /** @brief Convert an error code to a string
00161  * @param e Error code
00162  * @return Description string
00163  *
00164  * The description formally uses the current locale's language and
00165  * encoding, but NB that currently there are no localizations other
00166  * than English!
00167  *
00168  * The error string should not be freed.
00169  */
00170 const char *cgroggs_strerror(cgroggs_error e);
00171 
00172 /*@}*/
00173 
00174 /** @defgroup mem Memory Allocation
00175  *
00176  * By default, the standard functions malloc, free and realloc are used for
00177  * memory management.  It is possible to override this by settings @ref
00178  * cgroggs_malloc, @ref cgroggs_realloc and @ref cgroggs_free, for instance to
00179  * use a garbage collector.
00180  */
00181 
00182 /*@{*/
00183 
00184 /** @brief Function used to allocate memory
00185  *
00186  * The default value is malloc(), and this function is used in the
00187  * same way as that.
00188  */
00189 extern void *(*cgroggs_malloc)(size_t n);
00190 
00191 /** @brief Function used to reallocate memory
00192  *
00193  * The default value is realloc(), and this function is used in the
00194  * same way as that.
00195  */
00196 extern void *(*cgroggs_realloc)(void *ptr, size_t n);
00197 
00198 /** @brief Function used to free memory
00199  *
00200  * The default value is free(), and this function is used in the same
00201  * way as that.
00202  */
00203 extern void (*cgroggs_free)(void *);
00204 
00205 /*@}*/
00206 
00207 /** @defgroup setup Setup And Teardown
00208  *
00209  * Every application will have to call cgroggs_new() and cgroggs_configure().
00210  * The other functions in this section are only used for special purposes and
00211  * need not be called in most applications.
00212  */
00213 
00214 /*@{*/
00215 
00216 /** @brief Create a new handle
00217  * @param cp Where to store new handle
00218  * @return Error code
00219  *
00220  * The new handle won't be be configured or connected.  See
00221  * cgroggs_configure() for the former; connection is automatic when
00222  * necessary or can be forced with cgroggs_connect().
00223  */
00224 cgroggs_error cgroggs_new(cgroggs_handle *cp);
00225 
00226 /** @brief Destroy a handle
00227  * @param c Handle to destroy (or NULL)
00228  *
00229  * Disconnects from the server (if necessary) and destroys all state owned by
00230  * @p c.  If @p c is NULL then nothing happens.  It is not safe to use @p c
00231  * afterwards.
00232  */
00233 void cgroggs_destroy(cgroggs_handle c);
00234 
00235 /** @brief Configure a handle
00236  * @param c Handle
00237  * @param host Host to connect to
00238  * @param port Port to connect to (or NULL to use default)
00239  * @param user Username to login as (or NULL to read as guest)
00240  * @param secret Authentication secret (or NULL)
00241  * @param level Desired access level (1-3)
00242  * @return Error code
00243  *
00244  * You must configure the handle before connecting (or performing any
00245  * operation which requires a connection, which is most of them).  New
00246  * configuration will only take effect next time a connection is
00247  *
00248  * Values are copied so the argument pointers need not remain live
00249  * after the call has completed.
00250  *
00251  * NB this function just records the information you give it, it does
00252  * not do a DNS lookup (and so it does not block).
00253  */
00254 cgroggs_error cgroggs_configure(cgroggs_handle c,
00255                                 const char *host,
00256                                 const char *port,
00257                                 const char *user,
00258                                 const char *secret,
00259                                 int level);
00260 
00261 /** @brief Connect to server
00262  * @param c Handle
00263  * @return Error code
00264  *
00265  * Connects to the server, including authorizing if necessary to achieve the
00266  * required access level.
00267  *
00268  * If the handle is already connected then nothing happens.  If you
00269  * want to force reconnection you should call cgroggs_disconnect()
00270  * first.
00271  *
00272  * This function does not have to be called; if other functions need a
00273  * connection they will automatically make one.
00274  */
00275 cgroggs_error cgroggs_connect(cgroggs_handle c);
00276 
00277 /** @brief Disconnect from server
00278  * @param c Handle
00279  * @return Error code
00280  *
00281  * cgroggs_destroy() automatically calls this function and in general
00282  * it's never formally needed.  However if you wish to force a
00283  * disconnect and reconnect for some reason this might be useful.
00284  *
00285  * If the handle is not connected then nothing happens.
00286  */
00287 cgroggs_error cgroggs_disconnect(cgroggs_handle c);
00288 
00289 /** @brief Change access level
00290  * @param c Handle
00291  * @param newlevel Desired new access level (1-3)
00292  * @return Error code
00293  *
00294  * Changes the desired access level.  On success, the new access level will be
00295  * requested even for reconnections on this handle; i.e. you must all this
00296  * function again to downgrade access, disconnecting and reconnecting is not
00297  * sufficient.
00298  *
00299  * If the connection is already at the desired access level then no action is
00300  * taken.
00301  */
00302 cgroggs_error cgroggs_alvl(cgroggs_handle c, int newlevel);
00303 
00304 /*@}*/
00305 
00306 /** @defgroup indx Fetching The Index
00307  *
00308  * Use cgroggs_index_fetch() to fetch updates to the server index.  Generally
00309  * you want to fetch only updates to this, and keep a local copy of existing
00310  * information.
00311  */
00312 
00313 /*@{*/
00314 
00315 /** @brief Index handle type
00316  *
00317  * A index handle contains the result of calling cgroggs_index_fetch().
00318  * Destroy with cgroggs_index_destroy().
00319  *
00320  * Index items are numbered from 0, with the oldest item first (so date and
00321  * sequence number will increase).  NB that sequence numbers should be expected
00322  * to wrap, and should be compared using functions from @ref seq.
00323  *
00324  * Accessor functions:
00325  * - cgroggs_index_count()
00326  * - cgroggs_index_sequence()
00327  * - cgroggs_index_date()
00328  * - cgroggs_index_id()
00329  * - cgroggs_index_user()
00330  * - cgroggs_index_subject()
00331  * - cgroggs_index_type()
00332  */
00333 typedef struct cgroggs_index_data *cgroggs_index;
00334 
00335 /** @brief Fetch the index
00336  * @param c Handle
00337  * @param date Starting time or 0
00338  * @param is_sequence If non-zero, @p date is a sequence number
00339  * @param indexp Where to store index handle
00340  * @return Error code
00341  *
00342  * Fetches the index.
00343  *
00344  * If @p date is non-0 then only index entries since that timestamp (or
00345  * sequence number) will be fetched.  Otherwise all index entries will b
00346  * fetched.
00347  *
00348  * A handle to the index is returned via @p indexp.  The handle can be
00349  * destroyed with cgroggs_index_destroy(), and values extracted from it with
00350  * the accessor functions in this section.
00351  */
00352 cgroggs_error cgroggs_index_fetch(cgroggs_handle c,
00353                                   unsigned long date,
00354                                   int is_sequence,
00355                                   cgroggs_index *indexp);
00356 
00357 /** @brief Destroy an index
00358  * @param i Index handle
00359  */
00360 void cgroggs_index_destroy(cgroggs_index i);
00361 
00362 /** @brief Count the number of items in an index
00363  * @param i Index handle
00364  * @return Item count
00365  *
00366  * Index items are numbered starting from 0.
00367  */
00368 int cgroggs_index_count(cgroggs_index i);
00369 
00370 /** @brief Get an index item's sequence number
00371  * @param i Index handle
00372  * @param item Item number (from 0)
00373  * @return Sequence number
00374  *
00375  * If @p item is not valid, 0 is returned.
00376  */
00377 unsigned long cgroggs_index_sequence(cgroggs_index i, int item);
00378 
00379 /** @brief Get an index item's timestamp
00380  * @param i Index handle
00381  * @param item Item number (from 0)
00382  * @return Sequence number
00383  *
00384  * If @p item is not valid, 0 is returned.
00385  */
00386 unsigned long cgroggs_index_date(cgroggs_index i, int item);
00387 
00388 /** @brief Get an index item's ID
00389  * @param i Index handle
00390  * @param item Item number (from 0)
00391  * @return Pointer to ID
00392  *
00393  * The ID for a motd update is "".
00394  *
00395  * The returned string points "inside" @p i, and becomes invalid when @p i is
00396  * destroyed.
00397  *
00398  * If @p item is not valid, NULL is returned.
00399  */
00400 const char *cgroggs_index_id(cgroggs_index i, int item);
00401 
00402 /** @brief Get an index item's user
00403  * @param i Index handle
00404  * @param item Item number (from 0)
00405  * @return Pointer to username
00406  *
00407  * The returned string points "inside" @p i, and becomes invalid when @p i is
00408  * destroyed.
00409  *
00410  * If @p item is not valid, NULL is returned.
00411  */
00412 const char *cgroggs_index_user(cgroggs_index i, int item);
00413 
00414 /** @brief Get an index item's subject
00415  * @param i Index handle
00416  * @param item Item number (from 0)
00417  * @return Pointer to subject (UTF-8)
00418  *
00419  * The subject for a motd update is "".
00420  *
00421  * The returned string points "inside" @p i, and becomes invalid when @p i is
00422  * destroyed.
00423  *
00424  * If @p item is not valid, NULL is returned.
00425  */
00426 const char *cgroggs_index_subject(cgroggs_index i, int item);
00427 
00428 /** @brief Get an index item's type
00429  * @param i Index handle
00430  * @param item Item number (from 0)
00431  * @return Type code
00432  *
00433  * The type codes from the protocol specification are:
00434  * - 'R' for a reply
00435  * - 'I' for a new item
00436  * - 'C' for a continuation
00437  * - 'F' for a continued item
00438  * - 'E' for an edited item
00439  * - 'M' for a motd update
00440  *
00441  * If @p item is not valid, 0 is returned.
00442  */
00443 int cgroggs_index_type(cgroggs_index i, int item);
00444 
00445 /*@}*/
00446 
00447 /** @defgroup items Fetching Items */
00448 
00449 /*@{*/
00450 
00451 /** @brief Item handle type
00452  *
00453  * Use cgroggs_item_fetch() to fetch an item and cgroggs_item_destroy() to
00454  * destroy a handle.
00455  *
00456  * Accessor functions:
00457  * - cgroggs_item_continued_from()
00458  * - cgroggs_item_continued_in()
00459  * - cgroggs_item_last_edit()
00460  * - cgroggs_item_last_reply() 
00461  * - cgroggs_item_count() 
00462  * - cgroggs_item_reply_sequence() 
00463  * - cgroggs_item_reply_date() 
00464  * - cgroggs_item_reply() 
00465  */
00466 typedef struct cgroggs_item_data *cgroggs_item;
00467 
00468 /** @brief Fetch an item
00469  * @param c Handle
00470  * @param id Item ID to fetch
00471  * @param jp Where to put item handle
00472  *
00473  * Fetches an item.
00474  */
00475 cgroggs_error cgroggs_item_fetch(cgroggs_handle c,
00476                                  const char *id,
00477                                  cgroggs_item *jp);
00478 
00479 /** @brief @brief Destroy an item handle
00480  * @param j Item handle
00481  */
00482 void cgroggs_item_destroy(cgroggs_item j);
00483 
00484 /** @brief Get an item's continued-from field
00485  * @param j Item handle
00486  * @return Item ID this was continued from, or NULL
00487  *
00488  * The returned string points "inside" @p j, and becomes invalid when @p j is
00489  * destroyed.
00490  */
00491 const char *cgroggs_item_continued_from(cgroggs_item j);
00492 
00493 /** @brief Get an item's continued-in field
00494  * @param j Item handle
00495  * @return Item ID this is continued in, or NULL
00496  *
00497  * The returned string points "inside" @p j, and becomes invalid when @p j is
00498  * destroyed.
00499  */
00500 const char *cgroggs_item_continued_in(cgroggs_item j);
00501 
00502 /** @brief Get an item's last-edit field
00503  * @param j Item handle
00504  * @return Last edit sequence number
00505  */
00506 unsigned long cgroggs_item_last_edit(cgroggs_item j);
00507 
00508 /** @brief Get an item's last-reply field
00509  * @param j Item handle
00510  * @return Last reply sequence number
00511  */
00512 unsigned long cgroggs_item_last_reply(cgroggs_item j);
00513 
00514 /** @brief Get an item's reply count
00515  * @param j Item handle
00516  * @return Number of replies
00517  */
00518 int cgroggs_item_count(cgroggs_item j);
00519 
00520 /** @brief Get an item reply's sequence number
00521  * @param j Item handle
00522  * @param n Reply number (from 0)
00523  * @return Sequence number
00524  *
00525  * If @p n is not valid, 0 is returned.
00526  */
00527 unsigned long cgroggs_item_reply_sequence(cgroggs_item j, int n);
00528 
00529 /** @brief Get an item reply's date
00530  * @param j Item handle
00531  * @param n Reply number (from 0)
00532  * @return Date
00533  *
00534  * If @p n is not valid, 0 is returned.
00535  */
00536 unsigned long cgroggs_item_reply_date(cgroggs_item j, int n);
00537 
00538 /** @brief Get an item reply's text
00539  * @param j Item handle
00540  * @param n Reply number (from 0)
00541  * @param nlinesp Where to store line count
00542  * @return Array of lines (UTF-8)
00543  *
00544  * If @p n is not valid, NULL is returned and @p nlinesp is set to 0.
00545  *
00546  * The returned array points "inside" @p j, and becomes invalid when @p j is
00547  * destroyed.
00548  */
00549 const char *const *cgroggs_item_reply(cgroggs_item j, int n, int *nlinesp);
00550 
00551 /** @brief Get item summary information
00552  * @param c Handle
00553  * @param id Item ID
00554  * @param contfromp Where to store continued-from ID, or NULL
00555  * @param continp Where to store continued-in ID, or NULL
00556  * @param lasteditp Where to store last edit sequence number, or NULL
00557  * @param lastreplyp Where to store last reply sequence number, or NULL
00558  * @param flagsp Where to store flags, or NULL
00559  * @param subjectp Where to store subject, or NULL
00560  * @return Error code
00561  *
00562  * All the strings are allocated as with cgroggs_malloc() and must be freed by
00563  * the caller.
00564  *
00565  * Valid flags for @p flagsp are:
00566  * - CGROGGS_STAT_EDITED - item has been edited
00567  * - CGROGGS_STAT_REPLIED - item has had a reply
00568  */
00569 cgroggs_error cgroggs_stat(cgroggs_handle c,
00570                            const char *id,
00571                            char **contfromp,
00572                            char **continp,
00573                            unsigned long *lasteditp,
00574                            unsigned long *lastreplyp,
00575                            unsigned long *flagsp,
00576                            char **subjectp);
00577 
00578 /** @brief Item has been edited
00579  *
00580  * Set in the @p flagsp return from cgroggs_stat() if the item has been edited.
00581  * If the item has not been edited then the @p lasteditp value is meaningless.
00582  */
00583 #define CGROGGS_STAT_EDITED 0x00000001
00584 
00585 /** @brief Item has had a reply
00586  *
00587  * Set in the @p flagsp return from cgroggs_stat() if the item has been
00588  * editedreplied.  If the item has not been replied then the @p lastreplyp
00589  * value is meaningless.
00590  *
00591  * A reply here includes the initial contribution.
00592  */
00593 #define CGROGGS_STAT_REPLIED 0x00000002
00594 
00595 /*@}*/
00596 
00597 /** @defgroup seq Sequence Number Comparison
00598  *
00599  * These functions provide comparison for 32-bit sequence numbers.  The rule
00600  * adopted is that @f$A>B@f$ iff @f$B-A <2^{31} (mod 2^{32})@f$.
00601  */
00602 
00603 /*@{*/
00604 
00605 /** @brief Compare 32-bit sequence numbers
00606  * @param a Sequence number
00607  * @param b Sequence number
00608  * return 1 if @p a is less than @p b, else 0
00609  */
00610 int cgroggs_seq_lt(unsigned long a, unsigned long b);
00611 
00612 /** @brief Compare 32-bit sequence numbers
00613  * @param a Sequence number
00614  * @param b Sequence number
00615  * return 1 if @p a is less than or equal to @p b, else 0
00616  */
00617 int cgroggs_seq_le(unsigned long a, unsigned long b);
00618 
00619 /** @brief Compare 32-bit sequence numbers
00620  * @param a Sequence number
00621  * @param b Sequence number
00622  * return 1 if @p a is greater than @p b, else 0
00623  */
00624 int cgroggs_seq_gt(unsigned long a, unsigned long b);
00625 
00626 /** @brief Compare 32-bit sequence numbers
00627  * @param a Sequence number
00628  * @param b Sequence number
00629  * return 1 if @p a is greater than or equal to @p b, else 0
00630  */
00631 int cgroggs_seq_ge(unsigned long a, unsigned long b);
00632 
00633 /*@}*/
00634 
00635 /** @defgroup misc Miscellaneous Operations */
00636 
00637 /*@{*/
00638 
00639 /** @brief Retrieve server motd
00640  * @param c Handle
00641  * @param vecp Where to store lines of message (UTF-8)
00642  * @param nvecp Where to store line count
00643  * @param lastchangep Where to store sequence number, or NULL
00644  * @param timestampp Where to store timestamp, or NULL
00645  * @return Error code
00646  *
00647  * Retrieves the server's message of the day.  The message is returned as an
00648  * array of pointers, one for each line.  Both the array and the individual
00649  * lines are separately allocated via cgroggs_malloc(), and must be freed by
00650  * the caller.
00651  *
00652  * If there is no motd then the sequence number and timestamp will both be 0.
00653  */
00654 cgroggs_error cgroggs_motd(cgroggs_handle c,
00655                            char ***vecp,
00656                            int *nvecp,
00657                            unsigned long *lastchangep,
00658                            unsigned long *timestampp);
00659 
00660 /*@}*/
00661 
00662 #ifdef __cplusplus
00663 };
00664 #endif
00665 
00666 #endif /* CGROGGS_H */
00667 
00668 /*
00669 Local Variables:
00670 c-basic-offset:2
00671 comment-column:40
00672 fill-column:79
00673 indent-tabs-mode:nil
00674 End:
00675 */

Generated on Mon Jan 28 19:38:29 2008 for Cgroggs by  doxygen 1.4.6