[BACK]Return to irc-metadata.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

File: [local] / ircnowd / src / ngircd / irc-metadata.c (download)

Revision 1.1, Thu May 16 11:07:06 2024 UTC (4 months ago) by tomglok
Branch point for: MAIN

Initial revision

/*
 * ngIRCd -- The Next Generation IRC Daemon
 * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors.
 *
 * 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.
 * Please read the file COPYING, README and AUTHORS for more information.
 */

#define __irc_metadata_c__

#include "portab.h"

/**
 * @file
 * IRC metadata commands
 */

#include <assert.h>
#include <strings.h>
#include <stdio.h>

#include "conn-func.h"
#include "channel.h"
#include "irc-macros.h"
#include "irc-write.h"
#include "log.h"
#include "messages.h"
#include "parse.h"

#include "irc-metadata.h"

/**
 * Handler for the IRC+ "METADATA" command.
 *
 * @param Client The client from which this command has been received.
 * @param Req Request structure with prefix and all parameters.
 * @returns CONNECTED or DISCONNECTED.
 */
GLOBAL bool
IRC_METADATA(CLIENT *Client, REQUEST *Req)
{
	CLIENT *prefix, *target;
	char new_flags[COMMAND_LEN];

	assert(Client != NULL);
	assert(Req != NULL);

	_IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req)

	prefix = Client_Search(Req->prefix);
	if (!prefix)
		return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
					  Client_ID(Client), Req->prefix);

	target = Client_Search(Req->argv[0]);
	if (!target)
		return IRC_WriteErrClient(Client, ERR_NOSUCHNICK_MSG,
					  Client_ID(Client), Req->argv[0]);

	LogDebug("Got \"METADATA\" command from \"%s\" for client \"%s\": \"%s=%s\".",
		 Client_ID(prefix), Client_ID(target),
		 Req->argv[1], Req->argv[2]);

	/* Mark client: it has received a METADATA command */
	if (!Client_HasFlag(target, 'M')) {
		snprintf(new_flags, sizeof new_flags, "%sM",
			 Client_Flags(target));
		Client_SetFlags(target, new_flags);
	}

	if (strcasecmp(Req->argv[1], "cloakhost") == 0) {
		Client_UpdateCloakedHostname(target, prefix, Req->argv[2]);
		if (Client_Conn(target) > NONE && Client_HasMode(target, 'x'))
			IRC_WriteStrClientPrefix(target, prefix,
					RPL_HOSTHIDDEN_MSG, Client_ID(target),
					Client_HostnameDisplayed(target));
		/* The Client_UpdateCloakedHostname() function already
		 * forwarded the METADATA command, don't do it twice: */
		return CONNECTED;
	}
	else if (*Req->argv[2] && strcasecmp(Req->argv[1], "host") == 0) {
		Client_SetHostname(target, Req->argv[2]);
		if (Client_Conn(target) > NONE && !Client_HasMode(target, 'x'))
			IRC_WriteStrClientPrefix(target, prefix,
						 RPL_HOSTHIDDEN_MSG, Client_ID(target),
						 Client_HostnameDisplayed(target));
	} else if (strcasecmp(Req->argv[1], "info") == 0)
		Client_SetInfo(target, Req->argv[2]);
	else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0)
		Client_SetUser(target, Req->argv[2], true);
	else if (strcasecmp(Req->argv[1], "accountname") == 0)
		Client_SetAccountName(target, Req->argv[2]);
	else if (*Req->argv[2] && strcasecmp(Req->argv[1], "certfp") == 0)
		Conn_SetCertFp(Client_Conn(target), Req->argv[2]);
	else
		Log(LOG_WARNING,
		    "Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!",
		    Client_ID(Client), Client_ID(target),
		    Req->argv[1], Req->argv[2]);

	/* Forward the METADATA command to peers that support it: */
	IRC_WriteStrServersPrefixFlag(Client, prefix, 'M', "METADATA %s %s :%s",
				Client_ID(target), Req->argv[1], Req->argv[2]);
	return CONNECTED;
}