Explorar el Código

Miscellaneous fixes and code cleanup to libircclient

master
achmizs hace 4 años
padre
commit
a44e8f5f00

+ 22
- 22
libircclient/include/config.h Ver fichero

/* #undef HAVE_GETHOSTBYNAME_R */ /* #undef HAVE_GETHOSTBYNAME_R */


/* Define to 1 if you have the `inet_ntoa' function. */ /* Define to 1 if you have the `inet_ntoa' function. */
/* #undef HAVE_INET_NTOA */
#define HAVE_INET_NTOA 1


/* Define to 1 if you have the `inet_pton' function. */ /* Define to 1 if you have the `inet_pton' function. */
/* #undef HAVE_INET_PTON */ /* #undef HAVE_INET_PTON */


/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */
#define HAVE_INTTYPES_H 1


/* Define to 1 if you have the `localtime_r' function. */ /* Define to 1 if you have the `localtime_r' function. */
/* #undef HAVE_LOCALTIME_R */
#define HAVE_LOCALTIME_R 1


/* Define to 1 if your system has a GNU libc compatible `malloc' function, and /* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */ to 0 otherwise. */
#define HAVE_MALLOC 0
#define HAVE_MALLOC 1


/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H */
#define HAVE_MEMORY_H 1


/* Define to 1 if you have the `socket' function. */ /* Define to 1 if you have the `socket' function. */
/* #undef HAVE_SOCKET */
#define HAVE_SOCKET 1


/* Define to 1 if `stat' has the bug that it succeeds when given the /* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */ zero-length file name argument. */
#define HAVE_STAT_EMPTY_STRING_BUG 1
/* #undef HAVE_STAT_EMPTY_STRING_BUG */


/* Define to 1 if stdbool.h conforms to C99. */ /* Define to 1 if stdbool.h conforms to C99. */
#define HAVE_STDBOOL_H 1 #define HAVE_STDBOOL_H 1


/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
/* #undef HAVE_STDINT_H */
#define HAVE_STDINT_H 1


/* Define to 1 if you have the <stdlib.h> header file. */ /* Define to 1 if you have the <stdlib.h> header file. */
/* #undef HAVE_STDLIB_H */
#define HAVE_STDLIB_H 1


/* Define to 1 if you have the <strings.h> header file. */ /* Define to 1 if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H */
#define HAVE_STRINGS_H 1


/* Define to 1 if you have the <string.h> header file. */ /* Define to 1 if you have the <string.h> header file. */
/* #undef HAVE_STRING_H */
#define HAVE_STRING_H 1


/* Define to 1 if you have the <sys/select.h> header file. */ /* Define to 1 if you have the <sys/select.h> header file. */
/* #undef HAVE_SYS_SELECT_H */
#define HAVE_SYS_SELECT_H 1


/* Define to 1 if you have the <sys/socket.h> header file. */ /* Define to 1 if you have the <sys/socket.h> header file. */
/* #undef HAVE_SYS_SOCKET_H */
#define HAVE_SYS_SOCKET_H 1


/* Define to 1 if you have the <sys/stat.h> header file. */ /* Define to 1 if you have the <sys/stat.h> header file. */
/* #undef HAVE_SYS_STAT_H */
#define HAVE_SYS_STAT_H 1


/* Define to 1 if you have the <sys/types.h> header file. */ /* Define to 1 if you have the <sys/types.h> header file. */
/* #undef HAVE_SYS_TYPES_H */
#define HAVE_SYS_TYPES_H 1


/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
#define HAVE_UNISTD_H 1


/* Define to 1 if the system has the type `_Bool'. */ /* Define to 1 if the system has the type `_Bool'. */
/* #undef HAVE__BOOL */
#define HAVE__BOOL 1


/* Define to 1 if `lstat' dereferences a symlink specified with a trailing /* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */ slash. */
#define PACKAGE_NAME "libircclient" #define PACKAGE_NAME "libircclient"


/* Define to the full name and version of this package. */ /* Define to the full name and version of this package. */
#define PACKAGE_STRING "libircclient 1.8"
#define PACKAGE_STRING "libircclient 1.3"


/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libircclient" #define PACKAGE_TARNAME "libircclient"


/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "1.8"
#define PACKAGE_VERSION "1.3"


/* Define to the type of arg 1 for `select'. */ /* Define to the type of arg 1 for `select'. */
#define SELECT_TYPE_ARG1 int #define SELECT_TYPE_ARG1 int


/* Define to the type of args 2, 3 and 4 for `select'. */ /* Define to the type of args 2, 3 and 4 for `select'. */
#define SELECT_TYPE_ARG234 (int *)
#define SELECT_TYPE_ARG234 (fd_set *)


/* Define to the type of arg 5 for `select'. */ /* Define to the type of arg 5 for `select'. */
#define SELECT_TYPE_ARG5 (struct timeval *) #define SELECT_TYPE_ARG5 (struct timeval *)


/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
#define STDC_HEADERS 1


/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
/* #undef TIME_WITH_SYS_TIME */
#define TIME_WITH_SYS_TIME 1


/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */ /* #undef const */

+ 5
- 6
libircclient/include/dcc.h Ver fichero

