| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 | package modulesimport (	"encoding/json"	"net/http"	"sort"	"strings"	"imuslab.com/arozos/mod/user")type ModuleInfo struct {	Name         string   //Name of this module. e.g. "Audio"	Desc         string   //Description for this module	Group        string   //Group of the module, e.g. "system" / "media" etc	IconPath     string   //Module icon image path e.g. "Audio/img/function_icon.png"	Version      string   //Version of the module. Format: [0-9]*.[0-9][0-9].[0-9]	StartDir     string   //Default starting dir, e.g. "Audio/index.html"	SupportFW    bool     //Support floatWindow. If yes, floatWindow dir will be loaded	LaunchFWDir  string   //This link will be launched instead of 'StartDir' if fw mode	SupportEmb   bool     //Support embedded mode	LaunchEmb    string   //This link will be launched instead of StartDir / Fw if a file is opened with this module	InitFWSize   []int    //Floatwindow init size. [0] => Width, [1] => Height	InitEmbSize  []int    //Embedded mode init size. [0] => Width, [1] => Height	SupportedExt []string //Supported File Extensions. e.g. ".mp3", ".flac", ".wav"	//Hidden properties	allowReload bool //Allow module reload by user}type ModuleHandler struct {	LoadedModule []*ModuleInfo	userHandler  *user.UserHandler	tmpDirectory string}func NewModuleHandler(userHandler *user.UserHandler, tmpFolderPath string) *ModuleHandler {	return &ModuleHandler{		LoadedModule: []*ModuleInfo{},		userHandler:  userHandler,		tmpDirectory: tmpFolderPath,	}}//Register endpoint. Provide moduleInfo datastructure or unparsed jsonfunc (m *ModuleHandler) RegisterModule(module ModuleInfo) {	m.LoadedModule = append(m.LoadedModule, &module)	//Add the module into universal module if it is utilities or system tools	moduleGroupLowerCase := strings.ToLower(module.Group)	if moduleGroupLowerCase == "utilities" || moduleGroupLowerCase == "system tools" {		m.userHandler.UniversalModules = append(m.userHandler.UniversalModules, module.Name)	}}//Sort the module listfunc (m *ModuleHandler) ModuleSortList() {	sort.Slice(m.LoadedModule, func(i, j int) bool {		return m.LoadedModule[i].Name < m.LoadedModule[j].Name	})}//Register a module from JSON stringfunc (m *ModuleHandler) RegisterModuleFromJSON(jsonstring string, allowReload bool) error {	var thisModuleInfo ModuleInfo	err := json.Unmarshal([]byte(jsonstring), &thisModuleInfo)	if err != nil {		return err	}	thisModuleInfo.allowReload = allowReload	m.RegisterModule(thisModuleInfo)	return nil}//Register a module from AGI scriptfunc (m *ModuleHandler) RegisterModuleFromAGI(jsonstring string) error {	var thisModuleInfo ModuleInfo	err := json.Unmarshal([]byte(jsonstring), &thisModuleInfo)	if err != nil {		return err	}	//AGI interface loaded module must allow runtime reload	thisModuleInfo.allowReload = true	m.RegisterModule(thisModuleInfo)	return nil}func (m *ModuleHandler) DeregisterModule(moduleName string) {	newLoadedModuleList := []*ModuleInfo{}	for _, thisModule := range m.LoadedModule {		if thisModule.Name != moduleName {			newLoadedModuleList = append(newLoadedModuleList, thisModule)		}	}	m.LoadedModule = newLoadedModuleList}//Get a list of module namesfunc (m *ModuleHandler) GetModuleNameList() []string {	result := []string{}	for _, module := range m.LoadedModule {		result = append(result, module.Name)	}	return result}//Handle Default Launcherfunc (m *ModuleHandler) HandleDefaultLauncher(w http.ResponseWriter, r *http.Request) {	username, _ := m.userHandler.GetAuthAgent().GetUserName(w, r)	opr, _ := mv(r, "opr", false) //Operation, accept {get, set, launch}	ext, _ := mv(r, "ext", false)	moduleName, _ := mv(r, "module", false)	ext = strings.ToLower(ext)	//Check if the default folder exists.	if opr == "get" {		//Get the opener for this file type		value := ""		err := m.userHandler.GetDatabase().Read("module", "default/"+username+"/"+ext, &value)		if err != nil {			sendErrorResponse(w, "No default opener")			return		}		js, _ := json.Marshal(value)		sendJSONResponse(w, string(js))		return	} else if opr == "launch" {		//Get launch paramter for this extension		value := ""		err := m.userHandler.GetDatabase().Read("module", "default/"+username+"/"+ext, &value)		if err != nil {			sendErrorResponse(w, "No default opener")			return		}		//Get the launch paramter of this module		var modInfo *ModuleInfo = nil		modExists := false		for _, mod := range m.LoadedModule {			if mod.Name == value {				modInfo = mod				modExists = true			}		}		if !modExists {			//This module has been removed or not exists anymore			sendErrorResponse(w, "Default opener no longer exists.")			return		} else {			//Return launch inforamtion			jsonString, _ := json.Marshal(modInfo)			sendJSONResponse(w, string(jsonString))		}	} else if opr == "set" {		//Set the opener for this filetype		if moduleName == "" {			sendErrorResponse(w, "Missing paratmer 'module'")			return		}		//Check if module name exists		moduleValid := false		for _, mod := range m.LoadedModule {			if mod.Name == moduleName {				moduleValid = true			}		}		if moduleValid {			m.userHandler.GetDatabase().Write("module", "default/"+username+"/"+ext, moduleName)			sendJSONResponse(w, "\"OK\"")		} else {			sendErrorResponse(w, "Given module not exists.")		}	} else if opr == "list" {		//List all the values that belongs to default opener		dbDump, _ := m.userHandler.GetDatabase().ListTable("module")		results := [][]string{}		for _, entry := range dbDump {			key := string(entry[0])			if strings.Contains(key, "default/"+username+"/") {				//This is a correct matched entry				extInfo := strings.Split(key, "/")				ext := extInfo[len(extInfo)-1:]				moduleName := ""				json.Unmarshal(entry[1], &moduleName)				results = append(results, []string{ext[0], moduleName})			}		}		jsonString, _ := json.Marshal(results)		sendJSONResponse(w, string(jsonString))		return	}}func (m *ModuleHandler) ListLoadedModules(w http.ResponseWriter, r *http.Request) {	userinfo, _ := m.userHandler.GetUserInfoFromRequest(w, r)	///Parse a list of modules where the user has permission to access	userAccessableModules := []*ModuleInfo{}	for _, thisModule := range m.LoadedModule {		thisModuleName := thisModule.Name		if userinfo.GetModuleAccessPermission(thisModuleName) {			userAccessableModules = append(userAccessableModules, thisModule)		}	}	//Return the loaded modules as a list of JSON string	jsonString, _ := json.Marshal(userAccessableModules)	sendJSONResponse(w, string(jsonString))}func (m *ModuleHandler) GetModuleInfoByID(moduleid string) *ModuleInfo {	for _, module := range m.LoadedModule {		if module.Name == moduleid {			return module		}	}	return nil}func (m *ModuleHandler) GetLaunchParameter(w http.ResponseWriter, r *http.Request) {	moduleName, _ := mv(r, "module", false)	if moduleName == "" {		sendErrorResponse(w, "Missing paramter 'module'.")		return	}	//Loop through the modules and see if the module exists.	var targetLaunchInfo *ModuleInfo = nil	found := false	for _, module := range m.LoadedModule {		thisModuleName := module.Name		if thisModuleName == moduleName {			targetLaunchInfo = module			found = true		}	}	if found {		jsonString, _ := json.Marshal(targetLaunchInfo)		sendJSONResponse(w, string(jsonString))		return	} else {		sendErrorResponse(w, "Given module not exists.")		return	}}
 |