@@ -126,7 +126,6 @@ void CLuaMain::InitSecurity ( void )
126126{
127127 lua_register ( m_luaVM, " dofile" , CLuaUtilDefs::DisabledFunction );
128128 lua_register ( m_luaVM, " loadfile" , CLuaUtilDefs::DisabledFunction );
129- lua_register ( m_luaVM, " require" , CLuaUtilDefs::DisabledFunction );
130129 lua_register ( m_luaVM, " loadlib" , CLuaUtilDefs::DisabledFunction );
131130 lua_register ( m_luaVM, " getfenv" , CLuaUtilDefs::DisabledFunction );
132131 lua_register ( m_luaVM, " newproxy" , CLuaUtilDefs::DisabledFunction );
@@ -192,6 +191,9 @@ void CLuaMain::InitVM ( void )
192191 luaopen_debug ( m_luaVM );
193192 luaopen_utf8 ( m_luaVM );
194193
194+ // Initialize packages system
195+ InitPackageStorage (m_luaVM);
196+
195197 // Initialize security restrictions. Very important to prevent lua trojans and viruses!
196198 InitSecurity ();
197199
@@ -250,7 +252,7 @@ void CLuaMain::InstructionCountHook ( lua_State* luaVM, lua_Debug* pDebug )
250252}
251253
252254
253- bool CLuaMain::LoadScriptFromBuffer ( const char * cpInBuffer, unsigned int uiInSize, const char * szFileName )
255+ bool CLuaMain::LoadScriptFromBuffer ( const char * cpInBuffer, unsigned int uiInSize, const char * szFileName, bool bClearReturnValues )
254256{
255257 SString strNiceFilename = ConformResourcePath ( szFileName );
256258
@@ -320,7 +322,7 @@ bool CLuaMain::LoadScriptFromBuffer ( const char* cpInBuffer, unsigned int uiInS
320322 g_pGame->GetScriptDebugging ()->LogPCallError ( m_luaVM, strRes, true );
321323 }
322324 // Cleanup any return values
323- if ( lua_gettop ( m_luaVM ) > luaSavedTop )
325+ if ( bClearReturnValues && lua_gettop ( m_luaVM ) > luaSavedTop )
324326 lua_settop ( m_luaVM, luaSavedTop );
325327 return true ;
326328 }
@@ -686,3 +688,164 @@ int CLuaMain::OnUndump( const char* p, size_t n )
686688 }
687689 return 1 ;
688690}
691+
692+
693+ // /////////////////////////////////////////////////////////////
694+ //
695+ // CLuaMain::InitPackageStorage
696+ //
697+ // Create a table for storage of Lua packages - stored in the Lua VM
698+ //
699+ // /////////////////////////////////////////////////////////////
700+ void CLuaMain::InitPackageStorage (lua_State* L)
701+ {
702+ lua_newtable (L); // stack: [tbl_new]
703+ lua_pushstring (L, " loaded" ); // stack: [tbl_new,"loaded"]
704+ lua_newtable (L); // stack: [tbl_new,"loaded",tbl_new2]
705+
706+ // We push our default Lua libs are loaded packages
707+ std::vector<const char *> szDefaultLibs = { " math" , " string" , " table" , " debug" , " utf8" };
708+ for (auto it : szDefaultLibs)
709+ {
710+ lua_pushstring (L, it); // stack: [tbl_new,"loaded",tbl_new2,"math"]
711+ lua_getglobal (L, it); // stack: [tbl_new,"loaded",tbl_new2,"math",_G.math]
712+ lua_settable (L, -3 ); // stack: [tbl_new,"loaded",tbl_new2]
713+ }
714+
715+ // Finally, store our original table as package.loaded
716+ lua_settable (L, -3 ); // stack: [tbl_new]
717+ lua_setglobal (L, " package" ); // stack: []
718+ }
719+
720+ // /////////////////////////////////////////////////////////////
721+ //
722+ // CLuaMain::SetPackage
723+ //
724+ // Pop the top most value as a package
725+ //
726+ // /////////////////////////////////////////////////////////////
727+ void CLuaMain::SetPackage (lua_State* L, SString &strName )
728+ {
729+ // We set varPkg, which is already on the stack, into package.loaded.moduleName = varPkg.
730+ // stack: [varPkg]
731+ int iPkg = luaL_ref (L, LUA_REGISTRYINDEX); // stack: []
732+ lua_getglobal (L, " package" ); // stack: [tbl_package]
733+ if (lua_type (L, -1 ) == LUA_TNIL )
734+ InitPackageStorage (L);
735+
736+ lua_pushstring (L, " loaded" ); // stack: [tbl_package,"loaded"]
737+ lua_rawget (L, -2 ); // stack: [tbl_package,tbl_loaded]
738+ if (lua_type (L, -1 ) == LUA_TNIL)
739+ InitPackageStorage (L);
740+
741+
742+ lua_pushstring (L, strName.c_str ()); // stack: [tbl_package,tbl_loaded,"moduleName"]
743+ lua_rawgeti (L, LUA_REGISTRYINDEX, iPkg); // stack: [tbl_package,tbl_loaded,"moduleName",varPkg]
744+ lua_rawset (L, -3 ); // stack: [tbl_package,tbl_loaded]
745+ lua_pop (L, 2 ); // stack: []
746+ lua_rawgeti (L, LUA_REGISTRYINDEX, iPkg); // stack: [varPkg]
747+
748+ // Cleanup our used registry entry, REGISTRY[i] = nil.
749+ lua_pushnil (L); // stack: [varPkg,nil]
750+ lua_rawseti (L, LUA_REGISTRYINDEX, iPkg); // stack: [varPkg]
751+ }
752+
753+ // /////////////////////////////////////////////////////////////
754+ //
755+ // CLuaMain::GetPackage
756+ //
757+ // Push the value of a package of name to the stack
758+ //
759+ // /////////////////////////////////////////////////////////////
760+ void CLuaMain::GetPackage (lua_State* L, SString &strName)
761+ {
762+ lua_getglobal (L, " package" ); // stack: [tbl_package]
763+ if (lua_type (L, -1 ) == LUA_TNIL )
764+ InitPackageStorage (m_luaVM);
765+
766+ lua_pushstring (L, " loaded" ); // stack: [tbl_package,"loaded"]
767+ if (lua_type (L, -1 ) == LUA_TNIL)
768+ InitPackageStorage (m_luaVM);
769+
770+ lua_rawget (L, -2 ); // stack: [tbl_package,tbl_loaded]
771+ lua_pushstring (L, strName.c_str ()); // stack: [tbl_package,tbl_loaded,"moduleName"]
772+ lua_rawget (L, -2 ); // stack: [tbl_package,varPkg]
773+ lua_remove (L, -2 ); // stack: [varPkg]
774+ }
775+
776+ // /////////////////////////////////////////////////////////////
777+ //
778+ // CLuaMain::LoadLuaLib
779+ //
780+ // Load a Lua lib of a given name
781+ //
782+ // /////////////////////////////////////////////////////////////
783+ bool CLuaMain::LoadLuaLib (lua_State *L, SString strName)
784+ {
785+ SString strPath = strName;
786+ // Name format shouldn't include slashes. Subdirs are dots.
787+ ReplaceOccurrencesInString (strPath, " \\ " , " " );
788+ ReplaceOccurrencesInString (strPath, " /" , " " );
789+ ReplaceOccurrencesInString (strPath, " ." , " /" );
790+
791+ SString strResPath = m_pResource->IsResourceZip () ? m_pResource->GetResourceCacheDirectoryPath () : m_pResource->GetResourceDirectoryPath ();
792+
793+ std::vector < char > buffer;
794+ // Try <resource>/?.lua
795+ SString strFilePath = PathJoin (strResPath, strPath + " .lua" );
796+ if (FileExists (strFilePath))
797+ FileLoad (strFilePath, buffer);
798+ else
799+ {
800+ // Try <resource>/?/init.lua
801+ strFilePath = PathJoin (strResPath, strPath, " init.lua" );
802+ if (FileExists (strFilePath))
803+ FileLoad (strFilePath, buffer);
804+ }
805+
806+ if (buffer.size () > 0 )
807+ {
808+ int luaSavedTop = lua_gettop (L);
809+ LoadScriptFromBuffer (&buffer.at (0 ), buffer.size (), strFilePath.c_str (), false );
810+ // Only keep the first return value
811+ if (lua_gettop (L) > luaSavedTop)
812+ lua_settop (L, luaSavedTop+1 );
813+
814+ SetPackage (L, strName); // Store our package into package.loaded
815+ GetPackage (L, strName); // Grab it back as a return value.
816+ return true ;
817+ }
818+
819+ return false ;
820+ }
821+
822+ // /////////////////////////////////////////////////////////////
823+ //
824+ // CLuaMain::LoadClib
825+ //
826+ // Load a C lib of a given name
827+ //
828+ // /////////////////////////////////////////////////////////////
829+ bool CLuaMain::LoadClib (lua_State* L, SString strName)
830+ {
831+ SString strPath = strName;
832+ // Name format shouldn't include slashes. Subdirs are dots.
833+ ReplaceOccurrencesInString (strPath, " \\ " , " " );
834+ ReplaceOccurrencesInString (strPath, " /" , " " );
835+ ReplaceOccurrencesInString (strPath, " ." , " /" );
836+
837+ strPath = PathJoin (g_pServerInterface->GetModManager ()->GetServerPath (), SERVER_BIN_PATH_MOD, " modules" , strPath);
838+
839+ #ifdef WIN32
840+ strPath += " .dll" ;
841+ #else
842+ strPath += " .so" ;
843+ #endif
844+
845+ luaL_loader_C (L, strName.c_str (), strPath.c_str ());
846+ if (lua_type (L, -1 ) == LUA_TNIL)
847+ return false ;
848+
849+ SetPackage (L, strName);
850+ return true ;
851+ }
0 commit comments