/*
 * 4m v2.15 (ctcp.c)
 * (C) Copyright 1990 by Carrick Sean Casey
 * (C) Copyright 1993 by Scott Chasin and Michaeljon Miller
 *
 * 3-24-93 See file COPYING for copyright information.
 *
 * Client to client protocol
 */

#include "4m.h"
#include "externs.h"
#include "../h/version.h"
#include <ctype.h>
#include <pwd.h>

#ifdef HAS_STRINGS
# include <strings.h>
#endif

#include "ctcp.h"

#ifdef HAS_STRING
# include <string.h>
#endif

extern char *skipword();
extern void parse ();
void ctcp_xfer ();
void ctcp_finger ();
void ctcp_version ();
void ctcp_time ();
void ctcp_chat ();
extern char *strrchr ();
extern int close ();
extern void putl ();
extern int atoi ();
extern uid_t getuid ();
extern void sendpersonal ();
extern char *local_ampm ();
extern time_t time ();


extern char *get_tail ();


extern int ishushed ();
extern int xfer_lookup ();
extern void xfer_erase ();
extern int find_slot ();
extern int find_chatter ();

void do_ctcp(from, pkt)
     char *from;
     char *pkt;
{
    char c;

    parse(pkt);
    args++;
    c = *args;

    switch (c) {
        case CTCP_XFER:
            ctcp_xfer(from, skipword(args));
            break;

        case CTCP_FINGER:
            ctcp_finger(IN, from, skipword(args));
            break;

        case CTCP_FINGEROUT:
            ctcp_finger(OUT, from, skipword(args));
            break;

        case CTCP_VERSION:
            ctcp_version(IN, from, skipword(args));
            break;

        case CTCP_VERSIONOUT:
            ctcp_version(OUT, from, skipword(args));
            break;

        case CTCP_TIME:
            ctcp_time(IN, from, skipword(args));
            break;

        case CTCP_TIMEOUT:
            ctcp_time(OUT, from, skipword(args));
            break;

        case CTCP_CHATIN:
            ctcp_chat(IN, from, skipword(args));
            break;

        case CTCP_CHATOUT:
            ctcp_chat(OUT, from, skipword(args));
            break;

    }

    return;
}


void ctcp_xfer(from, pkt)
     char *from;
     char *pkt;
{
    int xindex;
    char *text, *filename;
    char *strtok();

    parse(pkt);
    text = args;

    if (ishushed(from))
        return;

    if (strcmp(words[0], "DELETE") == 0) {
        if ((filename = (char *) strrchr(words[1], '/')) != 0)
            filename++;
        else
            filename = words[1];

        xindex = xfer_lookup(from, filename, GET);

        if (xindex == -1)
            return;

        if (xfer_tab[xindex].status == ACTIVE) {
            close(xfer_tab[xindex].s);
            close(xfer_tab[xindex].fd);
        }
        sprintf(mbuf, "[Xfer] %s has canceled transfer request for \"%s\".",
                xfer_tab[xindex].who, xfer_tab[xindex].filename);
        putl(mbuf, PL_ALL);
        xfer_erase(xindex);
        return;
    }
    if ((filename = (char *) strrchr(words[0], '/')) != 0)
        filename++;
    else
        filename = words[0];

    xindex = xfer_lookup(from, filename, SEND);
    if (xindex == -1) {
        sprintf(filename, "%s.%d", filename, atoi(words[3]));
        xindex = xfer_lookup(from, filename, SEND);
    }
    strcpy(xfer_tab[xindex].filename, filename);

    xfer_tab[xindex].size = atoi(words[1]);
    xfer_tab[xindex].ip = (u_long) atoi(words[2]);
    xfer_tab[xindex].port = (u_short) atoi(words[3]);
    xfer_tab[xindex].type = GET;
    xfer_tab[xindex].status = WAIT;
    strcpy(xfer_tab[xindex].who, from);
    xfer_tab[xindex].fd = -1;
    xfer_tab[xindex].s = -1;

    sprintf(mbuf, "[Xfer] %s requests get for %s (%d bytes).",
            from, xfer_tab[xindex].filename, xfer_tab[xindex].size);
    putl(mbuf, PL_ALL);
    sprintf(mbuf, "[Xfer] Type \"/get %s %s\" to start the transfer.",
            xfer_tab[xindex].filename, from);
    putl(mbuf, PL_ALL);

    return;
}

