/*
 * ----------------------------------------------------------------
 * Night Light Internet Relay Chat Functions
 * ----------------------------------------------------------------
 * Copyright (C) 1997-2003 Jonas Kvinge <jonas@night-light.net>
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Last modified by:
 * Jonas Kvinge (03.08.2002)
 *
 */

#define IRCCALLS_C

#define NEED_SYS_TYPES_H 1		/* Extra types */
#define NEED_SYS_PARAM_H 1		/* Some systems need this */
#define NEED_LIMITS_H 0			/* Kernel limits */
#define NEED_STDARG_H 1			/* va_list, etc */
#define NEED_ERRNO_H 1			/* errno */
#define NEED_CTYPE_H 1			/* isdigit(), etc */
#define NEED_NETINET_IN_H 0		/* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 0		/* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1			/* Standard C UNIX functions */
#define NEED_STDLIB_H 1			/* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1			/* time(), etc */
#define NEED_SYSCTL_H 0			/* sysctl(), etc */
#define NEED_SYS_STAT_H 0		/* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0		/* iovec, etc */
#define NEED_FCNTL_H 1			/* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 0		/* ioctl(), etc */
#define NEED_SYS_FILIO_H 0		/* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1			/* Unix standard functions */
#define NEED_STRING_H 1			/* C string functions */
#define NEED_SIGNAL_H 0			/* Signal functions */
#define NEED_SYS_SOCKET_H 0		/* Socket functions */
#define NEED_NETDB_H 0			/* Network database functions */
#define NEED_ARPA_NAMESER_H 0		/* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 0 	/* Functions to retrive system passwords */

#include "includes.h"

#include "irc.h"

/* VARIABLES - JONAS (28.08.2000) */

const char IRC_C_VERSION[] = "0.2.1d";

const char *IRC_StrEvent[] = {
  "Unknown",
  "Message",
  "Action",
  "CTCP",
  "Notice",
  "Nick",
  "Quit",
  "Mode",
  "Invite",
  "Join",
  "Part",
  "Kick",
  "Topic",
  "Kill",
  "Wallops",
};

char *IRCNUH = NULL;
char *IRCNICK = NULL;

/* IRC_ISVALIDEVENTS - JONAS (28.08.2000) */

unsigned short int irc_isvalidevents(const char *const StringPT) {

  unsigned short int Len1 = 0;
  unsigned short int Len2 = 0;
  unsigned short int Index1 = 0;
  unsigned short int Index2 = 0;
  unsigned short int Found = 0;

  Len1 = strlen(StringPT);
  Len2 = strlen(IRCEVENTS);
  for (Index1 = 0 ; Index1 < Len1 ; Index1++) {
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len2 ; Index2++) {
      if (StringPT[Index1] == IRCEVENTS[Index2]) {
        Found = TRUE;
        break;
      }
    }
    if (Found == FALSE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCUNKNOWNEVENT, StringPT[Index1]);
      return(FALSE);
    }
  }
  for (Index1 = 0 ; Index1 < Len1 ; Index1++) {
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len1 ; Index2++) {
      if (Index1 == Index2) { continue; }
      if (StringPT[Index1] == StringPT[Index2]) {
        Found = TRUE;
        break;
      }
    }
    if (Found == TRUE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCEVENTTWOTIMESINSTRING, StringPT[Index1]);
      return(FALSE);
    }
  }

  return(TRUE);

}

/* IRC_ISVALIDNICK - JONAS (28.08.2000) */