/* /*
* This structure keeps the state of a single DCC connection. * This structure keeps the state of a single DCC connection.
*/ */
struct irc_dcc_session_s
{
struct irc_dcc_session_s {
irc_dcc_session_t * next; irc_dcc_session_t * next;


irc_dcc_t id; irc_dcc_t id;
time_t timeout; time_t timeout;


FILE * dccsend_file_fp; FILE * dccsend_file_fp;
unsigned int received_file_size;
unsigned int file_confirm_offset;
size_t received_file_size;
size_t file_confirm_offset;


struct sockaddr_in remote_addr; struct sockaddr_in remote_addr;


char incoming_buf[LIBIRC_DCC_BUFFER_SIZE]; char incoming_buf[LIBIRC_DCC_BUFFER_SIZE];
unsigned int incoming_offset;
size_t incoming_offset;


char outgoing_buf[LIBIRC_DCC_BUFFER_SIZE]; char outgoing_buf[LIBIRC_DCC_BUFFER_SIZE];
unsigned int outgoing_offset;
size_t outgoing_offset;
port_mutex_t mutex_outbuf; port_mutex_t mutex_outbuf;


irc_dcc_callback_t cb; irc_dcc_callback_t cb;

+ 26
- 7
libircclient/include/libirc_events.h Ver fichero

* *
* \ingroup events * \ingroup events
*/ */
typedef void (*irc_event_callback_t) (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count);
typedef void (*irc_event_callback_t) (irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);




/*! /*!
* *
* \ingroup events * \ingroup events
*/ */
typedef void (*irc_eventcode_callback_t) (irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count);
typedef void (*irc_eventcode_callback_t) (irc_session_t *session, unsigned int event, const char *origin, const char **params, unsigned int count);




/*! /*!
* \sa irc_dcc_accept or irc_dcc_decline * \sa irc_dcc_accept or irc_dcc_decline
* \ingroup events * \ingroup events
*/ */
typedef void (*irc_event_dcc_chat_t) (irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid);
typedef void (*irc_event_dcc_chat_t) (irc_session_t *session, const char *nick, const char *addr, irc_dcc_t dccid);




/*! /*!
* \fn typedef void (*irc_event_dcc_send_t) (irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid) * \fn typedef void (*irc_event_dcc_send_t) (irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid)
* \brief A remote DCC CHAT request callback
* \brief A remote DCC SEND request callback
* *
* \param session the session, which generates an event * \param session the session, which generates an event
* \param nick the person who requested DCC CHAT with you.
* \param nick the person who requested DCC SEND to you.
* \param addr the person's IP address in decimal-dot notation. * \param addr the person's IP address in decimal-dot notation.
* \param filename the sent filename. * \param filename the sent filename.
* \param size the filename size. * \param size the filename size.
* \sa irc_dcc_accept or irc_dcc_decline * \sa irc_dcc_accept or irc_dcc_decline
* \ingroup events * \ingroup events
*/ */
typedef void (*irc_event_dcc_send_t) (irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid);
typedef void (*irc_event_dcc_send_t) (irc_session_t *session, const char *nick, const char *addr, const char *filename, size_t size, irc_dcc_t dccid);




/*! \brief Event callbacks structure. /*! \brief Event callbacks structure.
*/ */
irc_event_callback_t event_connect; irc_event_callback_t event_connect;


/*!
* The "ping" event is triggered when the client receives a PING message.
* It is only generated if the LIBIRC_OPTION_PING_PASSTHROUGH option is set;
* otherwise, the library responds to PING messages automatically.
*
* \param origin the person, who generated the ping.
* \param params[0] mandatory, contains who knows what.
*/
irc_event_callback_t event_ping;

/*! /*!
* The "nick" event is triggered when the client receives a NICK message, * The "nick" event is triggered when the client receives a NICK message,
* meaning that someone (including you) on a channel with the client has * meaning that someone (including you) on a channel with the client has
*/ */
irc_event_callback_t event_kick; irc_event_callback_t event_kick;


/*!
* The "error" event is triggered upon receipt of an ERROR message, which
* (when sent to clients) usually means the client has been disconnected.
*
* \param origin the person, who generates the message.
* \param params optional, contains who knows what.
*/
irc_event_callback_t event_error;

/*! /*!
* The "channel" event is triggered upon receipt of a PRIVMSG message * The "channel" event is triggered upon receipt of a PRIVMSG message
* to an entire channel, which means that someone on a channel with * to an entire channel, which means that someone on a channel with
irc_event_dcc_chat_t event_dcc_chat_req; irc_event_dcc_chat_t event_dcc_chat_req;


/*! /*!
* The "dcc chat" event is triggered when someone wants to send a file
* The "dcc send" event is triggered when someone wants to send a file
* to you via DCC SEND request. * to you via DCC SEND request.
* *
* See the params in ::irc_event_dcc_send_t specification. * See the params in ::irc_event_dcc_send_t specification.

+ 8
- 0
libircclient/include/libirc_options.h Ver fichero

*/ */
#define LIBIRC_OPTION_SSL_NO_VERIFY (1 << 3) #define LIBIRC_OPTION_SSL_NO_VERIFY (1 << 3)


/*! \brief Disables automatic response to PING messages.
*
* The library will still generate events for PING messages, if an event handler
* is provided.
* \ingroup options
*/
#define LIBIRC_OPTION_IGNORE_PING (1 << 4)



#endif /* INCLUDE_IRC_OPTIONS_H */ #endif /* INCLUDE_IRC_OPTIONS_H */

+ 131
- 70
libircclient/include/libircclient.h Ver fichero

/*! /*!
* \file libircclient.h * \file libircclient.h
* \author George Yunaev * \author George Yunaev
* \version 1.5
* \version 1.9
* \date 01.2012 * \date 01.2012
* \brief This file defines all prototypes and functions to use libircclient. * \brief This file defines all prototypes and functions to use libircclient.
* *


#include <stdlib.h> #include <stdlib.h>


#if !defined (WIN32)
#if !defined (_WIN32)
#include <sys/select.h> /* fd_set */ #include <sys/select.h> /* fd_set */
#else #else
#include <winsock2.h> #include <winsock2.h>
* *
* \ingroup dccstuff * \ingroup dccstuff
*/ */
typedef void (*irc_dcc_callback_t) (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length);
typedef void (*irc_dcc_callback_t) (irc_session_t *session, irc_dcc_t id, int status, void *ctx, const char *data, size_t length);




#define IN_INCLUDE_LIBIRC_H #define IN_INCLUDE_LIBIRC_H
* \sa irc_destroy_session * \sa irc_destroy_session
* \ingroup initclose * \ingroup initclose
*/ */
irc_session_t * irc_create_session (irc_callbacks_t * callbacks);
irc_session_t* irc_create_session (irc_callbacks_t *callbacks);




/*! /*!
* *
* \ingroup initclose * \ingroup initclose
*/ */
void irc_destroy_session (irc_session_t * session);
void irc_destroy_session (irc_session_t *session);




/*! /*!
* \sa irc_run * \sa irc_run
* \ingroup conndisc * \ingroup conndisc
*/ */
int irc_connect (irc_session_t * session,
const char * server,
unsigned short port,
const char * server_password,
const char * nick,
const char * username,
const char * realname);
int irc_connect (irc_session_t *session,
const char *server,
unsigned short port,
const char *server_password,
const char *nick,
const char *username,
const char *realname);




/*! /*!
* \sa irc_run * \sa irc_run
* \ingroup conndisc * \ingroup conndisc
*/ */
int irc_connect6 (irc_session_t * session,
const char * server,
unsigned short port,
const char * server_password,
const char * nick,
const char * username,
const char * realname);
int irc_connect6 (irc_session_t *session,
const char *server,
unsigned short port,
const char *server_password,
const char *nick,
const char *username,
const char *realname);


/*! /*!
* \fn void irc_disconnect (irc_session_t * session) * \fn void irc_disconnect (irc_session_t * session)
* \sa irc_connect irc_run * \sa irc_connect irc_run
* \ingroup conndisc * \ingroup conndisc
*/ */
void irc_disconnect (irc_session_t * session);
void irc_disconnect (irc_session_t *session);




/*! /*!
* \sa irc_connect irc_run * \sa irc_connect irc_run
* \ingroup conndisc * \ingroup conndisc
*/ */
int irc_is_connected (irc_session_t * session);
int irc_is_connected (irc_session_t *session);




/*! /*!
* *
* \ingroup running * \ingroup running
*/ */
int irc_run (irc_session_t * session);
int irc_run (irc_session_t *session);




/*! /*!
* \sa irc_process_select_descriptors * \sa irc_process_select_descriptors
* \ingroup running * \ingroup running
*/ */
int irc_add_select_descriptors (irc_session_t * session, fd_set *in_set, fd_set *out_set, int * maxfd);
int irc_add_select_descriptors (irc_session_t *session,
fd_set *in_set,
fd_set *out_set,
int *maxfd);




/*! /*!
* \sa irc_add_select_descriptors * \sa irc_add_select_descriptors
* \ingroup running * \ingroup running
*/ */
int irc_process_select_descriptors (irc_session_t * session, fd_set *in_set, fd_set *out_set);
int irc_process_select_descriptors (irc_session_t *session,
fd_set *in_set,
fd_set *out_set);




/*! /*!
* *
* \ingroup ircmd_oth * \ingroup ircmd_oth
*/ */
int irc_send_raw (irc_session_t * session, const char * format, ...);
int irc_send_raw (irc_session_t *session,
const char *format,
...);




/*! /*!
* *
* \ingroup ircmd_oth * \ingroup ircmd_oth
*/ */
int irc_cmd_quit (irc_session_t * session, const char * reason);
int irc_cmd_quit (irc_session_t *session,
const char *reason);




/*! /*!
* *
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_join (irc_session_t * session, const char * channel, const char * key);
int irc_cmd_join (irc_session_t *session,
const char *channel,
const char *key);




/*! /*!
* *
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_part (irc_session_t * session, const char * channel);
int irc_cmd_part (irc_session_t *session,
const char *channel);




/*! /*!
* \sa irc_callbacks_t::event_invite irc_cmd_channel_mode * \sa irc_callbacks_t::event_invite irc_cmd_channel_mode
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_invite (irc_session_t * session, const char * nick, const char * channel);
int irc_cmd_invite (irc_session_t *session,
const char *nick,
const char *channel);




/*! /*!
* *
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_names (irc_session_t * session, const char * channel);
int irc_cmd_names (irc_session_t *session,
const char *channel);




/*! /*!
* *
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_list (irc_session_t * session, const char * channel);
int irc_cmd_list (irc_session_t *session,
const char *channel);




/*! /*!
* \sa irc_callbacks_t::event_topic irc_cmd_channel_mode * \sa irc_callbacks_t::event_topic irc_cmd_channel_mode
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_topic (irc_session_t * session, const char * channel, const char * topic);
int irc_cmd_topic (irc_session_t *session,
const char *channel,
const char *topic);




/*! /*!
* \sa irc_cmd_topic irc_cmd_list * \sa irc_cmd_topic irc_cmd_list
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_channel_mode (irc_session_t * session, const char * channel, const char * mode);
int irc_cmd_channel_mode (irc_session_t *session,
const char *channel,
const char *mode);




/*! /*!
* *
* \ingroup ircmd_oth * \ingroup ircmd_oth
*/ */
int irc_cmd_user_mode (irc_session_t * session, const char * mode);
int irc_cmd_user_mode (irc_session_t *session,
const char *mode);




/*! /*!
* *
* \ingroup ircmd_oth * \ingroup ircmd_oth
*/ */
int irc_cmd_nick (irc_session_t * session, const char * newnick);
int irc_cmd_nick (irc_session_t *session,
const char *newnick);




/*! /*!
* *
* \ingroup ircmd_oth * \ingroup ircmd_oth
*/ */
int irc_cmd_whois (irc_session_t * session, const char * nick);
int irc_cmd_whois (irc_session_t *session,
const char *nick);




/*! /*!
* *
* \ingroup ircmd_msg * \ingroup ircmd_msg
*/ */
int irc_cmd_msg (irc_session_t * session, const char * nch, const char * text);
int irc_cmd_msg (irc_session_t *session,
const char *nch,
const char *text);




/*! /*!
* \sa irc_cmd_msg * \sa irc_cmd_msg
* \ingroup ircmd_msg * \ingroup ircmd_msg
*/ */
int irc_cmd_me (irc_session_t * session, const char * nch, const char * text);
int irc_cmd_me (irc_session_t *session,
const char *nch,
const char *text);




/*! /*!
* \sa irc_cmd_msg * \sa irc_cmd_msg
* \ingroup ircmd_msg * \ingroup ircmd_msg
*/ */
int irc_cmd_notice (irc_session_t * session, const char * nch, const char * text);
int irc_cmd_notice (irc_session_t *session,
const char *nch,
const char *text);




/*! /*!
* \sa irc_callbacks_t::event_numeric * \sa irc_callbacks_t::event_numeric
* \ingroup ircmd_ch * \ingroup ircmd_ch
*/ */
int irc_cmd_kick (irc_session_t * session, const char * nick, const char * channel, const char * reason);
int irc_cmd_kick (irc_session_t *session,
const char *nick,
const char *channel,
const char *reason);




/*! /*!
* \sa irc_callbacks_t::event_ctcp_rep irc_callbacks_t::event_numeric * \sa irc_callbacks_t::event_ctcp_rep irc_callbacks_t::event_numeric
* \ingroup ctcp * \ingroup ctcp
*/ */
int irc_cmd_ctcp_request (irc_session_t * session, const char * nick, const char * request);
int irc_cmd_ctcp_request (irc_session_t *session,
const char *nick,
const char *request);




/*! /*!
* *
* \ingroup ctcp * \ingroup ctcp
*/ */
int irc_cmd_ctcp_reply (irc_session_t * session, const char * nick, const char * reply);
int irc_cmd_ctcp_reply (irc_session_t *session,
const char *nick,
const char *reply);




/*! /*!
* \fn void irc_target_get_nick (const char * target, char *nick, size_t size) * \fn void irc_target_get_nick (const char * target, char *nick, size_t size)
* \brief Gets the nick part from the target * \brief Gets the nick part from the target
* *
* \param target A nick in common IRC server form like tim!root\@mycomain.com
* \param target A nick in common IRC server form like tim!root\@mycomain.com; cannot be NULL
* \param nick A buffer to hold the nickname. * \param nick A buffer to hold the nickname.
* \param size A buffer size. If nick is longer than buffer size, it will * \param size A buffer size. If nick is longer than buffer size, it will
* be truncated. * be truncated.
* *
* For most events IRC server returns 'origin' (i.e. the person, who * For most events IRC server returns 'origin' (i.e. the person, who
* generated this event) in i.e. "common" form, like nick!host\@domain. * generated this event) in i.e. "common" form, like nick!host\@domain.
* However, all the irc_cmd_* functions require just a nick/
* However, all the irc_cmd_* functions require just a nick.
* This function parses this origin, and gets the nick, storing it into * This function parses this origin, and gets the nick, storing it into
* user-provided buffer. * user-provided buffer.
* A buffer of size 90 should be enough for most nicks :) * A buffer of size 90 should be enough for most nicks :)
* *
* \ingroup nnparse * \ingroup nnparse
*/ */
void irc_target_get_nick (const char * target, char *nick, size_t size);
void irc_target_get_nick (const char *target,
char *nick,
size_t size);




/*! /*!
* *
* \ingroup nnparse * \ingroup nnparse
*/ */
void irc_target_get_host (const char * target, char *nick, size_t size);
void irc_target_get_host (const char *target,
char *nick,
size_t size);




/*! /*!
* \fn int irc_dcc_chat(irc_session_t * session, void * ctx, const char * nick, irc_dcc_callback_t callback, irc_dcc_t * dccid) * \fn int irc_dcc_chat(irc_session_t * session, void * ctx, const char * nick, irc_dcc_callback_t callback, irc_dcc_t * dccid)
* \brief Initiates a DCC CHAT. * \brief Initiates a DCC CHAT.
* *
* \param session An initiated and connected session.
* \param ctx A user-supplied DCC session context, which will be passed to
* the DCC callback function. May be NULL.
* \param nick A nick to DCC CHAT with.
* \param callback A DCC callback function, which will be called when
* anything is said by other party. Must not be NULL.
* \param dccid On success, DCC session ID will be stored in this var.
* \param session An initiated and connected session.
* \param ctx A user-supplied DCC session context, which will be passed to
* the DCC callback function. May be NULL.
* \param nick A nick to DCC CHAT with.
* \param callback A DCC callback function, which will be called when
* anything is said by other party. Must not be NULL.
* \param dccid On success, DCC session ID will be stored in this var.
* *
* \return Return code 0 means success. Other value means error, the error * \return Return code 0 means success. Other value means error, the error
* code may be obtained through irc_errno(). Any error, generated by the * code may be obtained through irc_errno(). Any error, generated by the
* \sa irc_dcc_callback_t irc_dcc_msg * \sa irc_dcc_callback_t irc_dcc_msg
* \ingroup dccstuff * \ingroup dccstuff
*/ */
int irc_dcc_chat (irc_session_t * session, void * ctx, const char * nick, irc_dcc_callback_t callback, irc_dcc_t * dccid);
int irc_dcc_chat (irc_session_t *session,
void *ctx,
const char *nick,
irc_dcc_callback_t
callback,
irc_dcc_t *dccid);




/*! /*!
* \sa irc_dcc_chat * \sa irc_dcc_chat
* \ingroup dccstuff * \ingroup dccstuff
*/ */
int irc_dcc_msg (irc_session_t * session, irc_dcc_t dccid, const char * text);
int irc_dcc_msg (irc_session_t *session,
irc_dcc_t dccid,
const char *text);




/*! /*!
* \sa irc_dcc_decline event_dcc_chat_req event_dcc_send_req * \sa irc_dcc_decline event_dcc_chat_req event_dcc_send_req
* \ingroup dccstuff * \ingroup dccstuff
*/ */
int irc_dcc_accept (irc_session_t * session, irc_dcc_t dccid, void * ctx, irc_dcc_callback_t callback);
int irc_dcc_accept (irc_session_t *session,
irc_dcc_t dccid,
void *ctx,
irc_dcc_callback_t callback);




/*! /*!
* \sa irc_dcc_accept irc_callbacks_t::event_dcc_chat_req irc_callbacks_t::event_dcc_send_req irc_dcc_destroy * \sa irc_dcc_accept irc_callbacks_t::event_dcc_chat_req irc_callbacks_t::event_dcc_send_req irc_dcc_destroy
* \ingroup dccstuff * \ingroup dccstuff
*/ */
int irc_dcc_decline (irc_session_t * session, irc_dcc_t dccid);
int irc_dcc_decline (irc_session_t *session,
irc_dcc_t dccid);




/*! /*!
* \sa irc_dcc_callback_t * \sa irc_dcc_callback_t
* \ingroup dccstuff * \ingroup dccstuff
*/ */
int irc_dcc_sendfile (irc_session_t * session, void * ctx, const char * nick, const char * filename, irc_dcc_callback_t callback, irc_dcc_t * dccid);
int irc_dcc_sendfile (irc_session_t *session,
void *ctx,
const char *nick,
const char *filename,
irc_dcc_callback_t callback,
irc_dcc_t *dccid);




/*! /*!
* *
* \ingroup dccstuff * \ingroup dccstuff
*/ */
int irc_dcc_destroy (irc_session_t * session, irc_dcc_t dccid);
int irc_dcc_destroy (irc_session_t *session,
irc_dcc_t dccid);




/*! /*!
* *
* \ingroup common * \ingroup common
*/ */
void irc_get_version (unsigned int * high, unsigned int * low);
void irc_get_version (unsigned int *high,
unsigned int *low);




/*! /*!
* \sa irc_get_ctx * \sa irc_get_ctx
* \ingroup contexts * \ingroup contexts
*/ */
void irc_set_ctx (irc_session_t * session, void * ctx);
void irc_set_ctx (irc_session_t *session,
void *ctx);


/*! /*!
* \fn void irc_set_ctcp_version (irc_session_t * session, const char *version) * \fn void irc_set_ctcp_version (irc_session_t * session, const char *version)
* *
* \ingroup contexts * \ingroup contexts
*/ */
void irc_set_ctcp_version(irc_session_t * session, const char * version);
void irc_set_ctcp_version(irc_session_t *session,
const char *version);


/*! /*!
* \fn void * irc_get_ctx (irc_session_t * session) * \fn void * irc_get_ctx (irc_session_t * session)
* \sa irc_set_ctx * \sa irc_set_ctx
* \ingroup contexts * \ingroup contexts
*/ */
void * irc_get_ctx (irc_session_t * session);
void* irc_get_ctx (irc_session_t *session);




/*! /*!
* \sa irc_strerror * \sa irc_strerror
* \ingroup errors * \ingroup errors
*/ */
int irc_errno (irc_session_t * session);
int irc_errno (irc_session_t *session);




/*! /*!
* \sa irc_errno() * \sa irc_errno()
* \ingroup errors * \ingroup errors
*/ */
const char * irc_strerror (int ircerrno);
const char* irc_strerror (int ircerrno);




/*! /*!
* \sa irc_option_reset * \sa irc_option_reset
* \ingroup options * \ingroup options
*/ */
void irc_option_set (irc_session_t * session, unsigned int option);
void irc_option_set (irc_session_t *session,
unsigned int option);




/*! /*!
* \sa irc_option_set * \sa irc_option_set
* \ingroup options * \ingroup options
*/ */
void irc_option_reset (irc_session_t * session, unsigned int option);
void irc_option_reset (irc_session_t *session,
unsigned int option);




/*! /*!
* \sa irc_color_convert_from_mirc irc_color_convert_to_mirc * \sa irc_color_convert_from_mirc irc_color_convert_to_mirc
* \ingroup colors * \ingroup colors
*/ */
char * irc_color_strip_from_mirc (const char * message);
char* irc_color_strip_from_mirc (const char *message);




/*! /*!
* \sa irc_color_strip_from_mirc irc_color_convert_to_mirc * \sa irc_color_strip_from_mirc irc_color_convert_to_mirc
* \ingroup colors * \ingroup colors
*/ */
char * irc_color_convert_from_mirc (const char * message);
char* irc_color_convert_from_mirc (const char *message);




/*! /*!
* \sa irc_color_strip_from_mirc irc_color_convert_from_mirc * \sa irc_color_strip_from_mirc irc_color_convert_from_mirc
* \ingroup colors * \ingroup colors
*/ */
char * irc_color_convert_to_mirc (const char * message);
char* irc_color_convert_to_mirc (const char *message);


#ifdef __cplusplus #ifdef __cplusplus
} }

