From cf03dfcf416efe1bac9a8ff5e87bd5eb06793ec8 Mon Sep 17 00:00:00 2001 From: H Jalfi Date: Sat, 18 Feb 2006 12:26:22 +0000 Subject: [PATCH] Initial import. --- gaim-citadel/COPYING | 341 ++++++++++++++++++++ gaim-citadel/c.pm | 147 +++++++++ gaim-citadel/citadel.c | 571 +++++++++++++++++++++++++++++++++ gaim-citadel/citadel.lua | 678 +++++++++++++++++++++++++++++++++++++++ gaim-citadel/gaim.pkg | 359 +++++++++++++++++++++ gaim-citadel/interface.h | 24 ++ gaim-citadel/pm | Bin 0 -> 81862 bytes gaim-citadel/pmfile | 50 +++ 8 files changed, 2170 insertions(+) create mode 100644 gaim-citadel/COPYING create mode 100644 gaim-citadel/c.pm create mode 100644 gaim-citadel/citadel.c create mode 100644 gaim-citadel/citadel.lua create mode 100644 gaim-citadel/gaim.pkg create mode 100644 gaim-citadel/interface.h create mode 100755 gaim-citadel/pm create mode 100644 gaim-citadel/pmfile diff --git a/gaim-citadel/COPYING b/gaim-citadel/COPYING new file mode 100644 index 000000000..21b9363e1 --- /dev/null +++ b/gaim-citadel/COPYING @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gaim-citadel/c.pm b/gaim-citadel/c.pm new file mode 100644 index 000000000..3894453b1 --- /dev/null +++ b/gaim-citadel/c.pm @@ -0,0 +1,147 @@ +-- Prime Mover C plugin. +-- © 2006 David Given. +-- +-- This code is part of Prime Mover and is licensed under the MIT public +-- license. + +-- pm includefile to compile *host* C programs. + +-- Standard Lua boilerplate. + +local io_open = io.open +local string_gsub = string.gsub +local string_gfind = string.gfind +local table_insert = table.insert +local table_getn = table.getn +local filetime = pm.filetime + +-- Define some variables. + +CC = "gcc %CBUILDFLAGS% %CDYNINCLUDES% %CINCLUDES% %CEXTRAFLAGS% -c -o %out% %in%" +CPROGRAM = "gcc %CBUILDFLAGS% %CLINKFLAGS% %CEXTRAFLAGS% -o %out% %in% %CLIBRARIES%" +CDEPENDS = "gcc %CBUILDFLAGS% %CDYNINCLUDES% %CINCLUDES% %CEXTRAFLAGS% -MM -MG -MF %out% %in%" +AR = "%RM% %out% && ar cr %out% %in%" + +CBUILDFLAGS = "-g -Os" +CINCLUDES = {} +CEXTRAFLAGS = "" +CLINKFLAGS = "" +CDYNINCLUDES = "" +CLIBRARIES = "" + +--- Manage C file dependencies ---------------------------------------------- + +local dependency_cache = {} +local function load_dependency_file(fn) + local o = dependency_cache[fn] + if o then + return o + end + + -- Read in the dependency file. + + local f = io_open(fn) + if not f then + print("failed to open "..fn) + return nil + end + f = f:read("*a") + + -- Massage the dependency file into a string containing one unescaped + -- filename per line. + + f = string_gsub(f, "^.*[^\\]: *", "") + f = string_gsub(f, "\\\r?\n", "") + f = string_gsub(f, "([^\\]) +", "%1\n") + f = string_gsub(f, "\\", "") + + -- Parse the string. + + o = {} + for l in string_gfind(f, "[^\n]+") do + table_insert(o, l) + end + + dependency_cache[fn] = o + return o +end + +-- This clause specialises 'simple' to add support for smart dependencies of C +-- files. + +simple_with_clike_dependencies = simple { + class = "simple_with_clike_dependencies", + makedepends = {"%CDEPENDS%"}, + + __init = function(self, p) + simple.__init(self, p) + + -- If we're a class, don't verify. + + if ((type(p) == "table") and p.class) then + return + end + + -- If dynamicheaders is an object, turn it into a singleton list. + + if self.dynamicheaders then + if (type(self.dynamicheaders) ~= "table") then + self:__error("doesn't know what to do with dynamicheaders, which ", + "should be a list or an object but was a ", type(self.dynamicheaders)) + end + if self.dynamicheaders.class then + self.dynamicheaders = {self.dynamicheaders} + end + end + end, + + __dependencies = function(self, inputs, outputs) + local obj = simple { + CDYNINCLUDES = self.CDYNINCLUDES, + command = self.makedepends, + outputs = {"%U%-%I%.d"}, + unpack(inputs) + } + local o = obj:__build() + local depends = load_dependency_file(o[1]) + if not depends then + self:__error("could not determine the dependencies for ", + pm.rendertable(inputs)) + end + return depends + end, + + __buildadditionalchildren = function(self) + self.CDYNINCLUDES = "" + if self.dynamicheaders then + for _, i in ipairs(self.dynamicheaders) do + local o = i:__build() + if o[1] then + self.CDYNINCLUDES = self.CDYNINCLUDES..' "-I'..string_gsub(o[1], "/[^/]*$", "")..'"' + end + end + end + end +} + +-- These are the publically useful clauses. + +cfile = simple_with_clike_dependencies { + class = "cfile", + command = {"%CC%"}, + outputs = {"%U%-%I%.o"}, +} + +cprogram = simple { + class = "cprogram", + command = {"%CPROGRAM%"}, + outputs = {"%U%-%I%"}, +} + +clibrary = simple { + class = "clibrary", + command = { + "%AR%" + }, + outputs = {"%U%-%I%.a"}, +} diff --git a/gaim-citadel/citadel.c b/gaim-citadel/citadel.c new file mode 100644 index 000000000..c33541c9d --- /dev/null +++ b/gaim-citadel/citadel.c @@ -0,0 +1,571 @@ +/* citadel.c + * Gaim Citadel plugin. + * + * © 2006 David Given. + * This code is licensed under the GPL v2. See the file COPYING in this + * directory for the full license text. + * + * $Id: auth.c 4258 2006-01-29 13:34:44 +0000 (Sun, 29 Jan 2006) dothebart $ + */ + +#define GAIM_PLUGINS +#include "internal.h" +#include "accountopt.h" +#include "blist.h" +#include "conversation.h" +#include "debug.h" +#include "notify.h" +#include "prpl.h" +#include "plugin.h" +#include "util.h" +#include "version.h" +#include "sslconn.h" + +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +#include "interface.h" + +extern int tolua_gaim_open(lua_State* L); +extern void tolua_gaim_close(lua_State* L); + +#define VERSION "0.2" +#define CITADEL_DEFAULT_SERVER "uncensored.citadel.org" +#define CITADEL_DEFAULT_PORT 504 +#define CITADEL_POLL_INTERVAL 10 +#define LUA_MICROCODE "/plugindata/citadel.lua" + +struct citadel { + GaimAccount* ga; + GaimConnection* gc; + GaimSslConnection* gsc; + int fd; + lua_State* L; +}; + +static GaimConnection* hackgc; + +/* ======================================================================= */ +/* LUA CALLIN */ +/* ======================================================================= */ + +static void wrappedcall(lua_State* L, int inparams, int outparams) +{ + int i; + + i = lua_pcall(L, inparams, outparams, 0); + if (i) + { + gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error: %s\n", + lua_tostring(L, -1)); + gaim_connection_error(hackgc, _("Internal error in plugin")); + return; + } + + lua_getglobal(L, "citadel_schedule_now"); + i = lua_pcall(L, 0, 0, 0); + if (i) + { + gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error in scheduler: %s\n", + lua_tostring(L, -1)); + gaim_connection_error(hackgc, _("Internal error in plugin")); + return; + } +} + +/* ======================================================================= */ +/* LUA CALLOUT */ +/* ======================================================================= */ + +/* --- Input ------------------------------------------------------------- */ + +static void input_cb(gpointer data, gint fd, GaimInputCondition cond) +{ + GaimConnection* gc = data; + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_input"); + wrappedcall(L, 0, 0); +} + +static void input_ssl_cb(gpointer data, GaimSslConnection* gsc, GaimInputCondition cond) +{ + GaimConnection* gc = data; + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_input"); + wrappedcall(L, 0, 0); +} + +char* interface_readdata(int fd, GaimSslConnection* gsc) +{ + static char buffer[1024]; + int len; + + /* Read in some data. */ + + if (gsc) + len = gaim_ssl_read(gsc, buffer, sizeof(buffer)-1); + else + len = read(fd, buffer, sizeof(buffer)-1); + + if (len <= 0) + return NULL; + + buffer[len] = '\0'; + return buffer; +} + +int interface_writedata(int fd, GaimSslConnection* gsc, char* buffer) +{ + int len = strlen(buffer); + char* p = buffer; + + while (len > 0) + { + int i; + + if (gsc) + i = gaim_ssl_write(gsc, p, len); + else + i = write(fd, p, len); + + if (i < 0) + return 1; + + p += i; + len -= i; + } + + return 0; +} + +/* --- Connection -------------------------------------------------------- */ + +static void login_cb(gpointer data, gint fd, GaimInputCondition cond) +{ + GaimConnection* gc = data; + lua_State* L = gc->proto_data; + + if (fd < 0) + { + gaim_connection_error(gc, _("Couldn't connect to host")); + return; + } + + if (!g_list_find(gaim_connections_get_all(), gc)) + { + close(fd); + return; + } + + /* Register the input event handler. */ + + gc->inpa = gaim_input_add(fd, GAIM_INPUT_READ, input_cb, gc); + + /* Register this file descriptor and tell Lua. */ + + lua_getglobal(L, "citadel_setfd"); + lua_pushnumber(L, fd); + wrappedcall(L, 1, 0); +} + +int interface_connect(GaimAccount* ga, GaimConnection* gc, + char* server, int port) +{ + return gaim_proxy_connect(ga, server, port, login_cb, gc); +} + +void interface_disconnect(int fd, GaimSslConnection* gsc) +{ + if (gsc) + gaim_ssl_close(gsc); + else if (fd >= 0) + close(fd); +} + +/* --- TLS setup --------------------------------------------------------- */ + +static void ssl_setup_cb(gpointer data, GaimSslConnection* gsc, + GaimInputCondition cond) +{ + GaimConnection* gc = data; + lua_State* L = gc->proto_data; + + if (!g_list_find(gaim_connections_get_all(), gc)) + { + gaim_ssl_close(gsc); + return; + } + + gaim_debug(GAIM_DEBUG_MISC, "citadel", "using gsc %p\n", gsc); + gaim_ssl_input_add(gsc, input_ssl_cb, gc); + + /* Register this file descriptor and tell Lua. */ + + lua_getglobal(L, "citadel_setgsc"); + { + GaimSslConnection** o = lua_newuserdata(L, sizeof(GaimSslConnection)); + *o = gsc; + } + wrappedcall(L, 1, 0); +} + +static void ssl_failure_cb(GaimSslConnection *gsc, GaimSslErrorType error, + gpointer data) +{ + GaimConnection* gc = data; + + switch(error) + { + case GAIM_SSL_CONNECT_FAILED: + gaim_connection_error(gc, _("Connection Failed")); + break; + + case GAIM_SSL_HANDSHAKE_FAILED: + gaim_connection_error(gc, _("SSL Handshake Failed")); + break; + } +} + +void interface_tlson(GaimConnection* gc, GaimAccount* ga, int fd) +{ + gaim_input_remove(gc->inpa); + gc->inpa = 0; + gaim_ssl_connect_fd(ga, fd, ssl_setup_cb, ssl_failure_cb, gc); +} + +/* --- Timer ------------------------------------------------------------- */ + +static gboolean timer_cb(gpointer data) +{ + struct lua_State* L = data; + + lua_getglobal(L, "citadel_timer"); + wrappedcall(L, 0, 0); + return TRUE; +} + +int interface_timeron(GaimConnection* gc, time_t interval) +{ + return gaim_timeout_add(interval, timer_cb, gc->proto_data); +} + +void interface_timeroff(GaimConnection* gc, int timerhandle) +{ + gaim_timeout_remove(timerhandle); +} + +/* ======================================================================= */ +/* CONNECT/DISCONNECT */ +/* ======================================================================= */ + +static void citadel_login(GaimAccount *account) +{ + GaimConnection* gc; + lua_State* L; + int i; + + /* Set up account settings. */ + + hackgc = gc = gaim_account_get_connection(account); + gc->flags |= GAIM_CONNECTION_NO_BGCOLOR + | GAIM_CONNECTION_FORMATTING_WBFO + | GAIM_CONNECTION_NO_FONTSIZE + | GAIM_CONNECTION_NO_URLDESC + | GAIM_CONNECTION_NO_IMAGES; + + /* Initialise our private data. */ + + gc->proto_data = L = lua_open(); + luaopen_base(L); + luaopen_table(L); + luaopen_string(L); + luaopen_math(L); + luaopen_debug(L); + luaopen_io(L); + tolua_gaim_open(L); + + /* Register our private library. */ + +// luaL_openlib(L, "gaimi", gaim_library, 0); + + /* Load in our 'microcode'. */ + + { + GString* microcode = g_string_new(gaim_user_dir()); + g_string_append(microcode, LUA_MICROCODE); + + + gaim_debug(GAIM_DEBUG_MISC, "citadel", "loading %s\n", microcode->str); + i = luaL_loadfile(L, microcode->str) || + lua_pcall(L, 0, 0, 0); + g_string_free(microcode, TRUE); + + if (i) + { + gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error on load: %s\n", + lua_tostring(L, -1)); + gaim_connection_error(gc, _("Unable to initialise plugin")); + return; + } + } + + /* Set the reentrancy counter. */ + + lua_pushnumber(L, 0); + lua_setglobal(L, " entrycount"); + + /* Tell the script to start connecting. */ + + lua_getglobal(L, "citadel_connect"); + { + GaimAccount** o = lua_newuserdata(L, sizeof(GaimAccount*)); + *o = account; + } + wrappedcall(L, 1, 0); +} + +static void citadel_close(GaimConnection* gc) +{ + lua_State* L = gc->proto_data; + + if (gc->inpa) + { + gaim_input_remove(gc->inpa); + gc->inpa = 0; + } + + if (L) + { + gaim_debug(GAIM_DEBUG_MISC, "citadel", "telling lua to disconnect\n"); + lua_getglobal(L, "citadel_close"); + wrappedcall(L, 0, 0); + } + + gaim_debug(GAIM_DEBUG_MISC, "citadel", "destroying lua VM\n"); + lua_close(L); +} + +/* ======================================================================= */ +/* MESSAGING */ +/* ======================================================================= */ + +static int citadel_send_im(GaimConnection* gc, const char* who, + const char* what, GaimConvImFlags flags) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_send_im"); + lua_pushstring(L, who); + lua_pushstring(L, what); + lua_pushnumber(L, flags); + wrappedcall(L, 3, 0); + + return 1; +} + +/* ======================================================================= */ +/* PRESENCE */ +/* ======================================================================= */ + +void citadel_add_buddy(GaimConnection* gc, GaimBuddy* buddy, GaimGroup* group) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_add_buddy"); + lua_pushstring(L, buddy->name); + wrappedcall(L, 1, 0); +} + +void citadel_remove_buddy(GaimConnection* gc, GaimBuddy* buddy, GaimGroup* group) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_remove_buddy"); + lua_pushstring(L, buddy->name); + wrappedcall(L, 1, 0); +} + +void citadel_alias_buddy(GaimConnection* gc, const char* who, const char* alias) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_alias_buddy"); + lua_pushstring(L, who); + wrappedcall(L, 1, 0); +} + +void citadel_group_buddy(GaimConnection* gc, const char *who, + const char *old_group, const char *new_group) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_group_buddy"); + lua_pushstring(L, who); + lua_pushstring(L, old_group); + lua_pushstring(L, new_group); + wrappedcall(L, 3, 0); +} + +/* This is really just to fill out a hole in the gaim API. */ + +const char* gaim_group_get_name(GaimGroup* group) +{ + return group->name; +} + +/* ======================================================================= */ +/* USER INFO */ +/* ======================================================================= */ + +void citadel_get_info(GaimConnection* gc, const char* name) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_get_info"); + lua_pushstring(L, name); + wrappedcall(L, 1, 0); +} + +/* ======================================================================= */ +/* MISCELLANEOUS */ +/* ======================================================================= */ + +static void citadel_keepalive(GaimConnection* gc) +{ + lua_State* L = gc->proto_data; + + lua_getglobal(L, "citadel_keepalive"); + wrappedcall(L, 0, 0); +} + +static const char* citadel_list_icon(GaimAccount* a, GaimBuddy* b) +{ + return "citadel"; +} + +static void citadel_list_emblems(GaimBuddy* b, char** se, char** sw, + char** nw, char** ne) +{ + if (b->present == GAIM_BUDDY_OFFLINE) + *se = "offline"; +} + +/* ======================================================================= */ +/* PLUGIN SETUP */ +/* ======================================================================= */ + +static GaimPluginProtocolInfo protocol = +{ + OPT_PROTO_CHAT_TOPIC, + NULL, /* user_splits */ + NULL, /* protocol_options */ + NO_BUDDY_ICONS, /* icon_spec */ + citadel_list_icon, /* list_icon */ + citadel_list_emblems, /* list_emblems */ + NULL, /* status_text */ + NULL, /* tooltip_text */ + NULL, //irc_away_states, /* away_states */ + NULL, /* blist_node_menu */ + NULL, //irc_chat_join_info, /* chat_info */ + NULL, //irc_chat_info_defaults, /* chat_info_defaults */ + citadel_login, /* login */ + citadel_close, /* close */ + citadel_send_im, /* send_im */ + NULL, /* set_info */ + NULL, /* send_typing */ + citadel_get_info, /* get_info */ + NULL, //irc_set_away, /* set_away */ + NULL, /* set_idle */ + NULL, /* change_passwd */ + citadel_add_buddy, /* add_buddy */ + NULL, /* add_buddies */ + citadel_remove_buddy, /* remove_buddy */ + NULL, /* remove_buddies */ + NULL, /* add_permit */ + NULL, /* add_deny */ + NULL, /* rem_permit */ + NULL, /* rem_deny */ + NULL, /* set_permit_deny */ + NULL, /* warn */ + NULL, //irc_chat_join, /* join_chat */ + NULL, /* reject_chat */ + NULL, //irc_get_chat_name, /* get_chat_name */ + NULL, //irc_chat_invite, /* chat_invite */ + NULL, //irc_chat_leave, /* chat_leave */ + NULL, /* chat_whisper */ + NULL, //irc_chat_send, /* chat_send */ + citadel_keepalive, /* keepalive */ + NULL, /* register_user */ + NULL, /* get_cb_info */ + NULL, /* get_cb_away */ + citadel_alias_buddy, /* alias_buddy */ + citadel_group_buddy, /* group_buddy */ + NULL, /* rename_group */ + NULL, /* buddy_free */ + NULL, /* convo_closed */ + gaim_normalize_nocase, /* normalize */ + NULL, /* set_buddy_icon */ + NULL, /* remove_group */ + NULL, /* get_cb_real_name */ + NULL, //irc_chat_set_topic, /* set_chat_topic */ + NULL, /* find_blist_chat */ + NULL, //irc_roomlist_get_list, /* roomlist_get_list */ + NULL, //irc_roomlist_cancel, /* roomlist_cancel */ + NULL, /* roomlist_expand_category */ + NULL, /* can_receive_file */ + NULL, //irc_dccsend_send_file /* send_file */ +}; + +static GaimPluginInfo info = +{ + GAIM_PLUGIN_MAGIC, + GAIM_MAJOR_VERSION, + GAIM_MINOR_VERSION, + GAIM_PLUGIN_PROTOCOL, /**< type */ + NULL, /**< ui_requirement */ + 0, /**< flags */ + NULL, /**< dependencies */ + GAIM_PRIORITY_DEFAULT, /**< priority */ + + "prpl-citadel", /**< id */ + "Citadel", /**< name */ + VERSION, /**< version */ + N_("Citadel Protocol Plugin"), /** summary */ + N_("Instant Messaging via Citadel"), /** description */ + NULL, /**< author */ + GAIM_WEBSITE, /**< homepage */ + + NULL, /**< load */ + NULL, /**< unload */ + NULL, /**< destroy */ + + NULL, /**< ui_info */ + &protocol, /**< extra_info */ + NULL, /**< prefs_info */ + NULL +}; + +static void _init_plugin(GaimPlugin *plugin) +{ + GaimAccountUserSplit *split; + GaimAccountOption *option; + + split = gaim_account_user_split_new(_("Server"), CITADEL_DEFAULT_SERVER, '@'); + protocol.user_splits = g_list_append(protocol.user_splits, split); + + option = gaim_account_option_int_new(_("Port"), "port", CITADEL_DEFAULT_PORT); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); + + option = gaim_account_option_bool_new(_("Use TLS"), "use_tls", TRUE); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); + + option = gaim_account_option_int_new(_("Polling interval"), "interval", CITADEL_POLL_INTERVAL); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); + + gaim_prefs_add_none("/plugins/prpl/citadel"); +} + +GAIM_INIT_PLUGIN(citadel, _init_plugin, info); diff --git a/gaim-citadel/citadel.lua b/gaim-citadel/citadel.lua new file mode 100644 index 000000000..71b3110d5 --- /dev/null +++ b/gaim-citadel/citadel.lua @@ -0,0 +1,678 @@ +-- citadel.lua +-- Gaim Citadel plugin. +-- +-- © 2006 David Given. +-- This code is licensed under the GPL v2. See the file COPYING in this +-- directory for the full license text. +-- +-- $Id: auth.c 4258 2006-01-29 13:34:44 +0000 (Sun, 29 Jan 2006) dothebart $ + +----------------------------------------------------------------------------- +-- GLOBALS -- +----------------------------------------------------------------------------- + +local _ +local username, servername, port +local ga, gc +local fd, gsc +local timerhandle +local buddies = {} + +----------------------------------------------------------------------------- +-- CONSTANTS -- +----------------------------------------------------------------------------- + +-- Special values returned as Citadel's response codes. + +local LISTING_FOLLOWS = 100 +local CIT_OK = 200 +local MORE_DATA = 300 +local SEND_LISTING = 400 +local ERROR = 500 +local BINARY_FOLLOWS = 600 +local SEND_BINARY = 700 +local START_CHAT_MODE = 800 + +local INTERNAL_ERROR = 10 +local TOO_BIG = 11 +local ILLEGAL_VALUE = 12 +local NOT_LOGGED_IN = 20 +local CMD_NOT_SUPPORTED = 30 +local PASSWORD_REQUIRED = 40 +local ALREADY_LOGGED_IN = 41 +local USERNAME_REQUIRED = 42 +local HIGHER_ACCESS_REQUIRED = 50 +local MAX_SESSIONS_EXCEEDED = 51 +local RESOURCE_BUSY = 52 +local RESOURCE_NOT_OPEN = 53 +local NOT_HERE = 60 +local INVALID_FLOOR_OPERATION = 61 +local NO_SUCH_USER = 70 +local FILE_NOT_FOUND = 71 +local ROOM_NOT_FOUND = 72 +local NO_SUCH_SYSTEM = 73 +local ALREADY_EXISTS = 74 +local MESSAGE_NOT_FOUND = 75 + +local ASYNC_MSG = 900 +local ASYNC_GEXP = 02 + +-- Other Citadel settings. + +local CITADEL_DEFAULT_PORT = 504 +local CITADEL_CONFIG_ROOM = "My Citadel Config" +local CITADEL_BUDDY_MSG = "__ Buddy List __" +local CITADEL_POLL_INTERVAL = 5 + +----------------------------------------------------------------------------- +-- UTILITIES -- +----------------------------------------------------------------------------- + +--local stderr = io.stderr + +local function log(...) + local s = {} + for _, i in ipairs(arg) do + table.insert(s, tostring(i)) + end + print("citadel: lua: "..table.concat(s)) +end + +local function unexpectederror() + error("The Citadel server said something unexpected. Giving up.") +end + +local function warning(...) + local s = {} + for _, i in ipairs(arg) do + table.insert(s, tostring(i)) + end + gaim_connection_notice(gc, s) +end + +local olderror = error +error = function(e) + log("error: ", e) + log("traceback: ", debug.traceback()) + olderror(e) +end + +----------------------------------------------------------------------------- +-- SCHEDULER -- +----------------------------------------------------------------------------- + +local taskqueue = {} +local idle +local inscheduler = false + +local yield = coroutine.yield + +local function schedule_now() + if not inscheduler then + inscheduler = true + + while taskqueue[1] do + -- Pull the first task off the queue, creating it if necessary. + + local task = taskqueue[1] + if (type(task) == "function") then + task = coroutine.create(task) + taskqueue[1] = task + end + + -- Run it. + + local s, e = coroutine.resume(task) + if not s then + log("error: ", e) + log("traceback: ", debug.traceback()) + gaim_connection_error(gc, e) + end + + -- If it's not dead, then it must have yielded --- return back to C. + + if (coroutine.status(task) ~= "dead") then + break + end + + -- Otherwise, remove it from the queue and go again. + + table.remove(taskqueue, 1) + end + + inscheduler = false + end +end + +local function queue(func) + table.insert(taskqueue, func) +--[[ + table.insert(taskqueue, function() + local i, e = pcall(func) + if not i then + log("coroutine died with error! ", e) + gaim_connection_error(gc, e) + end + end) +--]] +end + +local queued = {} +local function lazyqueue(func) + if not queued[func] then + queued[func] = true + queue( + function() + queued[func] = nil + func() + end) + end +end + +----------------------------------------------------------------------------- +-- INPUT MANGLING -- +----------------------------------------------------------------------------- + +local inputbuffer = "" + +-- Read a single line of text from the server, maing Lua's coroutines do the +-- vast bulk of the work of managing Gaim's state machine for us. Woo! + +local function readline() + -- Always yield at least once. Otherwise, Lua hogs all the CPU time. + + yield() + + while true do + if fd then + -- Read some data from the remote server, if any's + -- available. + + local i = interface_readdata(fd, gsc) + if not i then + error("Unexpected disconnection from Citadel server") + end + + inputbuffer = inputbuffer..i + + -- Have we read a complete line of text? + + local s, e, l = string.find(inputbuffer, "^([^\n]*)\n") + if l then + -- If so, return it. + + inputbuffer = string.sub(inputbuffer, e+1) + return l + end + end + + -- Otherwise, wait some more. + + yield() + end +end + +local function unpack_citadel_data_line(s, a) + a = a or {} + for i in string.gfind(s, "([^|]*)|?") do + table.insert(a, i) + end + return a +end + +-- Read in an parse a packet from the Citadel server. + +local function get_response() + local message = {} + + -- The first line of a message is of the format: + -- 123 String|String|String + -- + -- The 123 is a response code. + + local s = readline() + message.response = tonumber(string.sub(s, 1, 3)) + + s = string.sub(s, 5) + unpack_citadel_data_line(s, message) + + -- If the response code is LISTING_FOLLOWS, then there's more data + -- coming. + + if (message.response == LISTING_FOLLOWS) then + message.xargs = {} + + while true do + s = readline() + if (s == "000") then + break + end + --log("Got xarg: ", s) + table.insert(message.xargs, s) + end + end + + -- If the response code is BINARY_FOLLOWS, there's a big binary chunk + -- coming --- which we don't support. + + if (message.response == BINARY_FOLLOWS) then + error("Server sent a binary chunk, which we don't support yet") + end + + return message +end + +----------------------------------------------------------------------------- +-- OUTPUT MANGLING -- +----------------------------------------------------------------------------- + +local function writeline(...) + local s = table.concat(arg) + + log("send: ", s) + interface_writedata(fd, gsc, s) + interface_writedata(fd, gsc, "\n") +end + +----------------------------------------------------------------------------- +-- PRESENCE MANAGEMENT -- +----------------------------------------------------------------------------- + +local function cant_save_buddy_list() + warning("Unable to send buddy list to server.") +end + +local function save_buddy_list() + writeline("GOTO "..CITADEL_CONFIG_ROOM) + local m = get_response() + if (m.response ~= CIT_OK) then + cant_save_buddy_list() + return + end + + -- Search and destroy any old buddy list. + + writeline("MSGS ALL|0|1") + m = get_response() + if (m.response ~= START_CHAT_MODE) then + cant_save_buddy_list() + return + end + + writeline("subj|"..CITADEL_BUDDY_MSG) + writeline("000") + m = nil + while true do + local s = readline() + if (s == "000") then + break + end + if (not m) and (s ~= "000") then + m = s + end + end + + if m then + writeline("DELE "..m) + m = get_response() + if (m.response ~= CIT_OK) then + cant_save_buddy_list() + return + end + end + + -- Save our buddy list. + + writeline("ENT0 1||0|1|"..CITADEL_BUDDY_MSG.."|") + m = get_response() + if (m.response ~= SEND_LISTING) then + cant_save_buddy_list() + return + end + + for name, _ in pairs(buddies) do + local b = gaim_find_buddy(ga, name) + if b then + local alias = gaim_buddy_get_alias(b) or "" + local group = gaim_find_buddys_group(b) + local groupname = gaim_group_get_name(group) + writeline(name.."|"..alias.."|"..groupname) + end + end + writeline("000") + + -- Go back to the lobby. + + writeline("GOTO _BASEROOM_") + get_response() +end + +local function update_buddy_status() + writeline("RWHO") + local m = get_response() + if (m.response ~= LISTING_FOLLOWS) then + return + end + log("attempting to scan and update buddies") + + local onlinebuddies = {} + for _, s in ipairs(m.xargs) do + local name = unpack_citadel_data_line(s)[2] + onlinebuddies[name] = true + end + + for s, _ in pairs(onlinebuddies) do + serv_got_update(gc, s, true, 0, 0, 0, 0) + end +end + +----------------------------------------------------------------------------- +-- ENTRYPOINTS -- +----------------------------------------------------------------------------- + +function citadel_schedule_now() + schedule_now() +end + +function citadel_input() + -- If there's no task, create one to handle this input. + + if not taskqueue[1] then + queue(idle) + end +end + +function citadel_setfd(_fd) + fd = _fd + log("fd = ", tonumber(fd)) +end + +function citadel_setgsc(_gsc) + gsc = tolua.cast(_gsc, "GaimSslConnection") + log("gsc registered") +end + +function citadel_connect(_ga) + ga = tolua.cast(_ga, "GaimAccount") + gc = gaim_account_get_connection(ga) + + queue(function() + local STEPS = 13 + + username = gaim_account_get_username(ga) + _, _, username, servername = string.find(username, "^(.*)@(.*)$") + port = gaim_account_get_int(ga, "port", CITADEL_DEFAULT_PORT); + + log("connect to ", username, " on server ", servername, " port ", port) + + -- Make connection. + + gaim_connection_update_progress(gc, "Connecting", 1, STEPS) + local i = interface_connect(ga, gc, servername, port) + if (i ~= 0) then + error("Unable to create socket") + end + + local m = get_response() + if (m.response ~= CIT_OK) then + error("Unexpected response from server") + end + + -- Switch to TLS mode, if desired. + + if gaim_account_get_bool(ga, "use_tls", true) then + gaim_connection_update_progress(gc, "Requesting TLS", 2, STEPS) + writeline("STLS") + m = get_response() + if (m.response ~= 200) then + error("This Citadel server does not support TLS.") + end + + -- This will always work. If the handshake fails, Lua will be + -- shot and we don't need to worry about cleaning up. + + gaim_connection_update_progress(gc, "TLS handshake", 3, STEPS) + interface_tlson(gc, ga, fd) + + -- Wait for the gsc to be hooked up. + + while not gsc do + yield() + end + end + + -- Send username. + + gaim_connection_update_progress(gc, "Sending username", 4, STEPS) + writeline("USER "..username) + m = get_response() + if (m.response == (ERROR+NO_SUCH_USER)) then + error("There is no user with name '", username, "' on this server.") + end + if (m.response ~= MORE_DATA) then + unexpectederror() + end + + -- Send password. + + gaim_connection_update_progress(gc, "Sending password", 5, STEPS) + writeline("PASS "..gaim_account_get_password(ga)) + m = get_response() + if (m.response ~= CIT_OK) then + error("Incorrect password.") + end + + -- Tell Citadel who we are. + + gaim_connection_update_progress(gc, "Setting up", 6, STEPS) + writeline("IDEN 226|0|0.2|Gaim Citadel plugin|") + m = get_response() + + -- Set asynchronous mode. + + gaim_connection_update_progress(gc, "Setting up", 7, STEPS) + writeline("ASYN 1") + m = get_response() + if (m.response ~= CIT_OK) then + error("This Citadel server does not support instant messaging.") + end + + (function() + -- Switch to private configuration room. + + gaim_connection_update_progress(gc, "Setting up", 8, STEPS) + writeline("GOTO "..CITADEL_CONFIG_ROOM) + m = get_response() + if (m.response ~= CIT_OK) then + warning("Unable to fetch buddy list from server.") + return + end + + -- Look for our preferences. + + gaim_connection_update_progress(gc, "Setting up", 9, STEPS) + writeline("MSGS ALL|0|1") + m = get_response() + if (m.response ~= START_CHAT_MODE) then + warning("Unable to fetch buddy list from server.") + return + end + + writeline("subj|"..CITADEL_BUDDY_MSG) + writeline("000") + m = nil + while true do + local s = readline() + if (s == "000") then + break + end + if (not m) and (s ~= "000") then + m = s + end + end + + log("preference message in #", m) + if not m then + return + end + + gaim_connection_update_progress(gc, "Setting up", 10, STEPS) + writeline("MSG0 "..m) + while true do + local s = readline() + if (s == "000") then + return + end + if (s == "text") then + break + end + end + while true do + local s = readline() + if (s == "000") then + break + end + + local name, alias, groupname = unpack(unpack_citadel_data_line(s)) + if not gaim_find_buddy(ga, name) then + local buddy = gaim_buddy_new(ga, name, alias) + local group = gaim_group_new(groupname) + log("adding new buddy ", name) + if buddy then + -- buddy is not garbage collected! This must succeed! + gaim_blist_add_buddy(buddy, nil, group, nil) + end + end + end + end)() + + -- Update buddy list with who's online. + + gaim_connection_update_progress(gc, "Setting up", 11, STEPS) + update_buddy_status() + + -- Go back to the Lobby. + + gaim_connection_update_progress(gc, "Setting up", 12, STEPS) + writeline("GOTO _BASEROOM_") + get_response() + + -- Switch on the timer. + + timerhandle = interface_timeron(gc, + gaim_account_get_int(ga, "interval", CITADEL_POLL_INTERVAL)*1000) + + -- Done! + + gaim_connection_update_progress(gc, "Connected", 13, STEPS) + gaim_connection_set_state(gc, GAIM_CONNECTED) + end) +end + +function citadel_close() + interface_disconnect(fd or -1, gsc) + if timerhandle then + interface_timeroff(gc, timerhandle) + end + schedule_now = function() end +end + +function citadel_send_im(who, what, flags) + queue(function() + writeline("SEXP ", who, "|-") + local m = get_response() + if (m.response ~= SEND_LISTING) then + serv_got_im(gc, "Citadel", "Unable to send message", GAIM_MESSAGE_ERROR, 0); + return + end + writeline(what) + writeline("000") + end) +end + +function citadel_fetch_pending_messages() + queue(function() + while true do + writeline("GEXP") + local m = get_response() + if (m.response ~= LISTING_FOLLOWS) then + break + end + + local s = table.concat(m.xargs) + --log("got message from ", m[4], " at ", m[2], ": ", s) + serv_got_im(gc, m[4], s, GAIM_MESSAGE_RECV, m[2]) + end + end) +end + +function citadel_get_info(name) + queue(function() + writeline("RBIO "..name) + local m = get_response() + if (m.response ~= LISTING_FOLLOWS) then + m = "That user has been boojumed." + else + m = table.concat(m.xargs, "
") + end + + gaim_notify_userinfo(gc, name, name.."'s biography", + name, "Biography", m, nil, nil) + end) +end + +function citadel_keepalive() + queue(function() + writeline("NOOP") + get_response() + end) +end + +----------------------------------------------------------------------------- +-- BUDDY LIST -- +----------------------------------------------------------------------------- + +function citadel_add_buddy(name) + if not buddies[name] then + buddies[name] = true + lazyqueue(update_buddy_status) + lazyqueue(save_buddy_list) + end +end + +function citadel_remove_buddy(name) + if buddies[name] then + buddies[name] = nil + lazyqueue(save_buddy_list) + end +end + +function citadel_alias_buddy(name) + if buddies[name] then + lazyqueue(save_buddy_list) + end +end + +function citadel_group_buddy(name, oldgroup, newgroup) + if buddies[name] then + lazyqueue(save_buddy_list) + end +end + +function citadel_timer() + log("tick!") + lazyqueue(update_buddy_status) +end + +----------------------------------------------------------------------------- +-- IDLE -- +----------------------------------------------------------------------------- + +idle = function() + queue(function() + local m = get_response() + if (m.response == (ASYNC_MSG+ASYNC_GEXP)) then + citadel_fetch_pending_messages() + end + end) +end diff --git a/gaim-citadel/gaim.pkg b/gaim-citadel/gaim.pkg new file mode 100644 index 000000000..25183ce01 --- /dev/null +++ b/gaim-citadel/gaim.pkg @@ -0,0 +1,359 @@ +/* gaim.pkg + * Gaim Citadel plugin. + * + * © 2006 David Given. + * This code is licensed under the GPL v2. See the file COPYING in this + * directory for the full license text. + * + * $Id: auth.c 4258 2006-01-29 13:34:44 +0000 (Sun, 29 Jan 2006) dothebart $ + */ + +typedef unsigned int size_t; +typedef bool gboolean; +typedef long time_t; +typedef void* GCallback; + +$typedef int bool; +$#include "connection.h" +$#include "sslconn.h" +$#include "account.h" +$#include "conversation.h" +$#include "server.h" +$#include "notify.h" +$#include "util.h" + +$#include "interface.h" + +/* Private entrypoints */ + +char* interface_readdata(int fd, GaimSslConnection* gsc); +int interface_writedata(int fd, GaimSslConnection* gsc, char* data); +int interface_connect(GaimAccount* ga, GaimConnection* gc, char* server, int port); +void interface_disconnect(int fd, GaimSslConnection* gsc); +void interface_tlson(GaimConnection* gc, GaimAccount* ga, int fd); +int interface_timeron(GaimConnection* gc, time_t timeout); +void interface_timeroff(GaimConnection* gc, int handle); + +/* --- connection.h ------------------------------------------------------ */ + +typedef enum +{ + GAIM_CONNECTION_HTML = 0x0001, /**< Connection sends/receives in 'HTML'. */ + GAIM_CONNECTION_NO_BGCOLOR = 0x0002, /**< Connection does not send/receive + background colors. */ + GAIM_CONNECTION_AUTO_RESP = 0x0004, /**< Send auto responses when away. */ + GAIM_CONNECTION_FORMATTING_WBFO = 0x0008, /**< The text buffer must be formatted as a whole */ + GAIM_CONNECTION_NO_NEWLINES = 0x0010, /**< No new lines are allowed in outgoing messages */ + GAIM_CONNECTION_NO_FONTSIZE = 0x0020, /**< Connection does not send/receive font sizes */ + GAIM_CONNECTION_NO_URLDESC = 0x0040, /**< Connection does not support descriptions with links */ + GAIM_CONNECTION_NO_IMAGES = 0x0080 /**< Connection does not support sending of images */ +} GaimConnectionFlags; + +typedef enum +{ + GAIM_DISCONNECTED = 0, /**< Disconnected. */ + GAIM_CONNECTED, /**< Connected. */ + GAIM_CONNECTING /**< Connecting. */ + +} GaimConnectionState; + +void gaim_connection_set_state(GaimConnection *gc, GaimConnectionState state); +void gaim_connection_set_account(GaimConnection *gc, GaimAccount *account); +void gaim_connection_set_display_name(GaimConnection *gc, char *name); +GaimConnectionState gaim_connection_get_state(GaimConnection *gc); +GaimAccount *gaim_connection_get_account(GaimConnection *gc); +char *gaim_connection_get_display_name(GaimConnection *gc); +void gaim_connection_update_progress(GaimConnection *gc, char *text, + size_t step, size_t count); +void gaim_connection_notice(GaimConnection *gc, char *text); +void gaim_connection_error(GaimConnection *gc, char *reason); + +/* --- account.h --------------------------------------------------------- */ + +void gaim_account_request_change_password(GaimAccount *account); +void gaim_account_request_change_user_info(GaimAccount *account); +void gaim_account_set_username(GaimAccount *account, char *username); +void gaim_account_set_password(GaimAccount *account, char *password); +void gaim_account_set_alias(GaimAccount *account, char *alias); +void gaim_account_set_user_info(GaimAccount *account, char *user_info); +void gaim_account_set_buddy_icon(GaimAccount *account, char *icon); +void gaim_account_set_protocol_id(GaimAccount *account, + char *protocol_id); +void gaim_account_set_remember_password(GaimAccount *account, gboolean value); +void gaim_account_set_check_mail(GaimAccount *account, gboolean value); +void gaim_account_set_auto_login(GaimAccount *account, char *ui, + gboolean value); +void gaim_account_set_proxy_info(GaimAccount *account, GaimProxyInfo *info); +void gaim_account_clear_settings(GaimAccount *account); +void gaim_account_set_int(GaimAccount *account, char *name, int value); +void gaim_account_set_string(GaimAccount *account, char *name, + char *value); +void gaim_account_set_bool(GaimAccount *account, char *name, + gboolean value); +void gaim_account_set_ui_int(GaimAccount *account, char *ui, + char *name, int value); +void gaim_account_set_ui_string(GaimAccount *account, char *ui, + char *name, char *value); +void gaim_account_set_ui_bool(GaimAccount *account, char *ui, + char *name, gboolean value); +gboolean gaim_account_is_connected(GaimAccount *account); +char *gaim_account_get_username(GaimAccount *account); +char *gaim_account_get_password(GaimAccount *account); +char *gaim_account_get_alias(GaimAccount *account); +char *gaim_account_get_user_info(GaimAccount *account); +char *gaim_account_get_buddy_icon(GaimAccount *account); +char *gaim_account_get_protocol_id(GaimAccount *account); +char *gaim_account_get_protocol_name(GaimAccount *account); +GaimConnection *gaim_account_get_connection(GaimAccount *account); +gboolean gaim_account_get_remember_password(GaimAccount *account); +gboolean gaim_account_get_check_mail(GaimAccount *account); +gboolean gaim_account_get_auto_login(GaimAccount *account, char *ui); +int gaim_account_get_int(GaimAccount *account, char *name, int default_value); +char *gaim_account_get_string(GaimAccount *account, char *name, char *default_value); +gboolean gaim_account_get_bool(GaimAccount *account, char *name, gboolean default_value); +int gaim_account_get_ui_int(GaimAccount *account, char *ui, char *name, int default_value); +char *gaim_account_get_ui_string(GaimAccount *account, char *ui, char *name, char *default_value); +gboolean gaim_account_get_ui_bool(GaimAccount *account, char *ui, char *name, gboolean default_value); + +/* --- server.h ---------------------------------------------------------- */ + +void serv_login(GaimAccount *); +void serv_close(GaimConnection *); +void serv_touch_idle(GaimConnection *); +int serv_send_im(GaimConnection *, const char *, const char *, GaimConvImFlags); +void serv_get_info(GaimConnection *, const char *); +void serv_set_idle(GaimConnection *, int); +void serv_set_info(GaimConnection *, const char *); +void serv_set_away(GaimConnection *, const char *, const char *); +void serv_set_away_all(const char *); +int serv_send_typing(GaimConnection *, const char *, int); +void serv_change_passwd(GaimConnection *, const char *, const char *); +void serv_add_buddy(GaimConnection *, GaimBuddy *); +void serv_add_buddies(GaimConnection *, GList *); +void serv_remove_buddy(GaimConnection *, GaimBuddy *, GaimGroup *); +void serv_remove_buddies(GaimConnection *, GList *, GList *); +void serv_remove_group(GaimConnection *, GaimGroup *); +void serv_move_buddy(GaimBuddy *, GaimGroup *, GaimGroup *); +void serv_rename_group(GaimConnection *, const char *, GaimGroup *, GList *); +void serv_add_permit(GaimConnection *, const char *); +void serv_add_deny(GaimConnection *, const char *); +void serv_rem_permit(GaimConnection *, const char *); +void serv_rem_deny(GaimConnection *, const char *); +void serv_set_permit_deny(GaimConnection *); +void serv_warn(GaimConnection *, const char *, gboolean); +void serv_join_chat(GaimConnection *, GHashTable *); +void serv_reject_chat(GaimConnection *, GHashTable *); +void serv_chat_invite(GaimConnection *, int, const char *, const char *); +void serv_chat_leave(GaimConnection *, int); +void serv_chat_whisper(GaimConnection *, int, const char *, const char *); +int serv_chat_send(GaimConnection *, int, const char *); +void serv_alias_buddy(GaimBuddy *); +void serv_got_alias(GaimConnection *gc, const char *who, const char *alias); +void serv_got_eviled(GaimConnection *gc, const char *name, int lev); +void serv_got_typing(GaimConnection *gc, const char *name, int timeout, + GaimTypingState state); +void serv_set_buddyicon(GaimConnection *gc, const char *filename); +void serv_got_typing_stopped(GaimConnection *gc, const char *name); +void serv_got_im(GaimConnection *gc, const char *who, const char *msg, + GaimConvImFlags imflags, time_t mtime); +void serv_got_update(GaimConnection *gc, const char *name, gboolean loggedin, + int evil, time_t signon, time_t idle, int type); +void serv_finish_login(GaimConnection *gc); +void serv_got_chat_invite(GaimConnection *gc, const char *name, + const char *who, const char *message, + GHashTable *data); +GaimConversation *serv_got_joined_chat(GaimConnection *gc, + int id, const char *name); +void serv_got_chat_left(GaimConnection *g, int id); +void serv_got_chat_in(GaimConnection *g, int id, const char *who, + GaimConvChatFlags chatflags, const char *message, time_t mtime); +void serv_send_file(GaimConnection *gc, const char *who, const char *file); + +/* --- conversation.h ---------------------------------------------------- */ + +typedef enum +{ + GAIM_CONV_UNKNOWN = 0, /**< Unknown conversation type. */ + GAIM_CONV_IM, /**< Instant Message. */ + GAIM_CONV_CHAT, /**< Chat room. */ + GAIM_CONV_MISC /**< A misc. conversation. */ + +} GaimConversationType; + +typedef enum +{ + GAIM_UNSEEN_NONE = 0, /**< No unseen text in the conversation. */ + GAIM_UNSEEN_TEXT, /**< Unseen text in the conversation. */ + GAIM_UNSEEN_NICK, /**< Unseen text and the nick was said. */ + GAIM_UNSEEN_EVENT /**< Unseen events in the conversation. */ + +} GaimUnseenState; + +typedef enum +{ + GAIM_CONV_UPDATE_ADD = 0, /**< The buddy associated with the conversation + was added. */ + GAIM_CONV_UPDATE_REMOVE, /**< The buddy associated with the conversation + was removed. */ + GAIM_CONV_UPDATE_ACCOUNT, /**< The gaim_account was changed. */ + GAIM_CONV_UPDATE_TYPING, /**< The typing state was updated. */ + GAIM_CONV_UPDATE_UNSEEN, /**< The unseen state was updated. */ + GAIM_CONV_UPDATE_LOGGING, /**< Logging for this conversation was + enabled or disabled. */ + GAIM_CONV_UPDATE_TOPIC, /**< The topic for a chat was updated. */ + /* + * XXX These need to go when we implement a more generic core/UI event + * system. + */ + GAIM_CONV_ACCOUNT_ONLINE, /**< One of the user's accounts went online. */ + GAIM_CONV_ACCOUNT_OFFLINE, /**< One of the user's accounts went offline. */ + GAIM_CONV_UPDATE_AWAY, /**< The other user went away. */ + GAIM_CONV_UPDATE_ICON, /**< The other user's buddy icon changed. */ + GAIM_CONV_UPDATE_TITLE, + GAIM_CONV_UPDATE_CHATLEFT, + + GAIM_CONV_UPDATE_FEATURES /**< The features for a chat have changed */ + +} GaimConvUpdateType; + +typedef enum +{ + GAIM_NOT_TYPING = 0, /**< Not typing. */ + GAIM_TYPING, /**< Currently typing. */ + GAIM_TYPED /**< Stopped typing momentarily. */ + +} GaimTypingState; + +typedef enum +{ + GAIM_MESSAGE_SEND = 0x0001, /**< Outgoing message. */ + GAIM_MESSAGE_RECV = 0x0002, /**< Incoming message. */ + GAIM_MESSAGE_SYSTEM = 0x0004, /**< System message. */ + GAIM_MESSAGE_AUTO_RESP = 0x0008, /**< Auto response. */ + GAIM_MESSAGE_COLORIZE = 0x0010, /**< Colorize nicks. */ + GAIM_MESSAGE_NICK = 0x0020, /**< Contains your nick. */ + GAIM_MESSAGE_NO_LOG = 0x0040, /**< Do not log. */ + GAIM_MESSAGE_WHISPER = 0x0080, /**< Whispered message. */ + GAIM_MESSAGE_ERROR = 0x0200, /**< Error message. */ + GAIM_MESSAGE_DELAYED = 0x0400 /**< Delayed message. */ +} GaimMessageFlags; + +typedef enum +{ + GAIM_CBFLAGS_NONE = 0x0000, /**< No flags */ + GAIM_CBFLAGS_VOICE = 0x0001, /**< Voiced user or "Participant" */ + GAIM_CBFLAGS_HALFOP = 0x0002, /**< Half-op */ + GAIM_CBFLAGS_OP = 0x0004, /**< Channel Op or Moderator */ + GAIM_CBFLAGS_FOUNDER = 0x0008 /**< Channel Founder */ +} GaimConvChatBuddyFlags; + +/* --- prpl.h ------------------------------------------------------------ */ + +typedef enum +{ + GAIM_CONV_IM_AUTO_RESP = 0x0001, /**< Auto response. */ + GAIM_CONV_IM_IMAGES = 0x0002 /**< Contains images. */ +} GaimConvImFlags; + +typedef enum +{ + GAIM_CONV_CHAT_WHISPER = 0x0001, /**< Whispered message.*/ + GAIM_CONV_CHAT_DELAYED = 0x0002 /**< Delayed message. */ + +} GaimConvChatFlags; + +typedef enum { + GAIM_ICON_SCALE_DISPLAY = 0x01, /**< We scale the icon when we display it */ + GAIM_ICON_SCALE_SEND = 0x02 /**< We scale the icon before we send it to the server */ +} GaimIconScaleRules; + +/* --- blist.h ----------------------------------------------------------- */ + +typedef enum +{ + GAIM_BLIST_GROUP_NODE, + GAIM_BLIST_CONTACT_NODE, + GAIM_BLIST_BUDDY_NODE, + GAIM_BLIST_CHAT_NODE, + GAIM_BLIST_OTHER_NODE + +} GaimBlistNodeType; + +typedef enum +{ + GAIM_BUDDY_SIGNING_OFF = -1, + GAIM_BUDDY_OFFLINE = 0, + GAIM_BUDDY_ONLINE, + GAIM_BUDDY_SIGNING_ON + +} GaimBuddyPresenceState; + +GaimGroup *gaim_group_new(const char *name); +GaimGroup *gaim_find_buddys_group(GaimBuddy *buddy); +GaimBuddy *gaim_buddy_new(GaimAccount *account, const char *screenname, const char *alias); +const char *gaim_group_get_name(GaimGroup *group); // fake --- added by plugin +const char *gaim_buddy_get_alias_only(GaimBuddy *buddy); +const char *gaim_buddy_get_contact_alias(GaimBuddy *buddy); +const char *gaim_buddy_get_alias(GaimBuddy *buddy); +GaimBuddy *gaim_find_buddy(GaimAccount *account, const char *name); +void gaim_blist_add_buddy(GaimBuddy *buddy, GaimContact *contact, GaimGroup *group, GaimBlistNode *node); + +/* --- notify.h ---------------------------------------------------------- */ + +typedef enum +{ + GAIM_NOTIFY_MESSAGE = 0, /**< Message notification. */ + GAIM_NOTIFY_EMAIL, /**< Single e-mail notification. */ + GAIM_NOTIFY_EMAILS, /**< Multiple e-mail notification. */ + GAIM_NOTIFY_FORMATTED, /**< Formatted text. */ + GAIM_NOTIFY_USERINFO, /**< Formatted userinfo text. */ + GAIM_NOTIFY_URI /**< URI notification or display. */ + +} GaimNotifyType; + +typedef enum +{ + GAIM_NOTIFY_MSG_ERROR = 0, /**< Error notification. */ + GAIM_NOTIFY_MSG_WARNING, /**< Warning notification. */ + GAIM_NOTIFY_MSG_INFO /**< Information notification. */ + +} GaimNotifyMsgType; + +void *gaim_notify_message(void *handle, GaimNotifyMsgType type, + const char *title, const char *primary, + const char *secondary, GCallback cb, + void *user_data); +void *gaim_notify_email(void *handle, const char *subject, + const char *from, const char *to, + const char *url, GCallback cb, + void *user_data); +void *gaim_notify_emails(void *handle, size_t count, gboolean detailed, + const char **subjects, const char **froms, + const char **tos, const char **urls, + GCallback cb, void *user_data); +void *gaim_notify_formatted(void *handle, const char *title, + const char *primary, const char *secondary, + const char *text, GCallback cb, void *user_data); +void *gaim_notify_userinfo(GaimConnection *gc, const char *who, + const char *title, const char *primary, + const char *secondary, const char *text, + GCallback cb, void *user_data); +void *gaim_notify_uri(void *handle, const char *uri); + +/* --- util.h ------------------------------------------------------------ */ + +void gaim_quotedp_decode (const char *str, char **ret_str, int *ret_len); +char *gaim_mime_decode_field (const char *str); +const char *gaim_date(void); +const char *gaim_date_full(void); +time_t gaim_time_build(int year, int month, int day, int hour, int min, int sec); +time_t gaim_str_to_time(const char *timestamp, gboolean utc); + +const gchar *gaim_home_dir(void); +char *gaim_user_dir(void); +void set_gaim_user_dir(const char *dir); +int gaim_build_dir(const char *path, int mode); +gboolean gaim_program_is_valid(const char *program); + +const char *gaim_normalize(const GaimAccount *account, const char *str); +const char *gaim_normalize_nocase(const GaimAccount *account, const char *str); diff --git a/gaim-citadel/interface.h b/gaim-citadel/interface.h new file mode 100644 index 000000000..a304b1eb6 --- /dev/null +++ b/gaim-citadel/interface.h @@ -0,0 +1,24 @@ +/* interface.h + * Gaim Citadel plugin. + * + * © 2006 David Given. + * This code is licensed under the GPL v2. See the file COPYING in this + * directory for the full license text. + * + * $Id: auth.c 4258 2006-01-29 13:34:44 +0000 (Sun, 29 Jan 2006) dothebart $ + */ + +#ifndef INTERFACE_H +#define INTERFACE_H + +extern char* interface_readdata(int fd, GaimSslConnection* gsc); +extern int interface_writedata(int fd, GaimSslConnection* gsc, char* data); +extern int interface_connect(GaimAccount* ga, GaimConnection* gc, char* server, int port); +extern void interface_disconnect(int fd, GaimSslConnection* gsc); +extern void interface_tlson(GaimConnection* gc, GaimAccount* ga, int fd); +extern int interface_timeron(GaimConnection* gc, time_t timeout); +extern void interface_timeroff(GaimConnection* gc, int timerhandle); + +extern const char* gaim_group_get_name(GaimGroup* group); + +#endif diff --git a/gaim-citadel/pm b/gaim-citadel/pm new file mode 100755 index 0000000000000000000000000000000000000000..cd74d10479e8631ff5899a56e97634e8a6906fe9 GIT binary patch literal 81862 zcmZs>W0WRAvo+eb?S9%er)}Guwr$(CZDX3#wr$(C_04|Fto5`a59Hck&sjtlavwVB_?Ggh7lI#H8O%xkQLPs73QU9ptrZ7GjTUDqSH5U zG&0wRaWZiR(3!x%n7BJT8W=h2IhhzaTiDrBQUSbRpq)&N|4jmj8EF}QYy2C^DuPNX zq)ZIP!~kN_{|Q43@CH!AKtns47#IVbEIdvA-5VPN44rtH07iB$w$8ky|9J{v=3_86 zab>V|v9^YRrut{(X=LCG;{yXj0+2KXIGdXQ4DIZko&M3Vr*Hxox>#5{(*hh_YylR| z^e`|MrT}dK>3_=r(AhczNErdT-2XANg@OKmkq0;#Ia=5||AY9S2LFZZ7}y#E98H{@4IKYNz{JSh4nS;g z!}Y&u+FRI~(bLlt!@vmtSG*aVZR{ET#g~+n-U#MDIsn9uHUK(P0O^0t69YswBvt-D zp$1skI-5A!JDU8v0{8&`mlIN9;s3`NKxg;A)R2<{{*%K0D+m82>;I1=z|`QM9^-#3 z|4TCy49x$^J1+{*i>1$I5d{ouCaN>&^IWJoM}F zT7hHC>|{v1C(Tle)`2H4^5Ml(%T78WVf<;tlUu$~n|nM~(oZW7HvG@H!&;tH!h>q& zl>QTgd8WKYy%%AcsOAOsWy_F9f~qA@RMEN6lv>mfymhyANfl8vVF3y3SF&E@(qrN_ zkkJL{#A(~&FKfnr5l^#fJ+wyW-19`p%`kcloO&c_cyb2u^9AF?3#(N(96=VnBjw=j ze1ZxZAC`SZxDVd`Fu^8eP+g6A%DM@(R4ju0b|72~(on4dzUV{O*QK+|jikHpSL05% zÃP`>6_Rq!a@@B=LWk>nd}L2D#B%o&wM8Qr4^V^21qCc+l#&unq9c{K)s8tLEZ z3@h@8<`LiN%Rx2Qd>70amZccA>h5|g-4j~;am7OI+(`K`Diu|#5Ln^iY12olOKDs; zFPL&CN{^_&7<09eDvr5=w;0#<;2ekn>neB-YUV;R6Hn4oK_QDZZp<5Z8e60}7 zE-XM9)Vpg=hOk^=Kh$^;Abh}eYz~`fzCc=4;AFk7{UA$9@(wH0!GH8=fi~OVkQ3B&o%|vBYT(iNQ(LZ$ZF5 z39AA%K&9z>K_?k`sreS}bz&NMQZ0tTI9y6=Xjqac%?jWNmxgI-@I-nu;({cg^m+smSv_u> z3&xfUm2B5h7c#>X!y-XO-b17|7mG^mR&+;eOMsF&^|trnl>#&YysQF1l5w~p;n$78h)zruQWlU$JymTW zwb;ZY$qM1|_J(I385&H?Vj5Ow*Zav}i;2My3eQlM>0_%nW7$tFLggV~O5V*N(FC3Y zOVxkXU|qsygUZ$cXP1%Co(qP<*eZJf&Lvb5X@cQrK^iNm6b<6X6UIrYg#He7*OAJn zDMYEcUHi-3Fg|yd^AhEyV!IWN*sf2xGwuU3)LN&qYOZgcxkn+w04$p0ilFA(fGx5% zqeVrGAAyLRQtrhhkW5O441tvxlu7dIkEZHDC!!*tG699AjPit8yV!p~=ksI*?)8MM z!lmPbz_m1$s&>HS{Ih05T9AZND0}t%7kCCSbD2nz$(dh4PGB5mRMl;H15Gton7<%m zp0BTa6jx*W9C@W9Kapdc;!75=tMwFBvsk`>U*r2*R-)^gZ3ceZl=<30EJm~B2OBqf z7paL!_kK}t;4wk#Sx^{x%|S?TkV@jk|(F$H5MXj3uCBALJ4rCL;QXAbc-L7#Vy7**u%S;80)2N5o zN_^HKow1*`!^=g8xWc?YyM7(mvE`zPM zc~c-d&XQg%y=)t4O@5_8PQd+lk`6Ne4WXUe0VUi7x?Bsa-^zbNK)3ob9>ny;vw^uA ztD&V%&CG3_{G!)1>{ybTcBFN9x|&<9!#J1pErx@z5OP!kpq;AvE@;NVoHA^fRN$af%F7P%S%Rj5-M5Z*2Q; zqET?9S~qJNkn#c6ZjSy$5Q#1bYOz ze>EPZsS~ABk)TM8V=`F(-sw+n4GVM8vup!6QCazQVOwh@)np#!<*js51 z2@0tiiUVex7cx6gQ(}1pq z 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

