Few tweaks and some docs

- Use provided IRC_Message structs instead of global
- Add documentation
This commit is contained in:
Alex D. 2021-01-23 15:07:55 +00:00
parent 8a9b320ea4
commit 2949d02516
Signed by: caskd
GPG Key ID: F92BA85F61F4C173
16 changed files with 268 additions and 156 deletions

View File

@ -102,10 +102,15 @@ if(BUILD_DOCS)
find_package(Doxygen REQUIRED)
if (DOXYGEN_FOUND)
set(DOXYGEN_SOURCE_BROWSER YES)
set(DOXYGEN_EXTRACT_ALL YES)
set(DOXYGEN_MACRO_EXPANSION YES)
set(DOXYGEN_EXPAND_ONLY_PREDEF YES)
set(DOXYGEN_PREDEFINED
"UIRC_HELPERS"
"UIRC_IRCV3"
)
doxygen_add_docs(docgen
${UIRC_HEADERS}
src/public
src/doc/main.doc
README.md
ALL
)

View File

@ -28,7 +28,7 @@ Example for **make**:
make -C build
```
You now should have the library built at `build/libuirc.so` *(or your build output path)*
You now should have the library built at `build/libuirc.a` or `build/libuirc.so.VERSION`
## License

View File

@ -39,20 +39,20 @@ Assm_user(char* buf, IRC_User* in, size_t len, bool useorig)
assert(in != NULL);
char* pos = buf;
if (in->nick == NULL && in->host != NULL) {
if (!safe_strcpy(&pos, in->host, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->host, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
} else if (in->nick != NULL) {
if (!safe_strcpy(&pos, in->nick, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->nick, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (in->user != NULL) {
if (!safe_charcpy(&pos, '!', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->user, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, '!', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->user, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
if (useorig && in->orig != NULL) {
if (!safe_charcpy(&pos, '%', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->orig, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, '%', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->orig, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
if (in->host != NULL) {
if (!safe_charcpy(&pos, '@', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->host, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, '@', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, in->host, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
} else
return ERR_UIRC_INVALID_FORMAT;
@ -74,17 +74,17 @@ Assm_tags(char* buf, IRC_Tags* in, size_t len)
for (unsigned int i = 0; i < sizeof(tagmps) / sizeof(struct tagmapping); i++) {
if ((*tagmps[i].assg).value != NULL) {
if (pos == buf) {
if (!safe_charcpy(&pos, '@', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, '@', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
} else {
if (!safe_charcpy(&pos, ';', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, ';', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
if ((*tagmps[i].assg).clientbound) {
if (!safe_charcpy(&pos, '+', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, '+', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
if (!safe_strcpy(&pos, tagmps[i].name, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, tagmps[i].name, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (*(*tagmps[i].assg).value != '\0') {
if (!safe_charcpy(&pos, '=', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, (*tagmps[i].assg).value, len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, '=', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, (*tagmps[i].assg).value, len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
}
}
@ -100,18 +100,18 @@ Assm_mesg(char* buf, IRC_Message* in, size_t len)
char* pos = buf;
signed long cnt, ret;
#ifdef UIRC_IRCV3
if ((ret = Assm_tags(pos, &in->tags, len - (unsigned long) (pos - buf))) < 0) return ret;
if ((ret = Assm_tags(pos, &in->tags, len - (size_t)(pos - buf))) < 0) return ret;
else if (ret != 0) {
pos += ret;
if (!safe_charcpy(&pos, ' ', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, ' ', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
#endif /* UIRC_IRCV3 */
if (in->name.nick != NULL || in->name.host != NULL) {
if (!safe_charcpy(&pos, ':', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if ((ret = Assm_user(pos, &in->name, len - (unsigned long) (pos - buf), false)) <= 0) return ret;
if (!safe_charcpy(&pos, ':', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
if ((ret = Assm_user(pos, &in->name, len - (size_t)(pos - buf), false)) <= 0) return ret;
else
pos += ret;
if (!safe_charcpy(&pos, ' ', len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_charcpy(&pos, ' ', len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
}
if (in->cmd < UIRC_FCMD || in->cmd > UIRC_LCMD) {
if ((cnt = snprintf(pos, 4, "%.3i", in->cmd)) == 3) pos += cnt;
@ -120,155 +120,152 @@ Assm_mesg(char* buf, IRC_Message* in, size_t len)
} else {
if (IRC_Cmds[in->cmd] != NULL) {
size_t cmdlen = strlen(IRC_Cmds[in->cmd]);
if (len - (unsigned long) (pos - buf) > cmdlen && strcpy(pos, IRC_Cmds[in->cmd]) != NULL) pos += cmdlen;
if (len - (size_t)(pos - buf) > cmdlen && strcpy(pos, IRC_Cmds[in->cmd]) != NULL) pos += cmdlen;
else
return ERR_UIRC_UNKNOWN_TOKEN;
}
}
for (unsigned int i = 0; in->args[i] != NULL; i++) {
if (len - (unsigned long) (pos - buf) > strlen(in->args[i]) + 2
&& (cnt =
snprintf(pos, len - (unsigned long) (pos - buf), (in->args[i + 1] == NULL && in->trailing) ? " :%s" : " %s", in->args[i]))
> 0)
if (len - (size_t)(pos - buf) > strlen(in->args[i]) + 2
&& (cnt = snprintf(pos, len - (size_t)(pos - buf), (in->args[i + 1] == NULL && in->trailing) ? " :%s" : " %s", in->args[i])) > 0)
pos += cnt;
else
return ERR_UIRC_BUFFER_ERR;
}
if (!safe_strcpy(&pos, "\r\n", len - (unsigned long) (pos - buf))) return ERR_UIRC_BUFFER_ERR;
if (!safe_strcpy(&pos, "\r\n", len - (size_t)(pos - buf))) return ERR_UIRC_BUFFER_ERR;
return pos - buf;
}
#ifdef UIRC_HELPERS
static IRC_Message imassm_mesg;
#define RESERVED "*";
void
clear_assm(void)
clear_assm(IRC_Message* imassm_mesg)
{
memset((void*) &imassm_mesg, '\0', sizeof(IRC_Message));
memset((void*) imassm_mesg, '\0', sizeof(IRC_Message));
}
IRC_Message*
Assm_AUTO(IRC_Command cmd, bool trailing, char** args, int req)
Assm_AUTO(IRC_Message* imassm_mesg, IRC_Command cmd, bool trailing, char** args, int req)
{
clear_assm();
clear_assm(imassm_mesg);
int i;
for (i = 0; args[i] != NULL && i < 15; i++) { imassm_mesg.args[i] = args[i]; }
for (i = 0; args[i] != NULL && i < 15; i++) { imassm_mesg->args[i] = args[i]; }
if (i < req) return NULL;
imassm_mesg.trailing = trailing;
imassm_mesg.cmd = cmd;
return &imassm_mesg;
imassm_mesg->trailing = trailing;
imassm_mesg->cmd = cmd;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_USER(char* user, char* realname, int modes)
Assm_cmd_USER(IRC_Message* imassm_mesg, char* user, char* realname, int modes)
{
if (user == NULL || modes < 0 || modes > (MBMASK_INVIS | MBMASK_WALLOPS)) return NULL;
clear_assm();
clear_assm(imassm_mesg);
static char local_mode[2];
snprintf(local_mode, 2, "%i", modes);
imassm_mesg.args[0] = user;
imassm_mesg.args[1] = local_mode;
imassm_mesg.args[2] = RESERVED;
imassm_mesg.args[3] = realname;
imassm_mesg.trailing = true;
imassm_mesg.cmd = USER;
return &imassm_mesg;
imassm_mesg->args[0] = user;
imassm_mesg->args[1] = local_mode;
imassm_mesg->args[2] = RESERVED;
imassm_mesg->args[3] = realname;
imassm_mesg->trailing = true;
imassm_mesg->cmd = USER;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_LINKS(char* remoteserv, char* servmask)
Assm_cmd_LINKS(IRC_Message* imassm_mesg, char* remoteserv, char* servmask)
{
if (remoteserv != NULL && servmask == NULL) return NULL;
clear_assm();
imassm_mesg.args[0] = (remoteserv == NULL) ? servmask : remoteserv;
imassm_mesg.args[1] = (remoteserv == NULL) ? NULL : servmask;
imassm_mesg.cmd = LINKS;
return &imassm_mesg;
clear_assm(imassm_mesg);
imassm_mesg->args[0] = (remoteserv == NULL) ? servmask : remoteserv;
imassm_mesg->args[1] = (remoteserv == NULL) ? NULL : servmask;
imassm_mesg->cmd = LINKS;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_WHO(char* mask, bool oper)
Assm_cmd_WHO(IRC_Message* imassm_mesg, char* mask, bool oper)
{
static char* operator= "o";
if (oper && mask == NULL) return NULL;
clear_assm();
imassm_mesg.args[0] = mask;
imassm_mesg.args[1] = (oper) ? operator: NULL;
imassm_mesg.cmd = WHO;
return &imassm_mesg;
clear_assm(imassm_mesg);
imassm_mesg->args[0] = mask;
imassm_mesg->args[1] = (oper) ? operator: NULL;
imassm_mesg->cmd = WHO;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_WHOIS(char* target, char* mask)
Assm_cmd_WHOIS(IRC_Message* imassm_mesg, char* target, char* mask)
{
if (mask == NULL) return NULL;
clear_assm();
imassm_mesg.args[0] = (target == NULL) ? mask : target;
imassm_mesg.args[1] = (target == NULL) ? NULL : mask;
imassm_mesg.cmd = WHOIS;
return &imassm_mesg;
clear_assm(imassm_mesg);
imassm_mesg->args[0] = (target == NULL) ? mask : target;
imassm_mesg->args[1] = (target == NULL) ? NULL : mask;
imassm_mesg->cmd = WHOIS;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_WHOWAS(char* nick, char* count, char* target)
Assm_cmd_WHOWAS(IRC_Message* imassm_mesg, char* nick, char* count, char* target)
{
if (nick == NULL || (target != NULL && count == NULL)) return NULL;
clear_assm();
imassm_mesg.args[0] = nick;
imassm_mesg.args[1] = count;
imassm_mesg.args[2] = target;
imassm_mesg.cmd = WHOWAS;
return &imassm_mesg;
clear_assm(imassm_mesg);
imassm_mesg->args[0] = nick;
imassm_mesg->args[1] = count;
imassm_mesg->args[2] = target;
imassm_mesg->cmd = WHOWAS;
return imassm_mesg;
}
/* NOTE: This is what implementation you have to live with
* I would've just used the prefix to set the source but whatever
*/
IRC_Message*
Assm_cmd_PING(char* source, char* target)
Assm_cmd_PING(IRC_Message* imassm_mesg, char* source, char* target)
{
if (source == NULL && target == NULL) return NULL;
clear_assm();
imassm_mesg.args[0] = (source != NULL) ? source : target;
imassm_mesg.args[1] = (source != NULL && target != NULL) ? target : NULL;
imassm_mesg.trailing = (source != NULL && target == NULL) ? true : false;
imassm_mesg.cmd = PING;
return &imassm_mesg;
clear_assm(imassm_mesg);
imassm_mesg->args[0] = (source != NULL) ? source : target;
imassm_mesg->args[1] = (source != NULL && target != NULL) ? target : NULL;
imassm_mesg->trailing = (source != NULL && target == NULL) ? true : false;
imassm_mesg->cmd = PING;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_SUMMON(char* user, char* target, char* channel)
Assm_cmd_SUMMON(IRC_Message* imassm_mesg, char* user, char* target, char* channel)
{
if (user == NULL || (channel != NULL && target == NULL)) return NULL;
clear_assm();
imassm_mesg.args[0] = user;
imassm_mesg.args[1] = target;
imassm_mesg.args[2] = channel;
imassm_mesg.cmd = SUMMON;
return &imassm_mesg;
clear_assm(imassm_mesg);
imassm_mesg->args[0] = user;
imassm_mesg->args[1] = target;
imassm_mesg->args[2] = channel;
imassm_mesg->cmd = SUMMON;
return imassm_mesg;
}
IRC_Message*
Assm_cmd_USERHOST(char* users[])
Assm_cmd_USERHOST(IRC_Message* imassm_mesg, char* users[])
{
if (users[0] == NULL) return NULL;
clear_assm();
for (unsigned int i = 0; i < 5 && users[i] != NULL; i++) imassm_mesg.args[i] = users[i];
imassm_mesg.cmd = USERHOST;
return &imassm_mesg;
clear_assm(imassm_mesg);
for (unsigned int i = 0; i < 5 && users[i] != NULL; i++) imassm_mesg->args[i] = users[i];
imassm_mesg->cmd = USERHOST;
return imassm_mesg;
}
/* NOTE: Limited to 14 nicks per command */
IRC_Message*
Assm_cmd_ISON(char* users[])
Assm_cmd_ISON(IRC_Message* imassm_mesg, char* users[])
{
if (users[0] == NULL) return NULL;
clear_assm();
for (unsigned int i = 0; i < 14 && users[i] != NULL; i++) { imassm_mesg.args[i] = users[i]; }
imassm_mesg.cmd = ISON;
return &imassm_mesg;
clear_assm(imassm_mesg);
for (unsigned int i = 0; i < 14 && users[i] != NULL; i++) { imassm_mesg->args[i] = users[i]; }
imassm_mesg->cmd = ISON;
return imassm_mesg;
}
#endif /* UIRC_HELPERS */

30
src/doc/main.doc Normal file
View File

@ -0,0 +1,30 @@
/// ***************************************************************************
/// @mainpage MicroIRC library
///
/// @section Core
/// @subsection Assemblers
/// Assemblers are a quick way to convert structs to a string representation
///
/// - \ref Assm_mesg
/// - \ref Assm_user
///
/// @subsection Tokenizers
/// Tokenizers tokenize and point struct elements to the matching substrings in the string given
///
/// - \ref Tok_mesg
/// - \ref Tok_user
///
/// @section Additions
///
/// @subsection Validators
/// - \ref Val_mesg
///
/// @subsection IRCv3
/// @subsubsection Tags
/// - \ref Assm_tags
/// - \ref Tok_tags
///
/// @subsubsection Capabilities
///
///
/// ***************************************************************************

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#include "types.h"
#include <sys/types.h>
@ -29,22 +31,29 @@ signed long Assm_user(char* buf, IRC_User* in, size_t len, bool useorig);
signed long Assm_tags(char* buf, IRC_Tags* in, size_t len);
#endif /* UIRC_IRCV3*/
/*!
* \brief IRC_Message to string converter
*
* This assembles a IRC_Message struct to a string representation of a most size len
* The return value is either the lenght of the string or any of the uirc_errors errors
* \param[in] in IRC_Message struct that contains at least a command
* \param[in] len Maximum lenght of string
* \param[out] buf String representation of message (if successful)
* \warning in and buf SHOULD NOT be NULL, this will trigger a ASSERT so it's required to check it where needed
*/
signed long Assm_mesg(char* buf, IRC_Message* in, size_t len);
#ifdef UIRC_HELPERS
static IRC_Message imassm_mesg;
void clear_assm(void);
IRC_Message* Assm_AUTO(IRC_Command cmd, bool trailing, char** args, int req);
IRC_Message* Assm_cmd_USER(char* user, char* realname, int modes);
IRC_Message* Assm_cmd_LINKS(char* remoteserv, char* servmask);
IRC_Message* Assm_cmd_WHO(char* mask, bool oper);
IRC_Message* Assm_cmd_WHOIS(char* target, char* mask);
IRC_Message* Assm_cmd_WHOWAS(char* nick, char* count, char* target);
IRC_Message* Assm_cmd_PING(char* source, char* target);
IRC_Message* Assm_cmd_SUMMON(char* user, char* target, char* channel);
IRC_Message* Assm_cmd_USERHOST(char* users[]);
IRC_Message* Assm_cmd_ISON(char* users[]);
IRC_Message* Assm_AUTO(IRC_Message* imassm_mesg, IRC_Command cmd, bool trailing, char** args, int req);
IRC_Message* Assm_cmd_USER(IRC_Message* imassm_mesg, char* user, char* realname, int modes);
IRC_Message* Assm_cmd_LINKS(IRC_Message* imassm_mesg, char* remoteserv, char* servmask);
IRC_Message* Assm_cmd_WHO(IRC_Message* imassm_mesg, char* mask, bool oper);
IRC_Message* Assm_cmd_WHOIS(IRC_Message* imassm_mesg, char* target, char* mask);
IRC_Message* Assm_cmd_WHOWAS(IRC_Message* imassm_mesg, char* nick, char* count, char* target);
IRC_Message* Assm_cmd_PING(IRC_Message* imassm_mesg, char* source, char* target);
IRC_Message* Assm_cmd_SUMMON(IRC_Message* imassm_mesg, char* user, char* target, char* channel);
IRC_Message* Assm_cmd_USERHOST(IRC_Message* imassm_mesg, char* users[]);
IRC_Message* Assm_cmd_ISON(IRC_Message* imassm_mesg, char* users[]);
#endif /* UIRC_HELPERS */
#define Assm_cmd_REHASH() Assm_AUTO(REHASH, false, (char*[]) { NULL }, 0)

View File

@ -16,9 +16,18 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#ifndef UIRC_GUARD_CAPABILITIES
#define UIRC_GUARD_CAPABILITIES
/*!
* \brief Converts capability to bitmask value
*
* \param[in] cap Capability bit from \link caps \endlink
*/
#define CAPBIT(cap) (1 << (cap))
/*!
* \brief List of capabilities to be used as a bitmask
*
@ -26,34 +35,27 @@
* \sa https://ircv3.net/registry#capabilities
*/
enum caps {
CAP_ACCOUNT_NOTIFY = 1,
CAP_ACCOUNT_TAG = 2,
CAP_AWAY_NOTIFY = 3,
CAP_BATCH = 4,
CAP_CAP_NOTIFY = 5,
CAP_CHANNEL_RENAME = 6,
CAP_CHGHOST = 7,
CAP_ECHO_MESSAGE = 8,
CAP_EXTENDED_JOIN = 9,
CAP_INVITE_NOTIFY = 10,
CAP_LABELED_RESPONSE = 11,
CAP_MESSAGE_TAGS = 12,
CAP_MONITOR = 13,
CAP_MULTI_PREFIX = 14,
CAP_MULTILINE = 15,
CAP_SASL = 16,
CAP_SERVER_TIME = 17,
CAP_SETNAME = 18,
CAP_TLS = 19,
CAP_USERHOST_IN_NAMES = 20,
CAP_ACCOUNT_NOTIFY,
CAP_ACCOUNT_TAG,
CAP_AWAY_NOTIFY,
CAP_BATCH,
CAP_CAP_NOTIFY,
CAP_CHANNEL_RENAME,
CAP_CHGHOST,
CAP_ECHO_MESSAGE,
CAP_EXTENDED_JOIN,
CAP_INVITE_NOTIFY,
CAP_LABELED_RESPONSE,
CAP_MESSAGE_TAGS,
CAP_MONITOR,
CAP_MULTI_PREFIX,
CAP_MULTILINE,
CAP_SASL,
CAP_SERVER_TIME,
CAP_SETNAME,
CAP_TLS,
CAP_USERHOST_IN_NAMES,
};
/*!
* \brief Converts capability to bitmask value
*
* \param[in] cap Capability bit from \link caps \endlink
*/
#define CAPBIT(cap) (1 << (cap))
#ifdef UIRC_HELPERS
/*!
* \brief Converts a string of capabilities to a bitmask

View File

@ -16,36 +16,74 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#ifndef UIRC_GUARD_COMMANDS
#define UIRC_GUARD_COMMANDS
#define UIRC_FCMD ADMIN
/*!
* \brief List of possible string commands
*
* This contains all the commands defined by RFC2812 (LIST, TIME, NAMES, QUIT ...) and extra ones defined by submodules
* It is used for mapping string commands to integers instead of storing them as strings
*/
enum commands {
/*! Used to find information about the administrator of the given server, or current server */
ADMIN = 10,
/*! Clients can set an automatic reply string for any PRIVMSG commands directed at them */
AWAY,
/*! Used to request a server to try to establish a new connection to another server immediately */
CONNECT,
/*! Shutdown the server */
DIE,
/*! Used by servers when reporting a serious or fatal error to its peers */
ERROR,
/*! Return information describing the server */
INFO,
/*! Invite a user to a channel */
INVITE,
/*! Checks whether a given nickname is currently on IRC */
ISON,
/*! Request to start listening to the specific channel */
JOIN,
/*! Request the forced removal of a user from a channel */
KICK,
/*! Closes client-server connection */
KILL,
/*! List all servernames */
LINKS,
/*! List channels and their topics */
LIST,
/*! Get statistics about the size of the IRC network */
LUSERS,
/*! Query and change the characteristics of a channel */
MODE,
/*! Get the "Message Of The Day" of the given server */
MOTD,
/*! List all nicknames that are visible to him */
NAMES,
/*! Give user a nickname or change the existing one */
NICK,
/*! Similar to PRIVMSG but without automatic replies
* \sa PRIVMSG */
NOTICE,
/*! Obtain operator privileges */
OPER,
/*! User sending the message is removed from the list of active members */
PART,
/*! Set connection password */
PASS,
/*! Test the presence of an active client or server at the other end of the connection
* \sa PING */
PING,
/*! Reply to ping message
* \sa PONG */
PONG,
/*! Send private messages between users or channels
* \sa NOTICE */
PRIVMSG,
// TODO: Document the lines below
QUIT,
REHASH,
RESTART,
@ -68,21 +106,36 @@ enum commands {
WHOIS,
WHOWAS,
#ifdef UIRC_IRCV3
ACC, /* https://github.com/ircv3/ircv3-specifications/pull/276 */
ACCOUNT, /* https://ircv3.net/specs/extensions/account-notify-3.1 */
ACK, /* https://ircv3.net/specs/extensions/labeled-response */
AUTHENTICATE, /* https://ircv3.net/specs/extensions/sasl-3.1 */
BATCH, /* https://ircv3.net/specs/extensions/batch-3.2 */
CAP, /* https://ircv3.net/specs/core/capability-negotiation */
CHGHOST, /* https://ircv3.net/specs/extensions/chghost-3.2 */
FAIL, /* https://ircv3.net/specs/extensions/standard-replies */
MONITOR, /* https://ircv3.net/specs/core/monitor-3.2 */
NOTE, /* https://ircv3.net/specs/extensions/standard-replies */
RENAME, /* https://github.com/ircv3/ircv3-specifications/pull/420 */
RESUME, /* https://github.com/ircv3/ircv3-specifications/pull/306 */
SETNAME, /* https://ircv3.net/specs/extensions/setname */
WARN, /* https://ircv3.net/specs/extensions/standard-replies */
WEBIRC, /* https://ircv3.net/specs/extensions/webirc */
/*! \sa https://github.com/ircv3/ircv3-specifications/pull/276 */
ACC,
/*! \sa https://ircv3.net/specs/extensions/account-notify-3.1 */
ACCOUNT,
/*! \sa https://ircv3.net/specs/extensions/labeled-response */
ACK,
/*! \sa https://ircv3.net/specs/extensions/sasl-3.1 */
AUTHENTICATE,
/*! \sa https://ircv3.net/specs/extensions/batch-3.2 */
BATCH,
/*! \sa https://ircv3.net/specs/core/capability-negotiation */
CAP,
/*! \sa https://ircv3.net/specs/extensions/chghost-3.2 */
CHGHOST,
/*! \sa https://ircv3.net/specs/extensions/standard-replies */
FAIL,
/*! \sa https://ircv3.net/specs/core/monitor-3.2 */
MONITOR,
/*! \sa https://ircv3.net/specs/extensions/standard-replies */
NOTE,
/*! \sa https://github.com/ircv3/ircv3-specifications/pull/420 */
RENAME,
/*! \sa https://github.com/ircv3/ircv3-specifications/pull/306 */
RESUME,
/*! \sa https://ircv3.net/specs/extensions/setname */
SETNAME,
/*! \sa https://ircv3.net/specs/extensions/standard-replies */
WARN,
/*! \sa https://ircv3.net/specs/extensions/webirc */
WEBIRC,
#define UIRC_LCMD WEBIRC
#else /* UIRC_IRCV3 */
#define UIRC_LCMD WHOWAS

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#ifndef UIRC_GUARD_CONVERTERS
#define UIRC_GUARD_CONVERTERS

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#ifndef UIRC_GUARD_ERRORS
#define UIRC_GUARD_ERRORS

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#ifndef UIRC_GUARD_MODES
#define UIRC_GUARD_MODES

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#ifndef UIRC_GUARD_REPLIES
#define UIRC_GUARD_REPLIES

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#include <sys/types.h>
#ifndef UIRC_GUARD_TAGS

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#include "types.h"
#include <stdbool.h>
@ -39,9 +41,9 @@ signed int Tok_tags(char* str, IRC_Tags* out);
* \brief Tokenize a IRC message source.
*
* This function takes the source part of a message, pointing struct elements to parts of it.
* \param[in] str String containing a IRC source with or without the ':' prefix
* \param[in] str String containing a IRC source with or without the ':' prefix
* \param[out] out Allocated IRC_User structure
* \param[in] useorig If '\%orig' should be considered in the parsing
* \param[in] useorig If '\%orig' should be considered in the parsing
*/
signed int Tok_user(char* str, IRC_User* out, bool useorig);
@ -49,7 +51,7 @@ signed int Tok_user(char* str, IRC_User* out, bool useorig);
* \brief Tokenize a IRC message string.
*
* This function takes a IRC Message and attempts to tokenize/parse it, pointing every element found to it's respective struct element
* \param[in] str String containing a IRC message without the ending '\\r\\n'
* \param[in] str String containing a IRC message without the ending '\\r\\n'
* \param[out] out Allocated IRC_Message structure
*/
signed int Tok_mesg(char* str, IRC_Message* out);
@ -59,7 +61,7 @@ signed int Tok_mesg(char* str, IRC_Message* out);
* \brief A PING tokenizer/parser
*
* This function is a simple helper to get the source and target of a PING since the RFC has a "interesting" implementation
* \param[in] mesg IRC_Message struct containing the PING message
* \param[in] mesg IRC_Message struct containing the PING message
* \param[out] source Source of the PING (server)
* \param[out] target Target of the PING (server or client)
*/
@ -68,7 +70,7 @@ void Tok_cmd_PING(const IRC_Message* mesg, char** source, char** target);
* \brief Tokenizer for cases where the first argument is optional
*
* This function is a private helper for cases where the first argument might be missing but the second isn't
* \param[in] mesg IRC_Message struct
* \param[in] mesg IRC_Message struct
* \param[out] optarg Optional argument if found or NULL
* \param[out] target Required argument
*/

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#include <stdbool.h>
#ifndef UIRC_GUARD_TYPES

View File

@ -16,6 +16,8 @@
* along with uIRC. If not, see <https://www.gnu.org/licenses/>.
*/
/*! \file */
#include "types.h"
#include <sys/types.h>

View File

@ -81,7 +81,7 @@ Tok_user(char* str, IRC_User* out, bool useorig)
if (useorig && (out->orig = strchr(pos, '%')) != NULL) *(out->orig++) = '\0';
if ((out->user = strchr(pos, '!'))
!= NULL) /* RFC2812 says this cannot be here without the host but RFC1459 says it can, we accept both options */
*((char*) out->user++) = '\0';
*(out->user++) = '\0';
if (!*(out->nick = pos)) return ERR_UIRC_INVALID_FORMAT;
/* NOTE: De-facto standard below
* This assumes that every prefix without a '@host' and '!user' is itself a host prefix only