+ 1
- 1
libircclient/include/params.h Ver fichero





#define LIBIRC_VERSION_HIGH 1 #define LIBIRC_VERSION_HIGH 1
#define LIBIRC_VERSION_LOW 8
#define LIBIRC_VERSION_LOW 10


#define LIBIRC_BUFFER_SIZE 1024 #define LIBIRC_BUFFER_SIZE 1024
#define LIBIRC_DCC_BUFFER_SIZE 1024 #define LIBIRC_DCC_BUFFER_SIZE 1024

+ 3
- 5
libircclient/include/session.h Ver fichero







struct irc_session_s
{
struct irc_session_s {
void * ctx; void * ctx;
int dcc_timeout; int dcc_timeout;


int lasterror; int lasterror;


char incoming_buf[LIBIRC_BUFFER_SIZE]; char incoming_buf[LIBIRC_BUFFER_SIZE];
unsigned int incoming_offset;
size_t incoming_offset;


char outgoing_buf[LIBIRC_BUFFER_SIZE]; char outgoing_buf[LIBIRC_BUFFER_SIZE];
unsigned int outgoing_offset;
size_t outgoing_offset;
port_mutex_t mutex_session; port_mutex_t mutex_session;


socket_t sock; socket_t sock;
SSL * ssl; SSL * ssl;
#endif #endif


}; };





