module.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. package modules
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "sort"
  6. "strings"
  7. "imuslab.com/arozos/mod/user"
  8. "imuslab.com/arozos/mod/utils"
  9. )
  10. type ModuleInfo struct {
  11. Name string //Name of this module. e.g. "Audio"
  12. Desc string //Description for this module
  13. Group string //Group of the module, e.g. "system" / "media" etc
  14. IconPath string //Module icon image path e.g. "Audio/img/function_icon.png"
  15. Version string //Version of the module. Format: [0-9]*.[0-9][0-9].[0-9]
  16. StartDir string //Default starting dir, e.g. "Audio/index.html"
  17. SupportFW bool //Support floatWindow. If yes, floatWindow dir will be loaded
  18. LaunchFWDir string //This link will be launched instead of 'StartDir' if fw mode
  19. SupportEmb bool //Support embedded mode
  20. LaunchEmb string //This link will be launched instead of StartDir / Fw if a file is opened with this module
  21. InitFWSize []int //Floatwindow init size. [0] => Width, [1] => Height
  22. InitEmbSize []int //Embedded mode init size. [0] => Width, [1] => Height
  23. SupportedExt []string //Supported File Extensions. e.g. ".mp3", ".flac", ".wav"
  24. //Hidden properties
  25. allowReload bool //Allow module reload by user
  26. }
  27. type ModuleHandler struct {
  28. LoadedModule []*ModuleInfo
  29. userHandler *user.UserHandler
  30. tmpDirectory string
  31. }
  32. func NewModuleHandler(userHandler *user.UserHandler, tmpFolderPath string) *ModuleHandler {
  33. return &ModuleHandler{
  34. LoadedModule: []*ModuleInfo{},
  35. userHandler: userHandler,
  36. tmpDirectory: tmpFolderPath,
  37. }
  38. }
  39. //Register endpoint. Provide moduleInfo datastructure or unparsed json
  40. func (m *ModuleHandler) RegisterModule(module ModuleInfo) {
  41. m.LoadedModule = append(m.LoadedModule, &module)
  42. //Add the module into universal module if it is utilities or system tools
  43. moduleGroupLowerCase := strings.ToLower(module.Group)
  44. if moduleGroupLowerCase == "utilities" || moduleGroupLowerCase == "system tools" {
  45. m.userHandler.UniversalModules = append(m.userHandler.UniversalModules, module.Name)
  46. }
  47. }
  48. //Sort the module list
  49. func (m *ModuleHandler) ModuleSortList() {
  50. sort.Slice(m.LoadedModule, func(i, j int) bool {
  51. return m.LoadedModule[i].Name < m.LoadedModule[j].Name
  52. })
  53. }
  54. //Register a module from JSON string
  55. func (m *ModuleHandler) RegisterModuleFromJSON(jsonstring string, allowReload bool) error {
  56. var thisModuleInfo ModuleInfo
  57. err := json.Unmarshal([]byte(jsonstring), &thisModuleInfo)
  58. if err != nil {
  59. return err
  60. }
  61. thisModuleInfo.allowReload = allowReload
  62. m.RegisterModule(thisModuleInfo)
  63. return nil
  64. }
  65. //Register a module from AGI script
  66. func (m *ModuleHandler) RegisterModuleFromAGI(jsonstring string) error {
  67. var thisModuleInfo ModuleInfo
  68. err := json.Unmarshal([]byte(jsonstring), &thisModuleInfo)
  69. if err != nil {
  70. return err
  71. }
  72. //AGI interface loaded module must allow runtime reload
  73. thisModuleInfo.allowReload = true
  74. m.RegisterModule(thisModuleInfo)
  75. return nil
  76. }
  77. func (m *ModuleHandler) DeregisterModule(moduleName string) {
  78. newLoadedModuleList := []*ModuleInfo{}
  79. for _, thisModule := range m.LoadedModule {
  80. if thisModule.Name != moduleName {
  81. newLoadedModuleList = append(newLoadedModuleList, thisModule)
  82. }
  83. }
  84. m.LoadedModule = newLoadedModuleList
  85. }
  86. //Get a list of module names
  87. func (m *ModuleHandler) GetModuleNameList() []string {
  88. result := []string{}
  89. for _, module := range m.LoadedModule {
  90. result = append(result, module.Name)
  91. }
  92. return result
  93. }
  94. // GetModuleListJSONForUser returns a JSON string of all modules the given username can access
  95. func (m *ModuleHandler) GetModuleListJSONForUser(username string) string {
  96. userinfo, err := m.userHandler.GetUserInfoFromUsername(username)
  97. if err != nil {
  98. return "[]"
  99. }
  100. accessable := []*ModuleInfo{}
  101. for _, mod := range m.LoadedModule {
  102. if userinfo.GetModuleAccessPermission(mod.Name) {
  103. accessable = append(accessable, mod)
  104. }
  105. }
  106. js, _ := json.Marshal(accessable)
  107. return string(js)
  108. }
  109. //Handle Default Launcher
  110. func (m *ModuleHandler) HandleDefaultLauncher(w http.ResponseWriter, r *http.Request) {
  111. username, _ := m.userHandler.GetAuthAgent().GetUserName(w, r)
  112. opr, _ := utils.GetPara(r, "opr") //Operation, accept {get, set, launch}
  113. ext, _ := utils.GetPara(r, "ext")
  114. moduleName, _ := utils.GetPara(r, "module")
  115. ext = strings.ToLower(ext)
  116. //Check if the default folder exists.
  117. switch opr {
  118. case "get":
  119. //Get the opener for this file type
  120. value := ""
  121. err := m.userHandler.GetDatabase().Read("module", "default/"+username+"/"+ext, &value)
  122. if err != nil {
  123. utils.SendErrorResponse(w, "No default opener")
  124. return
  125. }
  126. js, _ := json.Marshal(value)
  127. utils.SendJSONResponse(w, string(js))
  128. return
  129. case "launch":
  130. //Get launch paramter for this extension
  131. value := ""
  132. err := m.userHandler.GetDatabase().Read("module", "default/"+username+"/"+ext, &value)
  133. if err != nil {
  134. utils.SendErrorResponse(w, "No default opener")
  135. return
  136. }
  137. //Get the launch paramter of this module
  138. var modInfo *ModuleInfo = nil
  139. modExists := false
  140. for _, mod := range m.LoadedModule {
  141. if mod.Name == value {
  142. modInfo = mod
  143. modExists = true
  144. }
  145. }
  146. if !modExists {
  147. //This module has been removed or not exists anymore
  148. utils.SendErrorResponse(w, "Default opener no longer exists.")
  149. return
  150. } else {
  151. //Return launch inforamtion
  152. jsonString, _ := json.Marshal(modInfo)
  153. utils.SendJSONResponse(w, string(jsonString))
  154. }
  155. case "set":
  156. //Set the opener for this filetype
  157. if moduleName == "" {
  158. utils.SendErrorResponse(w, "Missing paratmer 'module'")
  159. return
  160. }
  161. //Check if module name exists
  162. moduleValid := false
  163. for _, mod := range m.LoadedModule {
  164. if mod.Name == moduleName {
  165. moduleValid = true
  166. }
  167. }
  168. if moduleValid {
  169. m.userHandler.GetDatabase().Write("module", "default/"+username+"/"+ext, moduleName)
  170. utils.SendJSONResponse(w, "\"OK\"")
  171. } else {
  172. utils.SendErrorResponse(w, "Given module not exists.")
  173. }
  174. case "list":
  175. //List all the values that belongs to default opener
  176. dbDump, _ := m.userHandler.GetDatabase().ListTable("module")
  177. results := [][]string{}
  178. for _, entry := range dbDump {
  179. key := string(entry[0])
  180. if strings.Contains(key, "default/"+username+"/") {
  181. //This is a correct matched entry
  182. extInfo := strings.Split(key, "/")
  183. ext := extInfo[len(extInfo)-1:]
  184. moduleName := ""
  185. json.Unmarshal(entry[1], &moduleName)
  186. results = append(results, []string{ext[0], moduleName})
  187. }
  188. }
  189. jsonString, _ := json.Marshal(results)
  190. utils.SendJSONResponse(w, string(jsonString))
  191. return
  192. }
  193. }
  194. func (m *ModuleHandler) ListLoadedModules(w http.ResponseWriter, r *http.Request) {
  195. userinfo, _ := m.userHandler.GetUserInfoFromRequest(w, r)
  196. ///Parse a list of modules where the user has permission to access
  197. userAccessableModules := []*ModuleInfo{}
  198. for _, thisModule := range m.LoadedModule {
  199. thisModuleName := thisModule.Name
  200. if userinfo.GetModuleAccessPermission(thisModuleName) {
  201. userAccessableModules = append(userAccessableModules, thisModule)
  202. }
  203. }
  204. //Return the loaded modules as a list of JSON string
  205. jsonString, _ := json.Marshal(userAccessableModules)
  206. utils.SendJSONResponse(w, string(jsonString))
  207. }
  208. func (m *ModuleHandler) GetModuleInfoByID(moduleid string) *ModuleInfo {
  209. for _, module := range m.LoadedModule {
  210. if module.Name == moduleid {
  211. return module
  212. }
  213. }
  214. return nil
  215. }
  216. func (m *ModuleHandler) GetLaunchParameter(w http.ResponseWriter, r *http.Request) {
  217. moduleName, _ := utils.GetPara(r, "module")
  218. if moduleName == "" {
  219. utils.SendErrorResponse(w, "Missing paramter 'module'.")
  220. return
  221. }
  222. //Loop through the modules and see if the module exists.
  223. var targetLaunchInfo *ModuleInfo = nil
  224. found := false
  225. for _, module := range m.LoadedModule {
  226. thisModuleName := module.Name
  227. if thisModuleName == moduleName {
  228. targetLaunchInfo = module
  229. found = true
  230. }
  231. }
  232. if found {
  233. jsonString, _ := json.Marshal(targetLaunchInfo)
  234. utils.SendJSONResponse(w, string(jsonString))
  235. return
  236. } else {
  237. utils.SendErrorResponse(w, "Given module not exists.")
  238. return
  239. }
  240. }