1 /*
2  * nicks.c
3  *
4  * this file contains code to implement nick name related stuff.
5  *
6  * written by Joshua J. Drake
7  * copyright (c) 1998
8  */
9 
10 #include "irc.h"
11 #include "ircaux.h"
12 #include "nicks.h"
13 #include "dma.h"
14 #include "list.h"
15 #include "server.h"
16 #include "output.h"
17 #include "channels.h"
18 #include "numbers.h"
19 
20 /* islegal: true if c is a legal nickname char anywhere but first char */
21 #define islegal(c) ((((c) >= 'A') && ((c) <= '}')) || \
22                     (((c) >= '0') && ((c) <= '9')) || \
23                      ((c) == '-') || ((c) == '_'))
24 
25 
26 u_char *old_nick = UNULL;
27 
28 static	u_char	*randcrap _((int));
29 
30 /*
31  * checkNick()
32  * checks to see if a nick name is legal.  it will check the first character first.
33  * if it is legal we return from here to the first illegal character.  if the first
34  * character is invalid, we return NULL.
35  *
36  **** rewritten, with help from do_nick_name() from the server code (2.8.5),
37  **** phone, april 1993.
38  *
39  * moved to nicks.c 11/13/98
40  */
41 u_char *
check_nick(nick)42 check_nick(nick)
43    u_char *nick;
44 {
45    u_char *s;
46 
47    /* check the first character. */
48    if (!nick || *nick == '-' || isdigit(*nick))
49       return NULL;
50 
51    /* skip to the first illegal character. */
52    for (s = nick; *s; s++)
53       if (!islegal(*s) || isspace(*s))
54          break;
55    *s = '\0';
56 
57    /* if we have something, return it, otherwise forget it. */
58    return *nick ? nick : NULL;
59 }
60 
61 void
free_nick(nick)62 free_nick(nick)
63     Nick **nick;
64 {
65    Nick *tmp = *nick;
66 
67    dma_Free(&(tmp->nick));
68    dma_Free(&(tmp->user));
69    dma_Free(&(tmp->host));
70    dma_Free(&(tmp->realname));
71    dma_Free(&(tmp->server));
72    dma_Free(&tmp);
73 }
74 
75 /*
76  * find a nick on a channel on a server
77  *
78  * this will find a nick ptr via the channel or tmpchan variable..
79  * the tmpchan is preferred as it doesn't require lookup_channel..
80  *
81  */
82 Nick *
find_nick(u_char * nick,u_char * channel,int server,Channel * tmpchan)83 find_nick(u_char *nick, u_char *channel, int server, Channel *tmpchan)
84 {
85    Channel *chan;
86 
87    if (!nick || (!tmpchan && !channel) || server < 0 || server >= number_of_servers)
88      return NULL;
89 
90    /* tmpchan is preferred */
91    if (tmpchan)
92      {
93 	if (tmpchan->server != server)
94 	  {
95 	     put_error("findnick() received bad Channel pointer server!=%d", server);
96 	     return NULL;
97 	  }
98 	return (Nick *) find_in_list((List **)&tmpchan->nicks, nick, !USE_WILDCARDS);
99      }
100 
101    /* okay fine, we'll look it up */
102    chan = lookup_channel(channel, server, 0);
103    if (!chan) /* we're not on the channel! */
104      return NULL;
105 
106    /* return it! */
107    return (Nick *) find_in_list((List **)&chan->nicks, nick, !USE_WILDCARDS);
108 }
109 
110 
111 /*
112  * this will rotate your nickname characters and send it to the server
113  */
114 #define MAX_AUTO_NICK_ATTEMPTS 6
115 void
rotate_nick(nick)116 rotate_nick(nick)
117    u_char *nick;
118 {
119    static int rot_att_cnt = 1;	/* count of how many rotations attempts in a row we've done */
120    int nicklen = 0, i;
121 
122    if (!attempting_to_connect)
123      return;
124 
125    /* put_info("passed in: %s (%s #%u)", nick, old_nick, rot_att_cnt); */
126 
127    /* same as we just passed out? */
128    if (!my_stricmp(old_nick, nick))
129      {
130 	rot_att_cnt++;
131 	if (rot_att_cnt == (MAX_AUTO_NICK_ATTEMPTS - 1))
132 	  {
133 	     /* one last shot!  lets try random */
134 	     dma_strcpy(&old_nick, randcrap(12));
135 	     send_to_server("NICK %s", old_nick);
136 	     return;
137 	  }
138 	else if (rot_att_cnt >= MAX_AUTO_NICK_ATTEMPTS)
139 	  {
140 	     /* absolute last resort: manual intervention */
141 	     reset_nickname();
142 	     rot_att_cnt = 1;
143 	     return;
144 	  }
145      }
146    else		/* if we're not looping, reset the attempt counter */
147      rot_att_cnt = 1;
148 
149    /* rotate the nickname */
150    nicklen = my_strlen(nick);
151    dma_strcpy(&old_nick, nick);
152    if (!old_nick)
153      {
154 	reset_nickname(); /* bleh, must be out of memory */
155 	return;
156      }
157 
158    for (i = 0; i < nicklen-1; i++)
159      old_nick[i] = old_nick[i+1];
160    old_nick[nicklen-1] = *nick;
161    /* send it to the server */
162    /* put_info("sending to server: %s", old_nick); */
163    send_to_server("NICK %s", old_nick);
164 }
165 
166 
167 /*
168  * return len of random isalpha()s
169  */
170 static u_char *
randcrap(len)171 randcrap(len)
172    int len;
173 {
174    static u_char rstr[128];
175    u_char all[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]{}-_|^`";
176    int i, t;
177    long int r;
178    float alen = my_strlen(all);
179 
180    srandom(time(NULL)/rand());
181    r = random();
182 #ifndef _Windows
183    srand(r*getpid());
184 #endif
185 
186    for (i = 0; i < len && i < sizeof(rstr)-1; i++)
187      {
188        t = (int)(alen * rand() / (RAND_MAX+1.0));
189        // printf("RAND: %d %c\n", t, all[t]);
190        rstr[i] = all[t];
191      }
192    rstr[i] = '\0';
193    return rstr;
194 }
195 
196