#include #include #include #include "sh_list.h" #include "CString.h" #include "amxmodx.h" #include "CFlagManager.h" void CFlagManager::SetFile(const char *Filename) { m_strConfigFile.assign(g_mod_name.c_str()); m_strConfigFile.append("/"); m_strConfigFile.append(get_localinfo("amxx_configsdir","addons/amxmodx/configs")); m_strConfigFile.append("/"); m_strConfigFile.append(Filename); CreateIfNotExist(); } const int CFlagManager::LoadFile(const int force) { CheckIfDisabled(); // If we're disabled get the hell out. now. if (m_iDisabled) { return 0; } // if we're not forcing this, and NeedToLoad says we dont have to // then just stop if (!force && !NeedToLoad()) { return 0; }; this->Clear(); // We need to load the file FILE *File; File=fopen(m_strConfigFile.c_str(),"r"); if (!File) { AMXXLOG_Log("[AMXX] FlagManager: Cannot open file \"%s\" (FILE pointer null!)",m_strConfigFile.c_str()); return -1; }; // Trying to copy this almost exactly as other configs are read... String Line; char Command[256]; char Flags[256]; String TempLine; while (!feof(File)) { Line._fread(File); char *nonconst=const_cast(Line.c_str()); // Strip out comments while (*nonconst) { if (*nonconst==';') // End the line at comments { *nonconst='\0'; } else { nonconst++; } }; Command[0]='\0'; Flags[0]='\0'; // Extract the command TempLine.assign(Line.c_str()); nonconst=const_cast(TempLine.c_str()); char *start=NULL; char *end=NULL; // move up line until the first ", mark this down as the start // then find the second " and mark it down as the end while (*nonconst!='\0') { if (*nonconst=='"') { if (start==NULL) { start=nonconst+1; } else { end=nonconst; goto done_with_command; } } nonconst++; } done_with_command: // invalid line? if (start==NULL || end==NULL) { // TODO: maybe warn for an invalid non-commented line? continue; } *end='\0'; strncpy(Command,start,sizeof(Command)-1); // Now do the same thing for the flags nonconst=++end; start=NULL; end=NULL; // move up line until the first ", mark this down as the start // then find the second " and mark it down as the end while (*nonconst!='\0') { if (*nonconst=='"') { if (start==NULL) { start=nonconst+1; } else { end=nonconst; goto done_with_flags; } } nonconst++; } done_with_flags: // invalid line? if (start==NULL || end==NULL) { // TODO: maybe warn for an invalid non-commented line? continue; } *end='\0'; strncpy(Flags,start,sizeof(Flags)-1); //if (!isalnum(*Command)) if (*Command == '"' || *Command == '\0') { continue; }; // Done sucking the command and flags out of the line // now insert this command into the linked list AddFromFile(const_cast(&Command[0]),&Flags[0]); nonconst=const_cast(Line.c_str()); *nonconst='\0'; }; fclose(File); return 1; } /** * This gets called from LoadFile * Do NOT flag the entries as NeedToWrite * No comment is passed from the file because * this should never get written */ void CFlagManager::AddFromFile(const char *Command, const char *Flags) { CFlagEntry *Entry=new CFlagEntry; Entry->SetName(Command); Entry->SetFlags(Flags); // Link it m_FlagList.push_back(Entry); }; void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin) { if (m_iDisabled) // if disabled in core.ini stop { return; } int TempFlags=Flags; if (TempFlags==-1) { TempFlags=0; } List::iterator iter; List::iterator end; iter=m_FlagList.begin(); end=m_FlagList.end(); while (iter!=end) { if (strcmp((*iter)->GetName()->c_str(),Command)==0) { CFlagEntry *Entry=(*iter); if (Entry->IsHidden()) // "!" flag, exclude this function { return; } // Found, byref the new flags Flags=Entry->Flags(); // Move it to the back of the list for faster lookup for the rest m_FlagList.erase(iter); m_FlagList.push_back(Entry); return; } iter++; } // was not found, add it CFlagEntry *Entry=new CFlagEntry; Entry->SetName(Command); Entry->SetFlags(TempFlags); if (Plugin) { CPluginMngr::CPlugin* a = g_plugins.findPluginFast(Plugin); if (a) { Entry->SetComment(a->getName()); } } // This entry was added from a register_* native // it needs to be written during map change Entry->SetNeedWritten(1); // Link it m_FlagList.push_back(Entry); } void CFlagManager::WriteCommands(void) { List::iterator iter; List::iterator end; FILE *File; int NeedToRead=0; // First off check the modified time of this file // if it matches the stored modified time, then update // after we write so we do not re-read next map struct stat TempStat; stat(m_strConfigFile.c_str(),&TempStat); if (TempStat.st_mtime != m_Stat.st_mtime) { NeedToRead=1; }; File=fopen(m_strConfigFile.c_str(),"a"); if (!File) { return; } iter=m_FlagList.begin(); end=m_FlagList.end(); while (iter!=end) { if ((*iter)->NeedWritten()) { if ((*iter)->GetComment()->size()) { fprintf(File,"\"%s\" \t\"%s\" ; %s\n",(*iter)->GetName()->c_str(),(*iter)->GetFlags()->c_str(),(*iter)->GetComment()->c_str()); } else { fprintf(File,"\"%s\" \t\"%s\"\n",(*iter)->GetName()->c_str(),(*iter)->GetFlags()->c_str()); } (*iter)->SetNeedWritten(0); } ++iter; }; fclose(File); // If NeedToRead was 0, then update the timestamp // that was saved so we do not re-read this file // next map if (!NeedToRead) { stat(m_strConfigFile.c_str(),&TempStat); m_Stat.st_mtime=TempStat.st_mtime; } } int CFlagManager::ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const { // If flagmanager is disabled then ignore this if (m_iDisabled) { return 0; } // If 5th param exists it was compiled after this change was made // if it does not exist, try our logic at the end of this function // 5th param being > 0 means explicit yes // < 0 means auto detect (default is -1), treat it like there was no 5th param // 0 means explicit no if ((params[0] / sizeof(cell)) >= 5) { if (params[5]>0) // This command was explicitly told to be included { return 1; } else if (params[5]==0) // this command was explicitly told to NOT be used { return 0; } } // auto detect if we should use this command // if command access is -1 (default, not set to ADMIN_ALL or any other access), then no if (params[3]==-1) { return 0; } // if command is (or starts with) "say", then no if (strncmp(cmdname,"say",3)==0) { return 0; } // else use it return 1; }; void CFlagManager::Clear(void) { List::iterator iter; List::iterator end; iter=m_FlagList.begin(); end=m_FlagList.end(); while (iter!=end) { delete (*iter); ++iter; } m_FlagList.clear(); }; void CFlagManager::CheckIfDisabled(void) { if (atoi(get_localinfo("disableflagman","0"))==0) { m_iDisabled=0; } else { m_iDisabled=1; } };