88=xE>H8_U7D*7xDfcQjhf-7A>B5xGJJ z5W({!7Jms{eyrF%qImMkkfh2e239gectS>^(`S~lB5$gkwn!4Q++d3)#X9+! z!|x>WUshT^oM73v#;RPp@4}h(wDXYy`5vagk!hP7b$I0oB>2<_r0*Sx!M zfgPX&J&WTVDMnvs!N+%C>OCG3eRnmnPAIxvuQ4G+W6yu->5eGMT{f7|$mxzU1vmY4 z3LiQ}gm0eSmN{GBoA$&c24s4joJvmZ-9lUC_MUw4N@n1Xa1Ll^d)#%C)q8Yke%R2f zjFh|<(*QHog4pvi;~bv1XNd~I`PqAn-3yU&5H^XPF0}#4#q~3}cW3x~nT(AAFcu~t zXpFVk=`8pY)Ss{R+s4xg_9&Z-)It6FE}a^iJsykPidY;uNbJ;s8SwC?IV{9Hz;-jb z`9bMZ^~aN71mQzTq$%$6N8VGRtStsbY_ldqj9n9X_A?P4?9YaM%_BWEVx#4cb~CGR zixH5T;**o1Yt?4v0ZcFSxvAVg$<-L|nnio>ESt+vKj56%&G`^KF*Qdu2rC3@&te-a zu+Bm}v%urIKD)PIS=Y9fzagb?g`Ml%^`*2XMzxUpAU>_@I<9{`3x$8aYaq6 z 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 literal 0 HcmV?d00001 diff --git a/gaim-citadel/pmfile b/gaim-citadel/pmfile new file mode 100644 index 000000000..c28b04a6b --- /dev/null +++ b/gaim-citadel/pmfile @@ -0,0 +1,50 @@ +-- citadel.c +-- Gaim Citadel plugin. +-- © 2006 David Given. +-- This code is licensed under the GPL v2. See the file COPYING in this +-- directory for the full license text. +-- +-- $Id: auth.c 4258 2006-01-29 13:34:44 +0000 (Sun, 29 Jan 2006) dothebart $ + +include "c.pm" + +GAIMINCLUDES = "-I/usr/include/gaim" +GLIBINCLUDES = "-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include" +LUAINCLUDES = "-I/usr/include/lua50" +LUALIBRARIES = "-llualib50 -llua50" + +HOME = os.getenv("HOME") + +csharedlibrary = simple { + class = "csharedlibrary", + CBUILDFLAGS = "-g -O0 -Wall -fPIC -shared", + + command = { + "%CPROGRAM%" + }, + outputs = {"%U%-%I%.so"}, +} + +default = csharedlibrary { + CEXTRAFLAGS="-DLUA_USE_POSIX", + CINCLUDES="-I. %GAIMINCLUDES% %GLIBINCLUDES% %LUAINCLUDES%", + CLIBRARIES="%LUALIBRARIES% -ltolua", + + cfile "citadel.c", + + cfile { + simple { + outputs = {"%U%-%I%.c"}, + command = { + "tolua -n gaim -o %out% %in%" + }, + + file "gaim.pkg" + } + }, + + install = { + pm.install("%HOME%/.gaim/plugins/citadel.so"), + pm.install("citadel.lua", "%HOME%/.gaim/plugindata/citadel.lua") + } +} -- 2.39.2