- std::string TypeName = Conf->ReadValue("type","name",j);
- Srv->Log(DEBUG,"Scanning opertype: "+TypeName);
- std::string pattern = std::string(user->ident) + "@" + std::string(user->host);
-
- if((TypeName == rowresult->GetField("type")) && OneOfMatches(pattern.c_str(), rowresult->GetField("hostname").c_str()))
- {
- /* found this oper's opertype */
- Srv->Log(DEBUG,"Host and type match: "+TypeName+" "+rowresult->GetField("type"));
- std::string HostName = Conf->ReadValue("type","host",j);
-
- if(HostName != "")
- Srv->ChangeHost(user,HostName);
-
- strlcpy(user->oper,rowresult->GetField("type").c_str(),NICKMAX-1);
- WriteOpers("*** %s (%s@%s) is now an IRC operator of type %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str());
- WriteServ(user->fd,"381 %s :You are now an IRC operator of type %s",user->nick,rowresult->GetField("type").c_str());
- if(!strchr(user->modes,'o'))
+ /* We got a row in the result, this means there was a record for the oper..
+ * now we just need to check if their host matches, and if it does then
+ * oper them up.
+ *
+ * We now (previous versions of the module didn't) support multiple SQL
+ * rows per-oper in the same way the config file does, all rows will be tried
+ * until one is found which matches. This is useful to define several different
+ * hosts for a single oper.
+ *
+ * The for() loop works as SQLresult::GetRowMap() returns an empty map when there
+ * are no more rows to return.
+ */
+
+ for (SQLfieldMap& row = res->GetRowMap(); row.size(); row = res->GetRowMap())
+ {
+ if (OperUser(user, row["username"].d, row["password"].d, row["hostname"].d, row["type"].d))
+ {
+ /* If/when one of the rows matches, stop checking and return */
+ return SQLSUCCESS;
+ }
+ if (tried_user && tried_pass)