unsigned short int irc_isvalidnick(const char *const StringPT) {

  unsigned short int Index = 0;
  int Temp = StringPT[0];

  assert(StringPT != NULL);

  if ((isdigit(Temp) != FALSE) || (Temp == '-')) {
    snprintf(StrResult, LINELEN+1, IRC_IRCNICKINVALIDSTARTCHAR, StringPT[0]);
    return(FALSE);
  }

  Index = strspn(StringPT, IRCNICKCHARS);
  if (Index < strlen(StringPT)) {
    snprintf(StrResult, LINELEN+1, IRC_IRCNICKINVALIDCHAR, StringPT[Index]);
    return(FALSE);
  }
  if (strlen(StringPT) > IRCNICKLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCNICKMAXCHARS, IRCNICKLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDUSER - JONAS (28.08.2000) */

unsigned short int irc_isvaliduser(const char *const StringPT) {

  unsigned short int Index = 0;

  assert(StringPT != NULL);

  Index = strspn(StringPT, IRCUSERCHARS);
  if (Index < strlen(StringPT)) {
    snprintf(StrResult, LINELEN+1, IRC_IRCUSERINVALIDCHAR, StringPT[Index]);
    return(FALSE);
  }
  if (strlen(StringPT) > IRCUSERLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCUSERMAXCHARS, IRCUSERLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDHOST - JONAS (28.08.2000) */

unsigned short int irc_isvalidhost(const char *const StringPT) {

  unsigned short int Index = 0;

  assert(StringPT != NULL);

  Index = strspn(StringPT, IRCHOSTCHARS);
  if (Index < strlen(StringPT)) {
    snprintf(StrResult, LINELEN+1, IRC_IRCHOSTINVALIDCHAR, StringPT[Index]);
    return(FALSE);
  }
  if (strlen(StringPT) > IRCHOSTLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCHOSTMAXCHARS, IRCHOSTLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDNUH - JONAS (28.08.2000) */

unsigned short int irc_isvalidnuh(const char *const StringPT) {

  unsigned short int Index = 0;

  assert(StringPT != NULL);

  Index = strspn(StringPT, IRCNUHCHARS);
  if (Index < strlen(StringPT)) {
    snprintf(StrResult, LINELEN+1, IRC_IRCNUHINVALIDCHAR, StringPT[Index]);
    return(FALSE);
  }
  if (strlen(StringPT) > IRCNUHLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCNUHMAXCHARS, IRCNUHLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDSERVER- JONAS (28.08.2000) */

unsigned short int irc_isvalidserver(const char *const StringPT) {

  unsigned short int Index = 0;

  assert(StringPT != NULL);

  Index = strspn(StringPT, IRCSERVERCHARS);
  if (Index < strlen(StringPT)) {
    snprintf(StrResult, LINELEN+1, IRC_IRCSERVERINVALIDCHAR, StringPT[Index]);
    return(FALSE);
  }
  if (strlen(StringPT) > IRCSERVERLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCSERVERMAXCHARS, IRCSERVERLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDPASS - JONAS (28.08.2000) */

unsigned short int irc_isvalidpass(const char *const StringPT) {

  unsigned short int Index = 0;

  assert(StringPT != NULL);

  Index = strspn(StringPT, IRCPASSCHARS);
  if (Index < strlen(StringPT)) {
    snprintf(StrResult, LINELEN+1, IRC_IRCPASSINVALIDCHAR, StringPT[Index]);
    return(FALSE);
  }
  if (strlen(StringPT) > IRCPASSLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCPASSMAXCHARS, IRCPASSLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDTARGET - JONAS (28.08.2000) */

unsigned short int irc_isvalidtarget(const char *const StringPT) {

  char *TempPT = NULL;

  TempPT = strchr(StringPT, ':');
  if (TempPT != NULL) {
    snprintf(StrResult, LINELEN+1, IRC_IRCTARGETINVALIDCHAR, *TempPT);
    return(FALSE);
  }
  TempPT = strchr(StringPT, ' ');
  if (TempPT != NULL) {
    snprintf(StrResult, LINELEN+1, IRC_IRCTARGETINVALIDCHAR, *TempPT);
    return(FALSE);
  }

  if (strlen(StringPT) > IRCCHANLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCTARGETMAXCHARS, IRCCHANLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDCHAN - JONAS (28.08.2000) */

unsigned short int irc_isvalidchan(const char *const StringPT) {

  char *TempPT = NULL;

  TempPT = strchr(StringPT, ':');
  if (TempPT != NULL) {
    snprintf(StrResult, LINELEN+1, IRC_IRCCHANINVALIDCHAR, *TempPT);
    return(FALSE);
  }
  TempPT = strchr(StringPT, ' ');
  if (TempPT != NULL) {
    snprintf(StrResult, LINELEN+1, IRC_IRCCHANINVALIDCHAR, *TempPT);
    return(FALSE);
  }

  if ((StringPT[0] != '*') && (StringPT[0] != '&') && (StringPT[0] != '#') && (StringPT[0] != '+') && (StringPT[0] != '!')) {
    snprintf(StrResult, LINELEN+1, IRC_IRCCHANINVALIDSTARTCHAR, StringPT[0]);
    return(FALSE);
  }

  if (strlen(StringPT) > IRCCHANLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCCHANMAXCHARS, IRCCHANLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDCHANTOPIC - JONAS (28.08.2000) */

unsigned short int irc_isvalidchantopic(const char * const StringPT) {

  if (strlen(StringPT) > IRCCHANTOPICLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCCHANTOPICMAXCHARS, IRCCHANTOPICLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDCHANKEY - JONAS (28.08.2000) */

unsigned short int irc_isvalidchankey(const char * const StringPT) {

  if (strlen(StringPT) > IRCCHANKEYLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCCHANKEYMAXCHARS, IRCCHANKEYLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_ISVALIDUSERMODES - JONAS (28.08.2000) */

unsigned short int irc_isvalidusermodes(const char * const StringPT) {

  unsigned short int Len1 = 0;
  unsigned short int Len2 = 0;
  unsigned short int Index1 = 0;
  unsigned short int Index2 = 0;
  unsigned short int Found = 0;

  Len1 = strlen(StringPT);
  Len2 = strlen(IRCUSERMODES);

  for (Index1 = 0 ; Index1 < Len1 ; Index1++) {
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len2 ; Index2++) {
      if (StringPT[Index1] == IRCUSERMODES[Index2]) { Found = TRUE; break; }
    }
    if (Found == FALSE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCUNKNOWNUSERMODEFLAG, StringPT[Index1]);
      return(FALSE);
    }
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len1 ; Index2++) {
      if (Index1 == Index2) { continue; }
      if (StringPT[Index1] == StringPT[Index2]) { Found = TRUE; break; }
    }
    if (Found == TRUE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCUSERMODESTWOTIMESINSTRING, StringPT[Index1]);
      return(FALSE);
    }
  }

  return(TRUE);

}

/* IRC_ISVALIDCHANMODES - JONAS (28.08.2000) */

unsigned short int irc_isvalidchanmodes(const char * const StringPT) {

  unsigned short int Len1 = 0;
  unsigned short int Len2 = 0;
  unsigned short int Index1 = 0;
  unsigned short int Index2 = 0;
  unsigned short int Found = 0;

  Len1 = strlen(StringPT);
  Len2 = strlen(IRCUSERMODES);

  for (Index1 = 0 ; Index1 < Len1 ; Index1++) {
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len2 ; Index2++) {
      if (StringPT[Index1] == IRCCHANMODES[Index2]) { Found = TRUE; break; }
    }
    if (Found == FALSE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCUNKNOWNCHANMODEFLAG, StringPT[Index1]);
      return(FALSE);
    }
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len1 ; Index2++) {
      if (Index1 == Index2) { continue; }
      if (StringPT[Index1] == StringPT[Index2]) { Found = TRUE; break; }
    }
    if (Found == TRUE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCCHANMODESTWOTIMESINSTRING, StringPT[Index1]);
      return(FALSE);
    }
  }

  return(TRUE);

}

/* IRC_ISVALIDCHANEVENTS - JONAS (28.08.2000) */

unsigned short int irc_isvalidchanevents(const char * const StringPT) {

  unsigned short int Len1 = 0;
  unsigned short int Len2 = 0;
  unsigned short int Index1 = 0;
  unsigned short int Index2 = 0;
  unsigned short int Found = 0;

  Len1 = strlen(StringPT);
  Len2 = strlen(IRCCHANEVENTS);
  for (Index1 = 0 ; Index1 < Len1 ; Index1++) {
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len2 ; Index2++) {
      if (StringPT[Index1] == IRCCHANEVENTS[Index2]) {
        Found = TRUE;
        break;
      }
    }
    if (Found == FALSE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCUNKNOWNCHANEVENT, StringPT[Index1]);
      return(FALSE);
    }
  }
  for (Index1 = 0 ; Index1 < Len1 ; Index1++) {
    Found = FALSE;
    for (Index2 = 0 ; Index2 < Len1 ; Index2++) {
      if (Index1 == Index2) { continue; }
      if (StringPT[Index1] == StringPT[Index2]) {
        Found = TRUE;
        break;
      }
    }
    if (Found == TRUE) {
      snprintf(StrResult, LINELEN+1, IRC_IRCCHANEVENTTWOTIMESINSTRING, StringPT[Index1]);
      return(FALSE);
    }
  }

  return(TRUE);

}

/* IRC_ISVALIDMSG - JONAS (28.08.2000) */

unsigned short int irc_isvalidmsg(const char *const StringPT) {

  if (strlen(StringPT) > IRCMSGLEN) {
    snprintf(StrResult, LINELEN+1, IRC_IRCMSGMAXCHARS, IRCMSGLEN);
    return(FALSE);
  }

  return(TRUE);

}

/* IRC_STREVENT - JONAS (28.08.2000) */

const char *irc_strevent(const char Event) {

  unsigned short int Index = 0;

  switch (Event) {
    case IRC_EVENT_PRIVMSG:
      Index = 1;
      break;
    case IRC_EVENT_ACTION:
      Index = 2;
      break;
    case IRC_EVENT_CTCP:
      Index = 3;
      break;
    case IRC_EVENT_NOTICE:
      Index = 4;
      break;
    case IRC_EVENT_NICK:
      Index = 5;
      break;
    case IRC_EVENT_QUIT:
      Index = 6;
      break;
    case IRC_EVENT_MODE:
      Index = 7;
      break;
    case IRC_EVENT_INVITE:
      Index = 8;
      break;
    case IRC_EVENT_JOIN:
      Index = 9;
      break;
    case IRC_EVENT_PART:
      Index = 10;
      break;
    case IRC_EVENT_KICK:
      Index = 11;
      break;
    case IRC_EVENT_TOPIC:
      Index = 12;
      break;
    case IRC_EVENT_KILL:
      Index = 13;
      break;
    case IRC_EVENT_WALLOPS:
      Index = 14;
      break;
    default:
      Index = 0;
      break;
  }

  assert((Index < (sizeof(IRC_StrEvent) / sizeof(*IRC_StrEvent))));

  return(IRC_StrEvent[Index]);

}

/* IRC_NUHMASK - JONAS (28.08.2000) */

char *irc_nuhmask(const char *NickPT, const char *UserPT, const char *HostPT, const unsigned short int NickMask, const unsigned short int UserMask, const unsigned short int HostMask) {

  char P_Nick[IRCNICKLEN+1] = "";
  char T_Nick[IRCNICKLEN+1] = "";
  char P_User[IRCUSERLEN+1] = "";
  char T_User[IRCUSERLEN+1] = "";
  char P_Host[IRCHOSTLEN+1] = "";

  char *P_NickPT = P_Nick;
  char *P_UserPT = P_User;
  char *P_HostPT = P_Host;

  char *TempPT = NULL;
  char *Temp1PT = NULL;
  char *Temp2PT = NULL;

  unsigned short int Count = 0;
  unsigned short int Number = 0;
  unsigned short int Len = 0;

  assert(NickPT != NULL);
  assert(UserPT != NULL);
  assert(HostPT != NULL);

  switch (NickMask) {
    case 1: /* "nick" */
      if (strlen(NickPT) <= IRCNICKLEN) {
        strncpy(P_Nick, NickPT, IRCNICKLEN);
        break;
      }
    case 2: /* "*nick" */
      Len = strlen(NickPT);
      if (Len >= 1) {
        strncpy(P_Nick, "*", IRCNICKLEN);
        while (Len >= IRCNICKLEN) { NickPT++; Len--; }
        strncat(P_Nick, NickPT, IRCNICKLEN - strlen(P_Nick));
        break;
      }
      strncpy(P_Nick, NickPT, IRCNICKLEN);
      break;
    case 3: /* "nick*" */
      strncpy(P_Nick, NickPT, IRCNICKLEN);
      Len = strlen(P_Nick);
      if (Len >= 1) {
        Temp1PT = P_Nick + IRCNICKLEN;
        Temp2PT = P_Nick + Len;
        for (; Temp2PT >= Temp1PT ; Temp2PT--) { *Temp2PT = 0; }
        *Temp2PT = '*';
        Temp2PT++;
        *Temp2PT = 0;
      }
      break;
    case 4: /* "*nick*" */
    case 5: /* "*nick*" */
      strncpy(T_Nick, NickPT, IRCNICKLEN);
      Len = strlen(T_Nick);
      if (Len >= 1) {
        Temp1PT = T_Nick;
        Temp2PT = T_Nick + Len - 1;
        Number = 1;
        for (; Len > IRCNICKLEN-2 ; Len--) {
          if (
              (*Temp1PT == '_')
              ||
              (*Temp1PT == '`')
              ||
              (*Temp1PT == '|')
              ||
              (*Temp1PT == 92)
              ||
              (*Temp1PT == '^')
              ||
              (*Temp1PT == '[')
              ||
              (*Temp1PT == ']')
              ||
              (*Temp1PT == '{')
              ||
              (*Temp1PT == '}')
              )
          {
            *Temp1PT = 0;
            Temp1PT++;
            continue;
          }
          if (
              (*Temp2PT == '_')
              ||
              (*Temp2PT == '`')
              ||
              (*Temp2PT == '|')
              ||
              (*Temp2PT == 92)
              ||
              (*Temp2PT == '^')
              ||
              (*Temp2PT == '[')
              ||
              (*Temp2PT == ']')
              ||
              (*Temp2PT == '{')
              ||
              (*Temp2PT == '}')
              ||
              (*Temp2PT == '-')
              ||
              ((*Temp2PT >= 49) && (*Temp2PT <= 57))
              )
          {
            *Temp2PT = 0;
            Temp2PT--;
            continue;
          }
          if (Number == 2) { Number = 1; *Temp1PT = 0; Temp1PT++; continue; }
          if (Number == 1) { Number = 2; *Temp2PT = 0; Temp2PT--; continue; }
        }
        strncpy(P_Nick, "*", IRCNICKLEN);
        strncat(P_Nick, Temp1PT, IRCNICKLEN - strlen(P_Nick));
        strncat(P_Nick, "*", IRCNICKLEN - strlen(P_Nick));
        break;
      }
      strncpy(P_Nick, NickPT, IRCNICKLEN);
      break;
    case 6: /* "*" */
      strncpy(P_Nick, "*", IRCNICKLEN);
      break;
    default: /* "nick" */
      strncpy(P_Nick, NickPT, IRCNICKLEN);
      break;
  }

  switch (UserMask) {
    case 1: /* "user" */
      if (strlen(UserPT) <= IRCUSERLEN) {
        strncpy(P_User, UserPT, IRCUSERLEN);
        break;
      }
    case 2: /* "*user" */
      Len = strlen(UserPT);
      if (Len >= 3) {
        strncpy(P_User, "*", IRCUSERLEN);
        if (*UserPT == '~') { UserPT++; Len--; }
        while (Len >= IRCUSERLEN) { UserPT++; Len--; }
        strncat(P_User, UserPT, IRCUSERLEN - strlen(P_User));
        break;
      }
      strncpy(P_User, UserPT, IRCUSERLEN);
      break;
    case 3: /* "user*" */
      strncpy(P_User, UserPT, IRCUSERLEN);
      Len = strlen(P_User);
      if (Len >= 3) {
        Temp1PT = P_User + IRCUSERLEN;
        Temp2PT = P_User + Len;
        for (; Temp2PT >= Temp1PT ; Temp2PT--) { *Temp2PT = 0; }
        *Temp2PT = '*';
        Temp2PT++;
        *Temp2PT = 0;
      }
      break;
     case 4: /* "*user*" */
     case 5: /* "*user*" */
      strncpy(T_User, UserPT, IRCUSERLEN);
      Len = strlen(T_User);
      if (Len >= 3) {
        Temp1PT = T_User;
        Temp2PT = T_User + Len - 1;
        if (*Temp1PT == '~') {
          *Temp1PT = 0;
          Temp1PT++;
          Len--;
        }
        Number = 1;
        for (; Len > IRCUSERLEN-2 ; Len--) {
          if (Number == 2) { Number = 1; *Temp1PT = 0; Temp1PT++; continue; }
          if (Number == 1) { Number = 2; *Temp2PT = 0; Temp2PT--; continue; }
        }
        strncpy(P_User, "*", IRCUSERLEN);
        strncat(P_User, Temp1PT, IRCUSERLEN - strlen(P_User));
        strncat(P_User, "*", IRCUSERLEN - strlen(P_User));
        break;
      }
      strncpy(P_User, UserPT, IRCUSERLEN);
      break;
    case 6:  /* "*" */
      strncpy(P_User, "*", IRCUSERLEN);
      break;
    default:
      strncpy(P_User, UserPT, IRCUSERLEN);
      break;
  }

  if (strip(HostPT) == TRUE) {
    switch (HostMask) {
      case 1: /* "195.159.32.54" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        break;
      case 2: /* "195.159.32.*" */
      case 3: /* "195.159.32.*" */
      case 4: /* "195.159.32.*" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        Len = strlen(P_Host);
        Temp1PT = P_Host;
        Temp2PT = P_Host + Len - 1;
        TempPT = strrchr(P_Host, '.');
        if (TempPT <= Temp1PT) { break; }
        if (TempPT >= Temp2PT) { break; }
        TempPT++;
        if (TempPT >= Temp2PT) { break; }
        *TempPT = '*';
        for (TempPT++ ; TempPT <= Temp2PT ; TempPT++) { *TempPT = 0; }
        break;
      case 5: /* "195.159.*" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        Len = strlen(P_Host);
        Temp1PT = P_Host;
        Temp2PT = P_Host + Len - 1;
        TempPT = Temp1PT;
        TempPT = strchr(TempPT, '.');
        if (TempPT <= Temp1PT) { break; }
        if (TempPT >= Temp2PT) { break; }
        TempPT++;
        if (TempPT >= Temp2PT) { break; }
        TempPT = strchr(TempPT, '.');
        if (TempPT >= Temp2PT) { break; }
        TempPT++;
        if (TempPT >= Temp2PT) { break; }
        *TempPT = '*';
        for (TempPT++ ; TempPT <= Temp2PT ; TempPT++) { *TempPT = 0; }
        break;
      case 6: /* "*" */
        strncpy(P_Host, "*", IRCHOSTLEN);
        break;
      default:
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        break;
    }
  }
  else {
    switch (HostMask) {
      case 1: /* d.c.b.a.night-light.net */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        break;
      case 2: /* "*.c.b.a.night-light.net" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        Len = strlen(P_Host);
        Number = strspn(P_Host, ".");
        if (Number <= 1) { break; }
        P_HostPT = P_Host;
        TempPT = P_Host + Len;
        for (; P_HostPT <= TempPT ; P_HostPT++) {
          if (*P_HostPT == '.') {
            P_HostPT--;
            *P_HostPT = '*';
            break;
          }
          *P_HostPT = 0;
        }
        break;
      case 3: /* "*.a.night-light.net" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        Len = strlen(P_Host);
        Count = 0;
        Number = strspn(P_Host, ".");
        if (Number <= 1) { break; }
        if (Number <= 3) { Number = 1; }
        else { Number -= 2; }
        TempPT = P_Host + Len;
        P_HostPT = P_Host;
        for (; P_HostPT <= TempPT ; P_HostPT++) {
          if (*P_HostPT == '.') {
            Count++;
            if (Count >= Number) {
              P_HostPT--;
              *P_HostPT = '*';
              break;
            }
          }
          *P_HostPT = 0;
        }
        break;
      case 4: /* "*.night-light.net" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        Len = strlen(P_Host);
        Count = 0;
        Number = strspn(P_Host, ".");
        if (Number < 2) { break; }
        if (Number == 2) { Number = 1; }
        else { Number--; }
        TempPT = P_Host + Len;
        P_HostPT = P_Host;
        for (; P_HostPT <= TempPT ; P_HostPT++) {
          if (*P_HostPT == '.') {
            Count++;
            if (Count >= Number) {
              P_HostPT--;
              *P_HostPT = '*';
              break;
            }
          }
          *P_HostPT = 0;
        }
        break;
      case 5: /* "*.net" */
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        Len = strlen(P_Host);
        Count = 0;
        Number = strspn(P_Host, ".");
        if (Number < 1) { break; }
        TempPT = P_Host + Len;
        P_HostPT = P_Host;
        for (; P_HostPT <= TempPT ; P_HostPT++) {
          if (*P_HostPT == '.') {
            Count++;
            if (Count >= Number) {
              P_HostPT--;
              *P_HostPT = '*';
              break;
            }
          }
          *P_HostPT = 0;
        }
        break;
      case 6: /* "*" */
        strncpy(P_Host, "*", IRCHOSTLEN);
        break;
      default:
        strncpy(P_Host, HostPT, IRCHOSTLEN);
        break;
    }
  }

  Len = (3 + strlen(P_NickPT) + strlen(P_UserPT) + strlen(P_HostPT));
  TempPT = realloc(IRCNUH, Len);
  if (TempPT == NULL) {
    FREE(IRCNUH);
    return(NULL);
  }
  IRCNUH = TempPT;
  sprintf(IRCNUH, "%s!%s@%s", P_NickPT, P_UserPT, P_HostPT);

  return(IRCNUH);

}

/* IRC_FIXNUH - JONAS (01.09.2001) */

char *irc_fixnuh(char *NUHPT) {

  char *TempPT = NULL;
  char *NickPT = NULL;
  char *UserPT = NULL;
  char *HostPT = NULL;
  unsigned short int Len = 0;

  assert(NUHPT != NULL);

  TempPT = strchr(NUHPT, '!');
  if (TempPT == NULL) {
    TempPT = strrchr(NUHPT, '@');
    if (TempPT == NULL) {
      if (strchr(NUHPT, '.') == NULL) {
        NickPT = NUHPT;
        UserPT = "*";
        HostPT = "*";
      }
      else {
        NickPT = "*";
        UserPT = "*";
        HostPT = NUHPT;
      }
    }
    else {
      *TempPT = '\0';
      TempPT++;
      NickPT = "*";
      UserPT = NUHPT;
      HostPT = TempPT;
    }
  }
  else {
    *TempPT = '\0';
    TempPT++;
    NickPT = NUHPT;
    UserPT = TempPT;
    NUHPT = TempPT;
    TempPT = strrchr(NUHPT, '@');
    if (TempPT == NULL) {
      HostPT = "*";
    }
    else {
      *TempPT = '\0';
      TempPT++;
      HostPT = TempPT;
    }
  }

  if (*NickPT == '\0') { NickPT = "*"; }
  if (*UserPT == '\0') { UserPT = "*"; }
  if (*HostPT == '\0') { HostPT = "*"; }

#if 0
  if ((*NickPT == '*') && (*UserPT == '*') && (*HostPT == '*')) {
    *NickPT == "nick";
    *UserPT == "user";
    *HostPT == "host";
  }
#endif

  Len = (3 + strlen(NickPT) + strlen(UserPT) + strlen(HostPT));
  TempPT = realloc(IRCNUH, Len);
  if (TempPT == NULL) {
    FREE(IRCNUH);
    return(NULL);
  }
  IRCNUH = TempPT;
  sprintf(IRCNUH, "%s!%s@%s", NickPT, UserPT, HostPT);

  return(IRCNUH);

}

/* IRC_NUHMASKTEST - JONAS (28.08.2000) */

void irc_nuhmastest(void) {

  char Nick[] = "nickabcdefghijklm";
  char User[] = "userabcdefghijklm";

  /*char Host[] = "195.159.32.54";*/
  char Host[] = "jonas.night-light.net";
  char *NUHPT = NULL;
  unsigned short int Count = 0;

  for (Count = 1 ; Count <= 6 ; Count++) {
    NUHPT = irc_nuhmask(Nick, User, Host, Count, 1, 1);
    printf("NICKMASK %d; %s\n", Count, NUHPT);
  }

  printf("\n");

  for (Count = 1 ; Count <= 6 ; Count++) {
    NUHPT = irc_nuhmask(Nick, User, Host, 1, Count, 1);
    printf("USERMASK %d; %s\n", Count, NUHPT);
  }

  printf("\n");

  for (Count = 1 ; Count <= 6 ; Count++) {
    NUHPT = irc_nuhmask(Nick, User, Host, 1, 1, Count);
    printf("HOSTMASK %d; %s\n", Count, NUHPT);
  }
}

/* IRC_NEXTNICK - JONAS (28.08.2000) */

unsigned short int irc_nextnick(const char *const NickPT, unsigned short int NicksIndex, const unsigned short int MaxNickLen) {

  char *Nicks[] = {

    "_%s_",
    "^%s^",
    "`%s`",
    "[%s]",
    "{%s}",
    "\\%s\\",
    "]%s[",
    "}%s{",

    "%s_",
    "_%s",

    "%s`",
    "`%s",

    "%s\\",
    "\\%s",

    "%s^",
    "^%s",

    "%s1",
    "%s2",
    "%s3",
    "%s4",
    "%s5",
    "%s6",
    "%s7",
    "%s8",
    "%s9",
    "%s0",

    "%s[",
    "%s]",
    "%s{",
    "%s}",

    "[%s",
    "]%s",
    "{%s",
    "}%s",

    "%s01",
    "%s02",
    "%s03",
    "%s04",
    "%s05",
    "%s06",
    "%s07",
    "%s08",
    "%s09",
    "%s10",
    "%s11",
    "%s12",
    "%s13",
    "%s14",
    "%s15",
    "%s16",
    "%s17",
    "%s18",
    "%s19",
    "%s20",
    "%s21",
    "%s22",
    "%s23",
    "%s24",
    "%s25",
    "%s26",
    "%s27",
    "%s28",
    "%s29",
    "%s30"

  };
  unsigned short int NicksLen = (sizeof(Nicks) / sizeof(*Nicks));

  char OldNick[MaxNickLen+1];
  char NewNick[MaxNickLen+1];
  unsigned short int OldNickLen = 0;
  unsigned short int NewNickLen = 0;

  assert(NickPT != NULL);

  FREE(IRCNICK);

  strncpy(OldNick, NickPT, (MaxNickLen-1));
  OldNickLen = strlen(OldNick);

  for (; NicksIndex < NicksLen ; ++NicksIndex) {
    NewNickLen = (strlen(Nicks[NicksIndex]) + OldNickLen - 2);
    if (NewNickLen > MaxNickLen) { continue; }
    snprintf(NewNick, MaxNickLen+1, Nicks[NicksIndex], OldNick);
    IRCNICK = strrealloc(IRCNICK, NewNick);
    break;
  }

  if (IRCNICK == NULL) {
    char P_Nick[IRCNICKLEN+1] = "";
    strrnd(P_Nick, IRCNICKLEN);
    IRCNICK = strrealloc(IRCNICK, P_Nick);
    if (IRCNICK == NULL) { IRCNICK = ""; }
  }

  return(NicksIndex);

}

void irc_cleanup(void) {

  DEBUGPRINT(BITMASK_DEBUG_IRCCALLS, "Freeing %s allocated memory.", __FILE__);

  FREE(IRCNUH);
  FREE(IRCNICK);

}


syntax highlighted by Code2HTML, v. 0.9.1