+ 153
- 174
libircclient/src/colors.c Ver fichero

#define LIBIRC_COLORPARSER_MAXCOLORS 15 #define LIBIRC_COLORPARSER_MAXCOLORS 15




static const char * color_replacement_table[] =
{
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })


static const char *color_replacement_table[] = {
"WHITE", "WHITE",
"BLACK", "BLACK",
"DARKBLUE", "DARKBLUE",
}; };




static inline void libirc_colorparser_addorcat (char ** destline, unsigned int * destlen, const char * str)
{
unsigned int len = strlen(str);
static inline void libirc_colorparser_addorcat (char **destline,
unsigned int *destlen,
const char *str) {
size_t len = strlen(str);


if ( *destline )
{
if (*destline) {
strcpy (*destline, str); strcpy (*destline, str);
*destline += len; *destline += len;
}
else
} else {
*destlen += len; *destlen += len;
}
} }




static void libirc_colorparser_applymask (unsigned int * mask,
char ** destline, unsigned int * destlen,
unsigned int bitmask, const char * start, const char * end)
{
if ( (*mask & bitmask) != 0 )
{
static void libirc_colorparser_applymask (unsigned int *mask,
char **destline,
unsigned int *destlen,
unsigned int bitmask,
const char *start,
const char *end) {
if ((*mask & bitmask) != 0) {
*mask &= ~bitmask; *mask &= ~bitmask;
libirc_colorparser_addorcat (destline, destlen, end); libirc_colorparser_addorcat (destline, destlen, end);
}
else
{
} else {
*mask |= bitmask; *mask |= bitmask;
libirc_colorparser_addorcat (destline, destlen, start); libirc_colorparser_addorcat (destline, destlen, start);
} }
} }




static void libirc_colorparser_applycolor (unsigned int * mask,
char ** destline, unsigned int * destlen,
unsigned int colorid, unsigned int bgcolorid)
{
const char * end = "[/COLOR]";
static void libirc_colorparser_applycolor (unsigned int *mask,
char **destline,
unsigned int *destlen,
unsigned int colorid,
unsigned int bgcolorid) {
const char *end = "[/COLOR]";
char startbuf[64]; char startbuf[64];


if ( bgcolorid != 0 )
if (bgcolorid != 0)
sprintf (startbuf, "[COLOR=%s/%s]", color_replacement_table[colorid], color_replacement_table[bgcolorid]); sprintf (startbuf, "[COLOR=%s/%s]", color_replacement_table[colorid], color_replacement_table[bgcolorid]);
else else
sprintf (startbuf, "[COLOR=%s]", color_replacement_table[colorid]); sprintf (startbuf, "[COLOR=%s]", color_replacement_table[colorid]);


if ( (*mask & LIBIRC_COLORPARSER_COLOR) != 0 )
if ((*mask & LIBIRC_COLORPARSER_COLOR) != 0)
libirc_colorparser_addorcat (destline, destlen, end); libirc_colorparser_addorcat (destline, destlen, end);


*mask |= LIBIRC_COLORPARSER_COLOR; *mask |= LIBIRC_COLORPARSER_COLOR;
libirc_colorparser_addorcat (destline, destlen, startbuf);
libirc_colorparser_addorcat(destline, destlen, startbuf);
} }




static void libirc_colorparser_closetags (unsigned int * mask,
char ** destline, unsigned int * destlen)
{
if ( *mask & LIBIRC_COLORPARSER_BOLD )
static void libirc_colorparser_closetags (unsigned int *mask,
char **destline,
unsigned int *destlen) {
if (*mask & LIBIRC_COLORPARSER_BOLD)
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_BOLD, 0, "[/B]"); libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_BOLD, 0, "[/B]");


if ( *mask & LIBIRC_COLORPARSER_UNDERLINE )
if (*mask & LIBIRC_COLORPARSER_UNDERLINE)
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_UNDERLINE, 0, "[/U]"); libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_UNDERLINE, 0, "[/U]");


if ( *mask & LIBIRC_COLORPARSER_REVERSE )
if (*mask & LIBIRC_COLORPARSER_REVERSE)
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_REVERSE, 0, "[/I]"); libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_REVERSE, 0, "[/I]");


if ( *mask & LIBIRC_COLORPARSER_COLOR )
if (*mask & LIBIRC_COLORPARSER_COLOR)
libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_COLOR, 0, "[/COLOR]"); libirc_colorparser_applymask (mask, destline, destlen, LIBIRC_COLORPARSER_COLOR, 0, "[/COLOR]");
} }


/* /*
* IRC to [code] color conversion. Or strip. * IRC to [code] color conversion. Or strip.
*/ */
static char * libirc_colorparser_irc2code (const char * source, int strip)
{
static char* libirc_colorparser_irc2code (const char *source,
int strip) {
unsigned int mask = 0, destlen = 0; unsigned int mask = 0, destlen = 0;
char * destline = 0, *d = 0;
char *destline = 0, *d = 0;
const char *p; const char *p;
int current_bg = 0;
unsigned int current_bg = 0;


/* /*
* There will be two passes. First pass calculates the total length of * There will be two passes. First pass calculates the total length of
* the destination string. The second pass allocates memory for the string, * the destination string. The second pass allocates memory for the string,
* and fills it. * and fills it.
*/ */
while ( destline == 0 ) // destline will be set after the 2nd pass
{
if ( destlen > 0 )
{
while (destline == 0) { // destline will be set after the 2nd pass
if (destlen > 0) {
// This is the 2nd pass; allocate memory. // This is the 2nd pass; allocate memory.
if ( (destline = malloc (destlen)) == 0 )
if ((destline = malloc (destlen)) == 0)
return 0; return 0;


d = destline; d = destline;
} }


for ( p = source; *p; p++ )
{
switch (*p)
{
case 0x02: // bold
if ( strip )
continue;

libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_BOLD, "[B]", "[/B]");
break;
case 0x1F: // underline
if ( strip )
continue;

libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_UNDERLINE, "[U]", "[/U]");
break;

case 0x16: // reverse
if ( strip )
continue;

libirc_colorparser_applymask (&mask, &d, &destlen, LIBIRC_COLORPARSER_REVERSE, "[I]", "[/I]");
break;

case 0x0F: // reset colors
if ( strip )
continue;

libirc_colorparser_closetags (&mask, &d, &destlen);
break;

case 0x03: // set color
if ( isdigit (p[1]) )
{
// Parse
int bgcolor = -1, color = p[1] - 0x30;
p++;

if ( isdigit (p[1]) )
{
color = color * 10 + (p[1] - 0x30);
p++;
}
for (p = source; *p; p++) {
switch (*p) {
case 0x02: { // bold
if (strip)
continue;

libirc_colorparser_applymask(&mask, &d, &destlen, LIBIRC_COLORPARSER_BOLD, "[B]", "[/B]");
break;
}
case 0x1F: { // underline
if (strip)
continue;

libirc_colorparser_applymask(&mask, &d, &destlen, LIBIRC_COLORPARSER_UNDERLINE, "[U]", "[/U]");
break;
}
case 0x16: { // reverse
if (strip)
continue;


// If there is a comma, search for the following
// background color
if ( p[1] == ',' && isdigit (p[2]) )
{
bgcolor = p[2] - 0x30;
p += 2;
libirc_colorparser_applymask(&mask, &d, &destlen, LIBIRC_COLORPARSER_REVERSE, "[I]", "[/I]");
break;
}
case 0x0F: { // reset colors
if (strip)
continue;


if ( isdigit (p[1]) )
{
bgcolor = bgcolor * 10 + (p[1] - 0x30);
libirc_colorparser_closetags(&mask, &d, &destlen);
break;
}
case 0x03: { // set color
if (isdigit (p[1])) {
// Parse
int bgcolor = -1, color = p[1] - 0x30;
p++;

if (isdigit (p[1])) {
color = color * 10 + (p[1] - 0x30);
p++; p++;
} }
}


// Check for range
if ( color <= LIBIRC_COLORPARSER_MAXCOLORS
&& bgcolor <= LIBIRC_COLORPARSER_MAXCOLORS )
{
if ( strip )
continue;
// If there is a comma, search for the following
// background color
if (p[1] == ',' && isdigit (p[2])) {
bgcolor = p[2] - 0x30;
p += 2;

if (isdigit (p[1])) {
bgcolor = bgcolor * 10 + (p[1] - 0x30);
p++;
}
}

// Check for range
if ( color <= LIBIRC_COLORPARSER_MAXCOLORS
&& bgcolor <= LIBIRC_COLORPARSER_MAXCOLORS) {
if (strip)
continue;


if ( bgcolor != -1 )
current_bg = bgcolor;
if (bgcolor != -1)
current_bg = (unsigned int) bgcolor;


libirc_colorparser_applycolor (&mask, &d, &destlen, color, current_bg);
libirc_colorparser_applycolor(&mask, &d, &destlen, (unsigned int) max(color, 0), current_bg);
}
} }
break;
}
default: {
if (destline)
*d++ = *p;
else
destlen++;
break;
} }
break;

default:
if ( destline )
*d++ = *p;
else
destlen++;
break;
} }
} }


} }




