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 */
1.4.6