module.go 7.3 KB

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