+ char *parameters;
+ char *command;
+ char *command_p[127];
+ char p[MAXBUF], temp[MAXBUF];
+ int j, items, cmd_found;
+ int total_params = 0;
+
+ for (int i = 0; i < 127; i++)
+ command_p[i] = NULL;
+
+ if (!user || !cmd || !*cmd)
+ {
+ return;
+ }
+
+ char* first_space = NULL;
+
+ /* If the command is > 2 characters (quick and dirty way to find out) */
+ if (*cmd && *(cmd+1) && *(cmd+2))
+ {
+ for (char* q = cmd; *q; q++)
+ {
+ if (*q == ' ')
+ {
+ first_space = q;
+ if (*(q+1) == ':')
+ {
+ total_params++;
+ // found a 'trailing', we dont count them after this.
+ break;
+ }
+ else
+ total_params++;
+ }
+ }
+ }
+
+ // another phidjit bug...
+ if (total_params > 126)
+ {
+ *first_space = 0;
+ WriteServ(user->fd,"421 %s %s :Too many parameters given",user->nick,cmd);
+ return;
+ }
+
+ strlcpy(temp,cmd,MAXBUF);
+
+ std::string tmp = cmd;
+
+ for (int i = 0; i <= MODCOUNT; i++)
+ {
+ std::string oldtmp = tmp;
+ modules[i]->OnServerRaw(tmp,true,user);
+ if (oldtmp != tmp)
+ {
+ log(DEBUG,"A Module changed the input string!");
+ log(DEBUG,"New string: %s",tmp.c_str());
+ log(DEBUG,"Old string: %s",oldtmp.c_str());
+ break;
+ }
+ }
+
+ strlcpy(cmd,tmp.c_str(),MAXBUF);
+ strlcpy(temp,cmd,MAXBUF);
+
+ char* has_space = strchr(cmd,' ');
+ int cm_length = 0;
+ if (!has_space)
+ {
+ /*
+ * no parameters, lets skip the formalities and not chop up
+ * the string
+ */
+ log(DEBUG,"About to preprocess command with no params");
+ items = 0;
+ command_p[0] = NULL;
+ parameters = NULL;
+ for (char* i = cmd; *i; i++,cm_length++)
+ *i = toupper(*i);
+ command = cmd;
+ }
+ else
+ {
+ *cmd = 0;
+ j = 0;
+
+ /* strip out extraneous linefeeds through mirc's crappy pasting (thanks Craig) */
+ for (char* i = temp; *i; i++)
+ {
+ if ((*i != 10) && (*i != 13) && (*i != 0) && (*i != 7))
+ {
+ cmd[j++] = *i;
+ }
+ }
+ cmd[j] = 0;
+
+ /* split the full string into a command plus parameters */
+ parameters = p;
+ p[0] = ' ';
+ p[1] = 0;
+
+ command = cmd;
+
+ if (has_space)
+ {
+ for (char* i = cmd; *i; i++)
+ {
+ /* capitalise the command ONLY, leave params intact */
+ *i = toupper(*i);
+ /* are we nearly there yet?! :P */
+ if (*i == ' ')
+ {
+ command = cmd;
+ parameters = i+1;
+ *i = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (char* i = cmd; *i; i++,cm_length++)
+ {
+ *i = toupper(*i);
+ }
+ }
+ }
+
+ if (cm_length > MAXCOMMAND)
+ {
+ WriteServ(user->fd,"421 %s %s :Command too long",user->nick,command);
+ return;
+ }
+
+ for (char* x = command; *x; x++)
+ {
+ if (((*x < 'A') || (*x > 'Z')) && (*x != '.'))
+ {
+ if (((*x < '0') || (*x> '9')) && (*x != '-'))
+ {
+ if (strchr("@!\"$%^&*(){}[]_=+;:'#~,<>/?\\|`",*x))
+ {
+ ServerInstance->stats->statsUnknown++;
+ WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
+ return;
+ }
+ }
+ }
+ }
+
+ std::string xcommand = command;
+ if ((user->registered != 7) && (xcommand == "SERVER"))
+ {
+ kill_link(user,"Server connection to non-server port");
+ return;
+ }
+
+ /* Tweak by brain - why was this INSIDE the mainloop? */
+ if (parameters)
+ {
+ if (parameters[0])
+ {
+ items = this->ProcessParameters(command_p,parameters);
+ }
+ else
+ {
+ items = 0;
+ command_p[0] = NULL;
+ }
+ }
+ else
+ {
+ items = 0;
+ command_p[0] = NULL;
+ }
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command,command_p,items,user,false));
+ if (MOD_RESULT == 1) {
+ return;
+ }
+
+ nspace::hash_map<std::string,command_t*>::iterator cm = cmdlist.find(xcommand);
+
+ if (cm != cmdlist.end())
+ {
+ if (user)
+ {
+ /* activity resets the ping pending timer */
+ user->nping = TIME + user->pingmax;
+ if ((items) < cm->second->min_params)
+ {
+ log(DEBUG,"not enough parameters: %s %s",user->nick,command);
+ WriteServ(user->fd,"461 %s %s :Not enough parameters",user->nick,command);
+ return;
+ }
+ if ((!strchr(user->modes,cm->second->flags_needed)) && (cm->second->flags_needed))
+ {
+ log(DEBUG,"permission denied: %s %s",user->nick,command);
+ WriteServ(user->fd,"481 %s :Permission Denied- You do not have the required operator privilages",user->nick);
+ cmd_found = 1;
+ return;
+ }
+ if ((cm->second->flags_needed) && (!user->HasPermission(xcommand)))
+ {
+ log(DEBUG,"permission denied: %s %s",user->nick,command);
+ WriteServ(user->fd,"481 %s :Permission Denied- Oper type %s does not have access to command %s",user->nick,user->oper,command);
+ if (!IS_LOCAL(user))
+ WriteOpers("*** \2WARNING\2: Command '%s' not allowed for oper '%s', dropped.",command,user->nick);
+ cmd_found = 1;
+ return;
+ }
+ /* if the command isnt USER, PASS, or NICK, and nick is empty,
+ * deny command! */
+ if ((cm->second != command_user) && (cm->second != command_nick) && (cm->second != command_pass))
+ {
+ if ((!isnick(user->nick)) || (user->registered != 7))
+ {
+ log(DEBUG,"not registered: %s %s",user->nick,command);
+ WriteServ(user->fd,"451 %s :You have not registered",command);
+ return;
+ }
+ }
+ if ((user->registered == 7) && (!*user->oper) && (*Config->DisabledCommands))
+ {
+ std::stringstream dcmds(Config->DisabledCommands);
+ std::string thiscmd;
+ while (dcmds >> thiscmd)
+ {
+ if (!strcasecmp(thiscmd.c_str(),command))
+ {
+ // command is disabled!
+ WriteServ(user->fd,"421 %s %s :This command has been disabled.",user->nick,command);
+ return;
+ }
+ }
+ }
+ if ((user->registered == 7) || (cm->second == command_user) || (cm->second == command_nick) || (cm->second == command_pass))
+ {
+ /* ikky /stats counters */
+ if (temp)
+ {
+ cm->second->use_count++;
+ cm->second->total_bytes+=strlen(temp);
+ }
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnPreCommand,OnPreCommand(command,command_p,items,user,true));
+ if (MOD_RESULT == 1)
+ {
+ return;
+ }
+
+ /*
+ * WARNING: nothing may come after the
+ * command handler call, as the handler
+ * may free the user structure!
+ */
+
+ cm->second->Handle(command_p,items,user);
+ return;
+ }
+ else
+ {
+ WriteServ(user->fd,"451 %s :You have not registered",command);
+ return;
+ }
+ }
+ }
+ else if (user)
+ {
+ ServerInstance->stats->statsUnknown++;
+ WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
+ }