static int libirc_colorparser_colorlookup (const char * color)
{
static int libirc_colorparser_colorlookup (const char *color) {
int i; int i;
for ( i = 0; color_replacement_table[i]; i++ )
if ( !strcmp (color, color_replacement_table[i]) )
for (i = 0; color_replacement_table[i]; i++)
if (!strcmp(color, color_replacement_table[i]))
return i; return i;


return -1; return -1;
/* /*
* [code] to IRC color conversion. * [code] to IRC color conversion.
*/ */
char * irc_color_convert_to_mirc (const char * source)
{
char* irc_color_convert_to_mirc (const char *source) {
unsigned int destlen = 0; unsigned int destlen = 0;
char * destline = 0, *d = 0;
char *destline = 0, *d = 0;
const char *p1, *p2, *cur; const char *p1, *p2, *cur;


/* /*
* the destination string. The second pass allocates memory for the string, * the destination string. The second pass allocates memory for the string,
* and fills it. * and fills it.
*/ */
while ( destline == 0 ) // destline will be set after the 2nd pass
{
if ( destlen > 0 )
{
while (destline == 0) { // destline will be set after the 2nd pass
if (destlen > 0) {
// This is the 2nd pass; allocate memory. // This is the 2nd pass; allocate memory.
if ( (destline = malloc (destlen)) == 0 )
if ((destline = malloc (destlen)) == 0)
return 0; return 0;


d = destline; d = destline;
} }


cur = source; cur = source;
while ( (p1 = strchr (cur, '[')) != 0 )
{
const char * replacedval = 0;
while ((p1 = strchr(cur, '[')) != 0) {
const char *replacedval = 0;
p2 = 0; p2 = 0;


// Check if the closing bracket is available after p1 // Check if the closing bracket is available after p1
// and the tag length is suitable // and the tag length is suitable
if ( p1[1] != '\0'
&& (p2 = strchr (p1, ']')) != 0
&& (p2 - p1) > 1
&& (p2 - p1) < 31 )
{
if ( p1[1] != '\0'
&& (p2 = strchr (p1, ']')) != 0
&& (p2 - p1) > 1
&& (p2 - p1) < 31) {
// Get the tag // Get the tag
char tagbuf[32]; char tagbuf[32];
int taglen = p2 - p1 - 1;
ssize_t taglen = p2 - p1 - 1;


memcpy (tagbuf, p1 + 1, taglen); memcpy (tagbuf, p1 + 1, taglen);
tagbuf[taglen] = '\0'; tagbuf[taglen] = '\0';


if ( !strcmp (tagbuf, "/COLOR") )
if (!strcmp (tagbuf, "/COLOR")) {
replacedval = "\x0F"; replacedval = "\x0F";
else if ( strstr (tagbuf, "COLOR=") == tagbuf )
{
} else if (strstr(tagbuf, "COLOR=") == tagbuf) {
int color, bgcolor = -2; int color, bgcolor = -2;
char * bcol;
char *bcol;


bcol = strchr (tagbuf + 6, '/');
bcol = strchr(tagbuf + 6, '/');


if ( bcol )
{
if (bcol) {
*bcol++ = '\0'; *bcol++ = '\0';
bgcolor = libirc_colorparser_colorlookup (bcol);
bgcolor = libirc_colorparser_colorlookup(bcol);
} }


color = libirc_colorparser_colorlookup (tagbuf + 6);
color = libirc_colorparser_colorlookup(tagbuf + 6);


if ( color != -1 && bgcolor == -2 )
{
if (color != -1 && bgcolor == -2) {
sprintf (tagbuf, "\x03%02d", color); sprintf (tagbuf, "\x03%02d", color);
replacedval = tagbuf; replacedval = tagbuf;
}
else if ( color != -1 && bgcolor >= 0 )
{
} else if (color != -1 && bgcolor >= 0) {
sprintf (tagbuf, "\x03%02d,%02d", color, bgcolor); sprintf (tagbuf, "\x03%02d,%02d", color, bgcolor);
replacedval = tagbuf; replacedval = tagbuf;
} }
}
else if ( !strcmp (tagbuf, "B") || !strcmp (tagbuf, "/B") )
} else if (!strcmp (tagbuf, "B") || !strcmp (tagbuf, "/B")) {
replacedval = "\x02"; replacedval = "\x02";
else if ( !strcmp (tagbuf, "U") || !strcmp (tagbuf, "/U") )
} else if (!strcmp (tagbuf, "U") || !strcmp (tagbuf, "/U")) {
replacedval = "\x1F"; replacedval = "\x1F";
else if ( !strcmp (tagbuf, "I") || !strcmp (tagbuf, "/I") )
} else if (!strcmp (tagbuf, "I") || !strcmp (tagbuf, "/I")) {
replacedval = "\x16"; replacedval = "\x16";
}
} }


if ( replacedval )
{
if (replacedval) {
// add a part before the tag // add a part before the tag
int partlen = p1 - cur;
ssize_t partlen = p1 - cur;


if ( destline )
{
if (destline) {
memcpy (d, cur, partlen); memcpy (d, cur, partlen);
d += partlen; d += partlen;
}
else
} else {
destlen += partlen; destlen += partlen;
}


// Add the replacement // Add the replacement
libirc_colorparser_addorcat (&d, &destlen, replacedval);
libirc_colorparser_addorcat(&d, &destlen, replacedval);


// And move the pointer // And move the pointer
cur = p2 + 1; cur = p2 + 1;
}
else
{
} else {
// add a whole part before the end tag // add a whole part before the end tag
int partlen;
ssize_t partlen;


if ( !p2 )
if (!p2)
p2 = cur + strlen(cur); p2 = cur + strlen(cur);


partlen = p2 - cur + 1; partlen = p2 - cur + 1;


if ( destline )
{
if (destline) {
memcpy (d, cur, partlen); memcpy (d, cur, partlen);
d += partlen; d += partlen;
}
else
} else {
destlen += partlen; destlen += partlen;
}


// And move the pointer // And move the pointer
cur = p2 + 1; cur = p2 + 1;
} }


// Add the rest of string // Add the rest of string
libirc_colorparser_addorcat (&d, &destlen, cur);
libirc_colorparser_addorcat(&d, &destlen, cur);
destlen++; // for 0-terminator destlen++; // for 0-terminator
} }


} }




char * irc_color_strip_from_mirc (const char * message)
{
char* irc_color_strip_from_mirc (const char *message) {
return libirc_colorparser_irc2code (message, 1); return libirc_colorparser_irc2code (message, 1);
} }




char * irc_color_convert_from_mirc (const char * message)
{
char* irc_color_convert_from_mirc (const char *message) {
return libirc_colorparser_irc2code (message, 0); return libirc_colorparser_irc2code (message, 0);
} }

+ 302
- 344
libircclient/src/dcc.c
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 420
- 476
libircclient/src/libircclient.c
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 0
- 7
libircclient/src/portable.c Ver fichero

#if defined (WIN32_DLL) #if defined (WIN32_DLL)
BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{ {
WORD wVersionRequested = MAKEWORD (1, 1);
WSADATA wsaData;

switch(fdwReason) switch(fdwReason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
if ( WSAStartup (wVersionRequested, &wsaData) != 0 )
return FALSE;

DisableThreadLibraryCalls (hinstDll); DisableThreadLibraryCalls (hinstDll);
break; break;


case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
WSACleanup();
break; break;
} }



+ 31
- 33
libircclient/src/sockets.c Ver fichero

#endif #endif




static int socket_error()
{
static int socket_error() {
#if !defined (_WIN32) #if !defined (_WIN32)
return errno; return errno;
#else #else
} }




static int socket_create (int domain, int type, socket_t * sock)
{
static int socket_create (int domain,
int type,
socket_t *sock) {
*sock = socket (domain, type, 0); *sock = socket (domain, type, 0);
return IS_SOCKET_ERROR(*sock) ? 1 : 0; return IS_SOCKET_ERROR(*sock) ? 1 : 0;
} }




static int socket_make_nonblocking (socket_t * sock)
{
static int socket_make_nonblocking (socket_t *sock) {
#if !defined (_WIN32) #if !defined (_WIN32)
return fcntl (*sock, F_SETFL, fcntl (*sock, F_GETFL,0 ) | O_NONBLOCK) != 0; return fcntl (*sock, F_SETFL, fcntl (*sock, F_GETFL,0 ) | O_NONBLOCK) != 0;
#else #else
unsigned long mode = 0;
unsigned long mode = 1;
return ioctlsocket (*sock, FIONBIO, &mode) == SOCKET_ERROR; return ioctlsocket (*sock, FIONBIO, &mode) == SOCKET_ERROR;
#endif #endif
} }




static int socket_close (socket_t * sock)
{
static int socket_close (socket_t *sock) {
#if !defined (_WIN32) #if !defined (_WIN32)
close (*sock); close (*sock);
#else #else
} }




static int socket_connect (socket_t * sock, const struct sockaddr *saddr, socklen_t len)
{
while ( 1 )
{
if ( connect (*sock, saddr, len) < 0 )
{
if ( socket_error() == EINTR )
static ssize_t socket_connect (socket_t *sock,
const struct sockaddr *saddr,
socklen_t len) {
while (1) {
if (connect(*sock, saddr, len) < 0) {
if (socket_error() == EINTR)
continue; continue;


if ( socket_error() != EINPROGRESS && socket_error() != EWOULDBLOCK )
if (socket_error() != EINPROGRESS && socket_error() != EWOULDBLOCK)
return 1; return 1;
} }


} }




static int socket_accept (socket_t * sock, socket_t * newsock, struct sockaddr *saddr, socklen_t * len)
{
while ( IS_SOCKET_ERROR(*newsock = accept (*sock, saddr, len)) )
{
if ( socket_error() == EINTR )
static ssize_t socket_accept (socket_t *sock,
socket_t *newsock,
struct sockaddr *saddr,
socklen_t *len) {
while (IS_SOCKET_ERROR(*newsock = accept(*sock, saddr, len))) {
if (socket_error() == EINTR)
continue; continue;


return 1; return 1;
} }




static int socket_recv (socket_t * sock, void * buf, size_t len)
{
int length;
static ssize_t socket_recv (socket_t *sock,
void *buf,
size_t len) {
ssize_t length;


while ( (length = recv (*sock, buf, len, 0)) < 0 )
{
while ((length = recv(*sock, buf, len, 0)) < 0) {
int err = socket_error(); int err = socket_error();
if ( err != EINTR && err != EAGAIN )
if (err != EINTR && err != EAGAIN)
break; break;
} }


} }




static int socket_send (socket_t * sock, const void *buf, size_t len)
{
int length;
static ssize_t socket_send (socket_t *sock,
const void *buf,
size_t len) {
ssize_t length;


while ( (length = send (*sock, buf, len, 0)) < 0 )
{
while ((length = send(*sock, buf, len, 0)) < 0) {
int err = socket_error(); int err = socket_error();
if ( err != EINTR && err != EAGAIN ) if ( err != EINTR && err != EAGAIN )

+ 115
- 121
libircclient/src/ssl.c Ver fichero

static CRITICAL_SECTION * mutex_buf = 0; static CRITICAL_SECTION * mutex_buf = 0;


// OpenSSL callback to utilize static locks // OpenSSL callback to utilize static locks
static void cb_openssl_locking_function( int mode, int n, const char * file, int line )
{
if ( mode & CRYPTO_LOCK)
EnterCriticalSection( &mutex_buf[n] );
static void cb_openssl_locking_function (int mode,
int n,
const char *file,
int line) {
if (mode & CRYPTO_LOCK)
EnterCriticalSection(&mutex_buf[n]);
else else
LeaveCriticalSection( &mutex_buf[n] );
LeaveCriticalSection(&mutex_buf[n]);
} }


// OpenSSL callback to get the thread ID // OpenSSL callback to get the thread ID
static unsigned long cb_openssl_id_function(void)
{
return ((unsigned long) GetCurrentThreadId() );
static unsigned long cb_openssl_id_function (void) {
return ((unsigned long) GetCurrentThreadId());
} }


static int alloc_mutexes( unsigned int total )
{
static int alloc_mutexes (unsigned int total) {
unsigned int i; unsigned int i;
// Enable thread safety in OpenSSL // Enable thread safety in OpenSSL
mutex_buf = (CRITICAL_SECTION*) malloc( total * sizeof(CRITICAL_SECTION) );
mutex_buf = (CRITICAL_SECTION *) malloc(total *sizeof(CRITICAL_SECTION));


if ( !mutex_buf )
if (!mutex_buf)
return -1; return -1;


for ( i = 0; i < total; i++)
InitializeCriticalSection( &(mutex_buf[i]) );
for (i = 0; i < total; i++)
InitializeCriticalSection(&(mutex_buf[i]));
return 0; return 0;
} }
static pthread_mutex_t * mutex_buf = 0; static pthread_mutex_t * mutex_buf = 0;


// OpenSSL callback to utilize static locks // OpenSSL callback to utilize static locks
static void cb_openssl_locking_function( int mode, int n, const char * file, int line )
{
static void cb_openssl_locking_function (int mode,
int n,
const char *file,
int line) {
(void)file; (void)file;
(void)line; (void)line;


if ( mode & CRYPTO_LOCK)
pthread_mutex_lock( &mutex_buf[n] );
if (mode & CRYPTO_LOCK)
pthread_mutex_lock(&mutex_buf[n]);
else else
pthread_mutex_unlock( &mutex_buf[n] );
pthread_mutex_unlock(&mutex_buf[n]);
} }


// OpenSSL callback to get the thread ID // OpenSSL callback to get the thread ID
static unsigned long cb_openssl_id_function()
{
return ((unsigned long) pthread_self() );
static void cb_openssl_id_function(CRYPTO_THREADID * id) {
CRYPTO_THREADID_set_pointer(id, pthread_self());
} }


static int alloc_mutexes( unsigned int total )
{
static int alloc_mutexes(unsigned int total) {
unsigned i; unsigned i;
// Enable thread safety in OpenSSL // Enable thread safety in OpenSSL
mutex_buf = (pthread_mutex_t*) malloc( total * sizeof(pthread_mutex_t) );
mutex_buf = (pthread_mutex_t *) malloc(total *sizeof(pthread_mutex_t));


if ( !mutex_buf )
if (!mutex_buf)
return -1; return -1;


for ( i = 0; i < total; i++)
pthread_mutex_init( &(mutex_buf[i]), 0 );
for (i = 0; i < total; i++)
pthread_mutex_init(&(mutex_buf[i]), 0);
return 0; return 0;
} }


#endif #endif


static int ssl_init_context( irc_session_t * session )
{
static int ssl_init_context(irc_session_t *session) {
// Load the strings and init the library // Load the strings and init the library
SSL_load_error_strings(); SSL_load_error_strings();


// Enable thread safety in OpenSSL // Enable thread safety in OpenSSL
if ( alloc_mutexes( CRYPTO_num_locks() ) )
if (alloc_mutexes( CRYPTO_num_locks()))
return LIBIRC_ERR_NOMEM; return LIBIRC_ERR_NOMEM;


// Register our callbacks // Register our callbacks
CRYPTO_set_id_callback( cb_openssl_id_function );
CRYPTO_set_locking_callback( cb_openssl_locking_function );
CRYPTO_THREADID_set_callback(cb_openssl_id_function);
CRYPTO_set_locking_callback(cb_openssl_locking_function);


// Init it // Init it
if ( !SSL_library_init() )
return LIBIRC_ERR_SSL_INIT_FAILED;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_library_init();
#else
OPENSSL_init_ssl(0, NULL);
#endif


if ( RAND_status() == 0 )
if (RAND_status() == 0)
return LIBIRC_ERR_SSL_INIT_FAILED; return LIBIRC_ERR_SSL_INIT_FAILED;


// Create an SSL context; currently a single context is used for all connections // Create an SSL context; currently a single context is used for all connections
ssl_context = SSL_CTX_new( SSLv23_method() );
ssl_context = SSL_CTX_new(SSLv23_method());


if ( !ssl_context )
if (!ssl_context)
return LIBIRC_ERR_SSL_INIT_FAILED; return LIBIRC_ERR_SSL_INIT_FAILED;


// Disable SSLv2 as it is unsecure // Disable SSLv2 as it is unsecure
if ( (SSL_CTX_set_options( ssl_context, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) == 0 )
if ((SSL_CTX_set_options(ssl_context, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) == 0)
return LIBIRC_ERR_SSL_INIT_FAILED; return LIBIRC_ERR_SSL_INIT_FAILED;


// Enable only strong ciphers // Enable only strong ciphers
if ( SSL_CTX_set_cipher_list( ssl_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH" ) != 1 )
if (SSL_CTX_set_cipher_list(ssl_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1)
return LIBIRC_ERR_SSL_INIT_FAILED; return LIBIRC_ERR_SSL_INIT_FAILED;


// Set the verification // Set the verification
if ( session->options & LIBIRC_OPTION_SSL_NO_VERIFY )
SSL_CTX_set_verify( ssl_context, SSL_VERIFY_NONE, 0 );
if (session->options & LIBIRC_OPTION_SSL_NO_VERIFY)
SSL_CTX_set_verify(ssl_context, SSL_VERIFY_NONE, 0);
else else
SSL_CTX_set_verify( ssl_context, SSL_VERIFY_PEER, 0 );
SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, 0);
// Disable session caching // Disable session caching
SSL_CTX_set_session_cache_mode( ssl_context, SSL_SESS_CACHE_OFF );
SSL_CTX_set_session_cache_mode(ssl_context, SSL_SESS_CACHE_OFF);


// Enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER so we can move the buffer during sending // Enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER so we can move the buffer during sending
SSL_CTX_set_mode( ssl_context, SSL_CTX_get_mode(ssl_context) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE );
SSL_CTX_set_mode( ssl_context, SSL_CTX_get_mode(ssl_context)
| SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
| SSL_MODE_ENABLE_PARTIAL_WRITE);
return 0; return 0;
} }
#endif #endif


// Initializes the SSL context. Must be called after the socket is created. // Initializes the SSL context. Must be called after the socket is created.
static int ssl_init( irc_session_t * session )
{
static int ssl_init (irc_session_t *session {
static int ssl_context_initialized = 0; static int ssl_context_initialized = 0;
#if defined (_WIN32) #if defined (_WIN32)
static HANDLE initmutex = 0; static HANDLE initmutex = 0;
// First time run? Create the mutex // First time run? Create the mutex
if ( initmutex == 0 )
{
HANDLE m = CreateMutex( 0, FALSE, 0 );
if (initmutex == 0) {
HANDLE m = CreateMutex(0, FALSE, 0);


// Now we check if the mutex has already been created by another thread performing the init concurrently. // Now we check if the mutex has already been created by another thread performing the init concurrently.
// If it was, we close our mutex and use the original one. This could be done synchronously by using the // If it was, we close our mutex and use the original one. This could be done synchronously by using the
// InterlockedCompareExchangePointer function. // InterlockedCompareExchangePointer function.
if ( InterlockedCompareExchangePointer( &m, m, 0 ) != 0 )
CloseHandle( m );
if (InterlockedCompareExchangePointer(&m, m, 0) != 0)
CloseHandle(m);
} }
#else #else
static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
// irc_connect() and this function may be called simultaneously from different threads. So we have // irc_connect() and this function may be called simultaneously from different threads. So we have
// to use mutex on Linux because it allows static mutex initialization. Windows doesn't, so here // to use mutex on Linux because it allows static mutex initialization. Windows doesn't, so here
// we do the sabre dance around it. // we do the sabre dance around it.
SSLINIT_LOCK_MUTEX( initmutex );
SSLINIT_LOCK_MUTEX(initmutex);


if ( ssl_context_initialized == 0 )
{
int res = ssl_init_context( session );
if (ssl_context_initialized == 0) {
int res = ssl_init_context(session);
if ( res )
{
SSLINIT_UNLOCK_MUTEX( initmutex );
if (res) {
SSLINIT_UNLOCK_MUTEX(initmutex);
return res; return res;
} }
ssl_context_initialized = 1; ssl_context_initialized = 1;
} }
SSLINIT_UNLOCK_MUTEX( initmutex );
SSLINIT_UNLOCK_MUTEX(initmutex);
// Get the SSL context // Get the SSL context
session->ssl = SSL_new( ssl_context );
session->ssl = SSL_new(ssl_context);


if ( !session->ssl )
if (!session->ssl)
return LIBIRC_ERR_SSL_INIT_FAILED; return LIBIRC_ERR_SSL_INIT_FAILED;


// Let OpenSSL use our socket // Let OpenSSL use our socket
if ( SSL_set_fd( session->ssl, session->sock) != 1 )
if (SSL_set_fd( session->ssl, session->sock) != 1)
return LIBIRC_ERR_SSL_INIT_FAILED; return LIBIRC_ERR_SSL_INIT_FAILED;
// Since we're connecting on our own, tell openssl about it // Since we're connecting on our own, tell openssl about it
SSL_set_connect_state( session->ssl );
SSL_set_connect_state(session->ssl);


return 0; return 0;
} }


static void ssl_handle_error( irc_session_t * session, int ssl_error )
{
if ( ERR_GET_LIB(ssl_error) == ERR_LIB_SSL )
{
if ( ERR_GET_REASON(ssl_error) == SSL_R_CERTIFICATE_VERIFY_FAILED )
{
static void ssl_handle_error (irc_session_t *session,
int ssl_error) {
if (ERR_GET_LIB(ssl_error) == ERR_LIB_SSL) {
if (ERR_GET_REASON(ssl_error) == SSL_R_CERTIFICATE_VERIFY_FAILED) {
session->lasterror = LIBIRC_ERR_SSL_CERT_VERIFY_FAILED; session->lasterror = LIBIRC_ERR_SSL_CERT_VERIFY_FAILED;
return; return;
} }
if ( ERR_GET_REASON(ssl_error) == SSL_R_UNKNOWN_PROTOCOL )
{
if (ERR_GET_REASON(ssl_error) == SSL_R_UNKNOWN_PROTOCOL) {
session->lasterror = LIBIRC_ERR_CONNECT_SSL_FAILED; session->lasterror = LIBIRC_ERR_CONNECT_SSL_FAILED;
return; return;
} }
} }


#if defined (ENABLE_DEBUG) #if defined (ENABLE_DEBUG)
if ( IS_DEBUG_ENABLED(session) )
fprintf (stderr, "[DEBUG] SSL error: %s\n\t(%d, %d)\n",
ERR_error_string( ssl_error, NULL), ERR_GET_LIB( ssl_error), ERR_GET_REASON(ssl_error) );
if (IS_DEBUG_ENABLED(session))
fprintf (stderr, "[DEBUG] SSL error: %s\n\t(%d, %d)\n",
ERR_error_string(ssl_error, NULL),
ERR_GET_LIB( ssl_error),
ERR_GET_REASON(ssl_error));
#endif #endif
} }


static int ssl_recv( irc_session_t * session )
{
static int ssl_recv (irc_session_t *session) {
int count; int count;
unsigned int amount = (sizeof (session->incoming_buf) - 1) - session->incoming_offset; unsigned int amount = (sizeof (session->incoming_buf) - 1) - session->incoming_offset;
ERR_clear_error(); ERR_clear_error();


// Read up to m_bufferLength bytes // Read up to m_bufferLength bytes
count = SSL_read( session->ssl, session->incoming_buf + session->incoming_offset, amount );
count = SSL_read(session->ssl,
session->incoming_buf + session->incoming_offset,
amount);


if ( count > 0 )
if (count > 0) {
return count; return count;
else if ( count == 0 )
} else if (count == 0) {
return -1; // remote connection closed return -1; // remote connection closed
else
{
int ssl_error = SSL_get_error( session->ssl, count );
} else {
int ssl_error = SSL_get_error(session->ssl, count);
// Handle SSL error since not all of them are actually errors // Handle SSL error since not all of them are actually errors
switch ( ssl_error )
{
switch (ssl_error) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
// This is not really an error. We received something, but // This is not really an error. We received something, but
// OpenSSL gave nothing to us because all it read was // OpenSSL gave nothing to us because all it read was
} }


// This is an SSL error, handle it // This is an SSL error, handle it
ssl_handle_error( session, ERR_get_error() );
ssl_handle_error(session, ERR_get_error());
} }
return -1; return -1;
} }




static int ssl_send( irc_session_t * session )
{
static int ssl_send (irc_session_t *session) {
int count; int count;
ERR_clear_error(); ERR_clear_error();


count = SSL_write( session->ssl, session->outgoing_buf, session->outgoing_offset );
count = SSL_write(session->ssl,
session->outgoing_buf,
session->outgoing_offset);


if ( count > 0 )
if (count > 0) {
return count; return count;
else if ( count == 0 )
} else if (count == 0) {
return -1; return -1;
else
{
int ssl_error = SSL_get_error( session->ssl, count );
} else {
int ssl_error = SSL_get_error(session->ssl, count);
switch ( ssl_error )
{
switch (ssl_error) {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
// This is not really an error. We sent some internal OpenSSL data, // This is not really an error. We sent some internal OpenSSL data,
// but now it needs to read more data before it can send anything. // but now it needs to read more data before it can send anything.
} }
// This is an SSL error, handle it // This is an SSL error, handle it
ssl_handle_error( session, ERR_get_error() );
ssl_handle_error(session, ERR_get_error());
} }


return -1; return -1;
// Returns -1 in case there is an error and socket should be closed/connection terminated // Returns -1 in case there is an error and socket should be closed/connection terminated
// Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case) // Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case)
// Returns a positive number if we actually read something // Returns a positive number if we actually read something
static int session_socket_read( irc_session_t * session )
{
int length;
static ssize_t session_socket_read (irc_session_t *session) {
ssize_t length;


#if defined (ENABLE_SSL) #if defined (ENABLE_SSL)
if ( session->ssl )
{
if (session->ssl) {
// Yes, I know this is tricky // Yes, I know this is tricky
if ( session->flags & SESSIONFL_SSL_READ_WANTS_WRITE )
{
if (session->flags & SESSIONFL_SSL_READ_WANTS_WRITE) {
session->flags &= ~SESSIONFL_SSL_READ_WANTS_WRITE; session->flags &= ~SESSIONFL_SSL_READ_WANTS_WRITE;
ssl_send( session );
ssl_send(session);
return 0; return 0;
} }
return ssl_recv( session );
return ssl_recv(session);
} }
#endif #endif
length = socket_recv( &session->sock,
session->incoming_buf + session->incoming_offset,
(sizeof (session->incoming_buf) - 1) - session->incoming_offset );
length = socket_recv(&session->sock,
session->incoming_buf + session->incoming_offset,
(sizeof (session->incoming_buf) - 1) - session->incoming_offset);
// There is no "retry" errors for regular sockets // There is no "retry" errors for regular sockets
if ( length <= 0 )
if (length <= 0)
return -1; return -1;
return length; return length;
// Returns -1 in case there is an error and socket should be closed/connection terminated // Returns -1 in case there is an error and socket should be closed/connection terminated
// Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case) // Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case)
// Returns a positive number if we actually sent something // Returns a positive number if we actually sent something
static int session_socket_write( irc_session_t * session )
{
int length;
static ssize_t session_socket_write (irc_session_t *session) {
ssize_t length;


#if defined (ENABLE_SSL) #if defined (ENABLE_SSL)
if ( session->ssl )
{
if (session->ssl) {
// Yep // Yep
if ( session->flags & SESSIONFL_SSL_WRITE_WANTS_READ )
{
if (session->flags & SESSIONFL_SSL_WRITE_WANTS_READ) {
session->flags &= ~SESSIONFL_SSL_WRITE_WANTS_READ; session->flags &= ~SESSIONFL_SSL_WRITE_WANTS_READ;
ssl_recv( session );
ssl_recv(session);
return 0; return 0;
} }
return ssl_send( session );
return ssl_send(session);
} }
#endif #endif
length = socket_send (&session->sock, session->outgoing_buf, session->outgoing_offset);
length = socket_send (&session->sock,
session->outgoing_buf,
session->outgoing_offset);
// There is no "retry" errors for regular sockets // There is no "retry" errors for regular sockets
if ( length <= 0 )
if (length <= 0)
return -1; return -1;
return length; return length;

+ 48
- 48
libircclient/src/utils.c Ver fichero

* License for more details. * License for more details.
*/ */


static void libirc_add_to_set (int fd, fd_set *set, int * maxfd)
{
static void libirc_add_to_set (int fd,
fd_set *set,
int *maxfd) {
FD_SET (fd, set); FD_SET (fd, set);


if ( *maxfd < fd )
if (*maxfd < fd)
*maxfd = fd; *maxfd = fd;
} }


#if defined (ENABLE_DEBUG) #if defined (ENABLE_DEBUG)
static void libirc_dump_data (const char * prefix, const char * buf, unsigned int length)
{
static void libirc_dump_data (const char *prefix,
const char *buf,
unsigned int length) {
printf ("%s: ", prefix); printf ("%s: ", prefix);
for ( ; length > 0; length -- )
for (; length > 0; length--)
printf ("%c", *buf++); printf ("%c", *buf++);
} }
#endif #endif
/* /*
* Finds a separator (\x0D\x0A), which separates two lines. * Finds a separator (\x0D\x0A), which separates two lines.
*/ */
static int libirc_findcrlf (const char * buf, int length)
{
int offset = 0;
for ( ; offset < length; offset++ )
{
if ( buf[offset] == 0x0D && offset < length - 1 && buf[offset+1] == 0x0A )
static size_t libirc_findcrlf (const char *buf,
size_t length) {
size_t offset = 0;
for (; offset < length; offset++) {
if ( buf[offset] == 0x0D
&& offset < length - 1
&& buf[offset+1] == 0x0A)
return offset; return offset;
if ( buf[offset] == 0x0A)
if (buf[offset] == 0x0A)
return offset; return offset;
} }


return 0; return 0;
} }


static int libirc_findcrlf_offset(const char *buf, int offset, const int length)
{
for(; offset < length; offset++)
{
if(buf[offset] != 0x0D && buf[offset] != 0x0A)
{
static size_t libirc_findcrlf_offset (const char *buf,
size_t offset,
const size_t length) {
for(; offset < length; offset++) {
if ( buf[offset] != 0x0D
&& buf[offset] != 0x0A) {
break; break;
} }
} }
return offset; return offset;
} }


static int libirc_findcrorlf (char * buf, int length)
{
int offset = 0;
for ( ; offset < length; offset++ )
{
if ( buf[offset] == 0x0D || buf[offset] == 0x0A )
{
static size_t libirc_findcrorlf (char *buf,
size_t length) {
size_t offset = 0;
for (; offset < length; offset++) {
if ( buf[offset] == 0x0D
|| buf[offset] == 0x0A) {
buf[offset++] = '\0'; buf[offset++] = '\0';


if ( offset < (length - 1)
&& (buf[offset] == 0x0D || buf[offset] == 0x0A) )
if ( offset < (length - 1)
&& ( buf[offset] == 0x0D
|| buf[offset] == 0x0A)
)
offset++; offset++;


return offset; return offset;
} }




static void libirc_event_ctcp_internal (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count)
{
(void)event;
(void)count;
static void libirc_event_ctcp_internal (irc_session_t *session,
const char *event,
const char *origin,
const char **params,
unsigned int count) {
(void) event;
(void) count;


if ( origin )
{
if (origin) {
char nickbuf[128], textbuf[256]; char nickbuf[128], textbuf[256];
irc_target_get_nick (origin, nickbuf, sizeof(nickbuf)); irc_target_get_nick (origin, nickbuf, sizeof(nickbuf));


if ( strstr (params[0], "PING") == params[0] )
if (strstr (params[0], "PING") == params[0]) {
irc_cmd_ctcp_reply (session, nickbuf, params[0]); irc_cmd_ctcp_reply (session, nickbuf, params[0]);
else if ( !strcmp (params[0], "VERSION") )
{
if ( !session->ctcp_version )
{
} else if (!strcmp (params[0], "VERSION")) {
if (!session->ctcp_version) {
unsigned int high, low; unsigned int high, low;
irc_get_version (&high, &low); irc_get_version (&high, &low);


snprintf (textbuf, sizeof (textbuf), "VERSION libircclient by Georgy Yunaev ver.%d.%d", high, low); snprintf (textbuf, sizeof (textbuf), "VERSION libircclient by Georgy Yunaev ver.%d.%d", high, low);
}
else
} else {
snprintf (textbuf, sizeof (textbuf), "VERSION %s", session->ctcp_version); snprintf (textbuf, sizeof (textbuf), "VERSION %s", session->ctcp_version);
}


irc_cmd_ctcp_reply (session, nickbuf, textbuf); irc_cmd_ctcp_reply (session, nickbuf, textbuf);
}
else if ( !strcmp (params[0], "FINGER") )
{
} else if (!strcmp (params[0], "FINGER")) {
sprintf (textbuf, "FINGER %s (%s) Idle 0 seconds", sprintf (textbuf, "FINGER %s (%s) Idle 0 seconds",
session->username ? session->username : "nobody", session->username ? session->username : "nobody",
session->realname ? session->realname : "noname"); session->realname ? session->realname : "noname");


irc_cmd_ctcp_reply (session, nickbuf, textbuf); irc_cmd_ctcp_reply (session, nickbuf, textbuf);
}
else if ( !strcmp (params[0], "TIME") )
{
} else if (!strcmp (params[0], "TIME")) {
time_t now = time(0); time_t now = time(0);


#if defined (ENABLE_THREADS) && defined (HAVE_LOCALTIME_R) #if defined (ENABLE_THREADS) && defined (HAVE_LOCALTIME_R)
struct tm tmtmp, *ltime = localtime_r (&now, &tmtmp); struct tm tmtmp, *ltime = localtime_r (&now, &tmtmp);
#else #else
struct tm * ltime = localtime (&now);
struct tm *ltime = localtime (&now);
#endif #endif
strftime (textbuf, sizeof(textbuf), "%a %b %d %H:%M:%S %Z %Y", ltime); strftime (textbuf, sizeof(textbuf), "%a %b %d %H:%M:%S %Z %Y", ltime);
irc_cmd_ctcp_reply (session, nickbuf, textbuf); irc_cmd_ctcp_reply (session, nickbuf, textbuf);

Cargando…
Cancelar
Guardar