void ctcp_finger(status, from, pkt)
     int status;
     char *from;
     char *pkt;
{

    struct passwd *pw;
    int uid;
    char *tmp;

    if (status == OUT) {
        parse(pkt);

        sprintf(mbuf, "[Finger] %s is %s@%s (%s).", from, words[0],
                words[1], get_tail(args));
        putl(mbuf, PL_ALL);
        return;
    }
    uid = getuid();
    if ((pw = getpwuid(uid)) != 0) {
        if ((tmp = (char *) index(pw->pw_gecos, ',')) != 0)
            *tmp = '\0';

        sprintf(mbuf, "%s \002%c %s %s %s", from, CTCP_FINGEROUT, pw->pw_name,
                localhost, pw->pw_gecos);
        sendpersonal(mbuf);
    }
    sprintf(mbuf, "[Ctcp] %s just fingered you.", from);
    putl(mbuf, PL_ALL);

    return;
}


void ctcp_version(status, from, pkt)
     int status;
     char *from;
     char *pkt;
{
    parse(pkt);

    if (status == OUT) {
        sprintf(mbuf, "[Version] %s is running client version %s.",
                from, words[0]);
        putl(mbuf, PL_ALL);
        return;
    }
    sprintf(mbuf, "%s \002%c %s", from, CTCP_VERSIONOUT, VERSION);
    sendpersonal(mbuf);

    return;
}

void ctcp_time(status, from, pkt)
     int status;
     char *from;
     char *pkt;
{
    if (status == OUT) {
        parse(pkt);
        sprintf(mbuf, "[Time] %s local time: %s", from, line);
        putl(mbuf, PL_ALL);
        return;
    }
    sprintf(mbuf, "%s \002%c %s", from, CTCP_TIMEOUT,
            local_ampm(time(NULL), 0));
    sendpersonal(mbuf);

    return;
}

void ctcp_chat(status, from, pkt)
     int status;
     char *from;
     char *pkt;
{
    char buf[100];
    int slot;
    char *text;

    parse(pkt);
    text = args;

 /* print the message */

    if (status == IN) {
        if (!strcmp(words[0], "ADD_SECURE")) {
            if ((slot = find_slot()) == -1) {
                sprintf(buf, "%s \002%c NOSPACE", from, CTCP_CHATIN);
                sendpersonal(buf);
                return;
            }
            slot = find_slot();

            strcpy(secure_tab[slot].who, from);
            secure_tab[slot].s = -1;
            secure_tab[slot].active = 1;
            secure_tab[slot].status = WAIT;
            secure_tab[slot].initiator = 0;
            secure_tab[slot].ip = (u_long) atoi(words[1]);
            secure_tab[slot].port = (u_short) atoi(words[2]);

            sprintf(buf, "[Chat] %s is requesting a secure link.", from);
            putl(buf, PL_SCR);
            sprintf(buf, "[Chat] Type \"/chat +%s\" to connect.", from);
            putl(buf, PL_SCR);
            return;
        }
        if (!strcmp(words[0], "DEL_SECURE")) {
            sprintf(buf, "[Chat] %s disconnected the link.", from);
            putl(buf, PL_SCR);
        }
        if (!strcmp(words[0], "NOSPACE")) {
            sprintf(buf, "[Chat] %s is unable to open a connection.", from);
            putl(buf, PL_SCR);
        }
        if (!strcmp(words[0], "ERROR")) {
            sprintf(buf, "[Chat] %s was unable to make a connection.", from);
            putl(buf, PL_SCR);
        }
        if (!strcmp(words[0], "REFUSED")) {
            sprintf(buf, "%s refused a secure chat", from);
            putl(buf, PL_SCR);
        }
        slot = find_chatter(from);
        memset(secure_tab[slot].who, 0, sizeof(secure_tab[slot].who));
        secure_tab[slot].active = 0;
        secure_tab[slot].initiator = 0;
        secure_tab[slot].s = -1;
    }
    return;
}
