desktop.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "os"
  8. "path/filepath"
  9. "strconv"
  10. "strings"
  11. fs "imuslab.com/arozos/mod/filesystem"
  12. "imuslab.com/arozos/mod/filesystem/arozfs"
  13. "imuslab.com/arozos/mod/filesystem/shortcut"
  14. module "imuslab.com/arozos/mod/modules"
  15. prout "imuslab.com/arozos/mod/prouter"
  16. "imuslab.com/arozos/mod/utils"
  17. )
  18. // Desktop script initiation
  19. func DesktopInit() {
  20. systemWideLogger.PrintAndLog("Desktop", "Starting Desktop Services", nil)
  21. router := prout.NewModuleRouter(prout.RouterOption{
  22. ModuleName: "Desktop",
  23. AdminOnly: false,
  24. UserHandler: userHandler,
  25. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  26. utils.SendErrorResponse(w, "Permission Denied")
  27. },
  28. })
  29. //Register all the required API
  30. router.HandleFunc("/system/desktop/listDesktop", desktop_listFiles)
  31. router.HandleFunc("/system/desktop/theme", desktop_theme_handler)
  32. router.HandleFunc("/system/desktop/files", desktop_fileLocation_handler)
  33. router.HandleFunc("/system/desktop/host", desktop_hostdetailHandler)
  34. router.HandleFunc("/system/desktop/user", desktop_handleUserInfo)
  35. router.HandleFunc("/system/desktop/preference", desktop_preference_handler)
  36. router.HandleFunc("/system/desktop/createShortcut", desktop_shortcutHandler)
  37. //API related to desktop based operations
  38. router.HandleFunc("/system/desktop/opr/renameShortcut", desktop_handleShortcutRename)
  39. //Initialize desktop database
  40. err := sysdb.NewTable("desktop")
  41. if err != nil {
  42. systemWideLogger.PrintAndLog("System", "Unable to create database table for Desktop. Please validation your installation.", nil)
  43. systemWideLogger.PrintAndLog("System", fmt.Sprint(err), nil)
  44. os.Exit(1)
  45. }
  46. //Register Desktop settings sub-items
  47. registerSetting(settingModule{
  48. Name: "Wallpaper",
  49. Desc: "Desktop Wallpaper Settings",
  50. IconPath: "SystemAO/desktop/img/personalization.png",
  51. Group: "Desktop",
  52. StartDir: "SystemAO/desktop/settings/wallpaper.html",
  53. })
  54. registerSetting(settingModule{
  55. Name: "Sounds",
  56. Desc: "System Sound Settings",
  57. IconPath: "SystemAO/desktop/img/personalization.png",
  58. Group: "Desktop",
  59. StartDir: "SystemAO/desktop/settings/sounds.html",
  60. })
  61. registerSetting(settingModule{
  62. Name: "Theme",
  63. Desc: "System Theme Color",
  64. IconPath: "SystemAO/desktop/img/personalization.png",
  65. Group: "Desktop",
  66. StartDir: "SystemAO/desktop/settings/theme.html",
  67. })
  68. registerSetting(settingModule{
  69. Name: "Mobile UX",
  70. Desc: "Mobile Desktop Shortcuts",
  71. IconPath: "SystemAO/desktop/img/personalization.png",
  72. Group: "Desktop",
  73. StartDir: "SystemAO/desktop/settings/mobile_ux.html",
  74. })
  75. //Register Desktop Module
  76. moduleHandler.RegisterModule(module.ModuleInfo{
  77. Name: "Desktop",
  78. Desc: "The Web Desktop experience for everyone",
  79. Group: "Interface Module",
  80. IconPath: "img/desktop/desktop.png",
  81. Version: internal_version,
  82. StartDir: "",
  83. SupportFW: false,
  84. LaunchFWDir: "",
  85. SupportEmb: false,
  86. })
  87. }
  88. /*
  89. FUNCTIONS RELATED TO PARSING DESKTOP FILE ICONS
  90. The functions in this section handle file listing and its icon locations.
  91. */
  92. func desktop_initUserFolderStructure(username string) {
  93. //Call to filesystem for creating user file struture at root dir
  94. userinfo, _ := userHandler.GetUserInfoFromUsername(username)
  95. userfsh, err := userinfo.GetHomeFileSystemHandler()
  96. if err != nil {
  97. systemWideLogger.PrintAndLog("Desktop", "Unable to initiate user desktop folder", err)
  98. return
  99. }
  100. userFsa := userfsh.FileSystemAbstraction
  101. userDesktopPath, _ := userFsa.VirtualPathToRealPath("user:/Desktop", userinfo.Username)
  102. if !userFsa.FileExists(userDesktopPath) {
  103. //Desktop directory not exists. Create one and copy a template desktop
  104. userFsa.MkdirAll(userDesktopPath, 0755)
  105. //Copy template file from system folder if exists
  106. templateFolder := "./system/desktop/template/"
  107. if fs.FileExists(templateFolder) {
  108. templateFiles, _ := filepath.Glob(templateFolder + "*")
  109. for _, tfile := range templateFiles {
  110. input, _ := os.ReadFile(tfile)
  111. userFsa.WriteFile(arozfs.ToSlash(filepath.Join(userDesktopPath, filepath.Base(tfile))), input, 0755)
  112. }
  113. }
  114. }
  115. }
  116. // Return the information about the host
  117. func desktop_hostdetailHandler(w http.ResponseWriter, r *http.Request) {
  118. type returnStruct struct {
  119. Hostname string
  120. DeviceUUID string
  121. BuildVersion string
  122. InternalVersion string
  123. DeviceVendor string
  124. DeviceModel string
  125. }
  126. jsonString, _ := json.Marshal(returnStruct{
  127. Hostname: *host_name,
  128. DeviceUUID: deviceUUID,
  129. BuildVersion: build_version,
  130. InternalVersion: internal_version,
  131. DeviceVendor: deviceVendor,
  132. DeviceModel: deviceModel,
  133. })
  134. utils.SendJSONResponse(w, string(jsonString))
  135. }
  136. func desktop_handleShortcutRename(w http.ResponseWriter, r *http.Request) {
  137. //Check if the user directory already exists
  138. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  139. if err != nil {
  140. utils.SendErrorResponse(w, "User not logged in")
  141. return
  142. }
  143. //Get the shortcut file that is renaming
  144. target, err := utils.GetPara(r, "src")
  145. if err != nil {
  146. utils.SendErrorResponse(w, "Invalid shortcut file path given")
  147. return
  148. }
  149. //Get the new name
  150. new, err := utils.GetPara(r, "new")
  151. if err != nil {
  152. utils.SendErrorResponse(w, "Invalid new name given")
  153. return
  154. }
  155. fsh, subpath, _ := GetFSHandlerSubpathFromVpath(target)
  156. fshAbs := fsh.FileSystemAbstraction
  157. //Check if the file actually exists and it is on desktop
  158. rpath, err := fshAbs.VirtualPathToRealPath(subpath, userinfo.Username)
  159. if err != nil {
  160. utils.SendErrorResponse(w, err.Error())
  161. return
  162. }
  163. if target[:14] != "user:/Desktop/" {
  164. utils.SendErrorResponse(w, "Shortcut not on desktop")
  165. return
  166. }
  167. if !fshAbs.FileExists(rpath) {
  168. utils.SendErrorResponse(w, "File not exists")
  169. return
  170. }
  171. //OK. Change the name of the shortcut
  172. originalShortcut, err := fshAbs.ReadFile(rpath)
  173. if err != nil {
  174. utils.SendErrorResponse(w, "Shortcut file read failed")
  175. return
  176. }
  177. lines := strings.Split(string(originalShortcut), "\n")
  178. if len(lines) < 4 {
  179. //Invalid shortcut properties
  180. utils.SendErrorResponse(w, "Invalid shortcut file")
  181. return
  182. }
  183. //Change the 2nd line to the new name
  184. lines[1] = new
  185. newShortcutContent := strings.Join(lines, "\n")
  186. err = fshAbs.WriteFile(rpath, []byte(newShortcutContent), 0755)
  187. if err != nil {
  188. utils.SendErrorResponse(w, err.Error())
  189. return
  190. }
  191. utils.SendOK(w)
  192. }
  193. func desktop_listFiles(w http.ResponseWriter, r *http.Request) {
  194. //Check if the user directory already exists
  195. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  196. if err != nil {
  197. utils.SendErrorResponse(w, "user not logged in!")
  198. return
  199. }
  200. username := userinfo.Username
  201. //Initiate the user folder structure. Do nothing if the structure already exists.
  202. desktop_initUserFolderStructure(username)
  203. //List all files inside the user desktop directory
  204. fsh, subpath, err := GetFSHandlerSubpathFromVpath("user:/Desktop/")
  205. if err != nil {
  206. utils.SendErrorResponse(w, "Desktop file load failed")
  207. return
  208. }
  209. fshAbs := fsh.FileSystemAbstraction
  210. userDesktopRealpath, err := fshAbs.VirtualPathToRealPath(subpath, userinfo.Username)
  211. if err != nil {
  212. utils.SendErrorResponse(w, err.Error())
  213. return
  214. }
  215. files, err := fshAbs.Glob(userDesktopRealpath + "/*")
  216. if err != nil {
  217. utils.SendErrorResponse(w, "Desktop file load failed")
  218. return
  219. }
  220. //Desktop object structure
  221. type desktopObject struct {
  222. Filepath string
  223. Filename string
  224. Ext string
  225. IsDir bool
  226. IsEmptyDir bool
  227. IsShortcut bool
  228. IsShared bool
  229. ShortcutImage string
  230. ShortcutType string
  231. ShortcutName string
  232. ShortcutPath string
  233. IconX int
  234. IconY int
  235. }
  236. desktopFiles := []desktopObject{}
  237. for _, this := range files {
  238. //Always use linux convension for directory seperator
  239. if filepath.Base(this)[:1] == "." {
  240. //Skipping hidden files
  241. continue
  242. }
  243. this = filepath.ToSlash(this)
  244. thisFileObject := new(desktopObject)
  245. thisFileObject.Filepath, _ = fshAbs.RealPathToVirtualPath(this, userinfo.Username)
  246. thisFileObject.Filename = filepath.Base(this)
  247. thisFileObject.Ext = filepath.Ext(this)
  248. thisFileObject.IsDir = fshAbs.IsDir(this)
  249. if thisFileObject.IsDir {
  250. //Check if this dir is empty
  251. filesInFolder, _ := fshAbs.Glob(filepath.ToSlash(filepath.Clean(this)) + "/*")
  252. fc := 0
  253. for _, f := range filesInFolder {
  254. if filepath.Base(f)[:1] != "." {
  255. fc++
  256. }
  257. }
  258. if fc > 0 {
  259. thisFileObject.IsEmptyDir = false
  260. } else {
  261. thisFileObject.IsEmptyDir = true
  262. }
  263. } else {
  264. //File object. Default true
  265. thisFileObject.IsEmptyDir = true
  266. }
  267. //Check if the file is a shortcut
  268. isShortcut := false
  269. if filepath.Ext(this) == ".shortcut" {
  270. isShortcut = true
  271. shortcutInfo, _ := fshAbs.ReadFile(this)
  272. infoSegments := strings.Split(strings.ReplaceAll(string(shortcutInfo), "\r\n", "\n"), "\n")
  273. if len(infoSegments) < 4 {
  274. thisFileObject.ShortcutType = "invalid"
  275. } else {
  276. thisFileObject.ShortcutType = infoSegments[0]
  277. thisFileObject.ShortcutName = infoSegments[1]
  278. thisFileObject.ShortcutPath = infoSegments[2]
  279. thisFileObject.ShortcutImage = infoSegments[3]
  280. }
  281. }
  282. thisFileObject.IsShortcut = isShortcut
  283. //Check if this file is shared
  284. thisFileObject.IsShared = shareManager.FileIsShared(userinfo, thisFileObject.Filepath)
  285. //Check the file location
  286. username, _ := authAgent.GetUserName(w, r)
  287. x, y, _ := getDesktopLocatioFromPath(thisFileObject.Filename, username)
  288. //This file already have a location on desktop
  289. thisFileObject.IconX = x
  290. thisFileObject.IconY = y
  291. desktopFiles = append(desktopFiles, *thisFileObject)
  292. }
  293. //Convert the struct to json string
  294. jsonString, _ := json.Marshal(desktopFiles)
  295. utils.SendJSONResponse(w, string(jsonString))
  296. }
  297. // functions to handle desktop icon locations. Location is directly written into the center db.
  298. func getDesktopLocatioFromPath(filename string, username string) (int, int, error) {
  299. //As path include username, there is no different if there are username in the key
  300. locationdata := ""
  301. err := sysdb.Read("desktop", username+"/filelocation/"+filename, &locationdata)
  302. if err != nil {
  303. //The file location is not set. Return error
  304. return -1, -1, errors.New("This file do not have a location registry")
  305. }
  306. type iconLocation struct {
  307. X int
  308. Y int
  309. }
  310. thisFileLocation := iconLocation{
  311. X: -1,
  312. Y: -1,
  313. }
  314. //Start parsing the from the json data
  315. json.Unmarshal([]byte(locationdata), &thisFileLocation)
  316. return thisFileLocation.X, thisFileLocation.Y, nil
  317. }
  318. // Set the icon location of a given filepath
  319. func setDesktopLocationFromPath(filename string, username string, x int, y int) error {
  320. //You cannot directly set path of others people's deskop. Hence, fullpath needed to be parsed from auth username
  321. userinfo, _ := userHandler.GetUserInfoFromUsername(username)
  322. fsh, subpath, _ := GetFSHandlerSubpathFromVpath("user:/Desktop/")
  323. fshAbs := fsh.FileSystemAbstraction
  324. desktoppath, _ := fshAbs.VirtualPathToRealPath(subpath, userinfo.Username)
  325. path := filepath.Join(desktoppath, filename)
  326. type iconLocation struct {
  327. X int
  328. Y int
  329. }
  330. newLocation := new(iconLocation)
  331. newLocation.X = x
  332. newLocation.Y = y
  333. //Check if the file exits
  334. if !fshAbs.FileExists(path) {
  335. return errors.New("Given filename not exists.")
  336. }
  337. //Parse the location to json
  338. jsonstring, err := json.Marshal(newLocation)
  339. if err != nil {
  340. systemWideLogger.PrintAndLog("Desktop", "Unable to parse new file location on desktop for file: "+path, err)
  341. return err
  342. }
  343. //systemWideLogger.PrintAndLog(key,string(jsonstring),nil)
  344. //Write result to database
  345. sysdb.Write("desktop", username+"/filelocation/"+filename, string(jsonstring))
  346. return nil
  347. }
  348. func delDesktopLocationFromPath(filename string, username string) {
  349. //Delete a file icon location from db
  350. sysdb.Delete("desktop", username+"/filelocation/"+filename)
  351. }
  352. // Return the user information to the client
  353. func desktop_handleUserInfo(w http.ResponseWriter, r *http.Request) {
  354. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  355. if err != nil {
  356. utils.SendErrorResponse(w, err.Error())
  357. return
  358. }
  359. nic, _ := utils.PostPara(r, "noicon")
  360. noicon := (nic == "true")
  361. type PublicUserInfo struct {
  362. Username string
  363. UserIcon string
  364. UserGroups []string
  365. IsAdmin bool
  366. StorageQuotaTotal int64
  367. StorageQuotaLeft int64
  368. }
  369. //Check if the user is requesting another user's public info
  370. targetUser, err := utils.GetPara(r, "target")
  371. if err == nil {
  372. //User asking for another user's desktop icon
  373. userIcon := ""
  374. searchingUser, err := userHandler.GetUserInfoFromUsername(targetUser)
  375. if err != nil {
  376. utils.SendErrorResponse(w, "User not found")
  377. return
  378. }
  379. //Load the profile image
  380. userIcon = searchingUser.GetUserIcon()
  381. js, _ := json.Marshal(PublicUserInfo{
  382. Username: searchingUser.Username,
  383. UserIcon: userIcon,
  384. IsAdmin: searchingUser.IsAdmin(),
  385. })
  386. utils.SendJSONResponse(w, string(js))
  387. return
  388. }
  389. //Calculate the storage quota left
  390. remainingQuota := userinfo.StorageQuota.TotalStorageQuota - userinfo.StorageQuota.UsedStorageQuota
  391. if userinfo.StorageQuota.TotalStorageQuota == -1 {
  392. remainingQuota = -1
  393. }
  394. //Get the list of user permission group names
  395. pgs := []string{}
  396. for _, pg := range userinfo.GetUserPermissionGroup() {
  397. pgs = append(pgs, pg.Name)
  398. }
  399. rs := PublicUserInfo{
  400. Username: userinfo.Username,
  401. UserIcon: userinfo.GetUserIcon(),
  402. IsAdmin: userinfo.IsAdmin(),
  403. UserGroups: pgs,
  404. StorageQuotaTotal: userinfo.StorageQuota.GetUserStorageQuota(),
  405. StorageQuotaLeft: remainingQuota,
  406. }
  407. if noicon {
  408. rs.UserIcon = ""
  409. }
  410. jsonString, _ := json.Marshal(rs)
  411. utils.SendJSONResponse(w, string(jsonString))
  412. }
  413. // Icon handling function for web endpoint
  414. func desktop_fileLocation_handler(w http.ResponseWriter, r *http.Request) {
  415. get, _ := utils.PostPara(r, "get") //Check if there are get request for a given filepath
  416. set, _ := utils.PostPara(r, "set") //Check if there are any set request for a given filepath
  417. del, _ := utils.PostPara(r, "del") //Delete the given filename coordinate
  418. if set != "" {
  419. //Set location with given paramter
  420. x := 0
  421. y := 0
  422. sx, _ := utils.PostPara(r, "x")
  423. sy, _ := utils.PostPara(r, "y")
  424. path := set
  425. x, err := strconv.Atoi(sx)
  426. if err != nil {
  427. x = 0
  428. }
  429. y, err = strconv.Atoi(sy)
  430. if err != nil {
  431. y = 0
  432. }
  433. //Set location of icon from path
  434. username, _ := authAgent.GetUserName(w, r)
  435. err = setDesktopLocationFromPath(path, username, x, y)
  436. if err != nil {
  437. utils.SendErrorResponse(w, err.Error())
  438. return
  439. }
  440. utils.SendJSONResponse(w, string("\"OK\""))
  441. } else if get != "" {
  442. username, _ := authAgent.GetUserName(w, r)
  443. x, y, _ := getDesktopLocatioFromPath(get, username)
  444. result := []int{x, y}
  445. json_string, _ := json.Marshal(result)
  446. utils.SendJSONResponse(w, string(json_string))
  447. } else if del != "" {
  448. username, _ := authAgent.GetUserName(w, r)
  449. delDesktopLocationFromPath(del, username)
  450. } else {
  451. //No argument has been set
  452. utils.SendJSONResponse(w, "Paramter missing.")
  453. }
  454. }
  455. //////////////////////////////// END OF DESKTOP FILE ICON HANDLER ///////////////////////////////////////////////////
  456. func desktop_theme_handler(w http.ResponseWriter, r *http.Request) {
  457. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  458. if err != nil {
  459. utils.SendErrorResponse(w, "User not logged in")
  460. return
  461. }
  462. username := userinfo.Username
  463. //Check if the set GET paramter is set.
  464. targetTheme, _ := utils.GetPara(r, "set")
  465. getUserTheme, _ := utils.GetPara(r, "get")
  466. loadUserTheme, _ := utils.GetPara(r, "load")
  467. if targetTheme == "" && getUserTheme == "" && loadUserTheme == "" {
  468. //List all the currnet themes in the list
  469. themes, err := filepath.Glob("web/img/desktop/bg/*")
  470. if err != nil {
  471. systemWideLogger.PrintAndLog("Desktop", "Unable to search bg from destkop image root. Are you sure the web data folder exists?", err)
  472. return
  473. }
  474. //Prase the results to json array
  475. //Tips: You must use captial letter for varable in struct that is accessable as public :)
  476. type desktopTheme struct {
  477. Theme string
  478. Bglist []string
  479. }
  480. var desktopThemeList []desktopTheme
  481. acceptBGFormats := []string{
  482. ".jpg",
  483. ".png",
  484. ".gif",
  485. }
  486. for _, file := range themes {
  487. if fs.IsDir(file) {
  488. thisTheme := new(desktopTheme)
  489. thisTheme.Theme = filepath.Base(file)
  490. bglist, _ := filepath.Glob(file + "/*")
  491. var thisbglist []string
  492. for _, bg := range bglist {
  493. ext := filepath.Ext(bg)
  494. //if (sliceutil.Contains(acceptBGFormats, ext) ){
  495. if utils.StringInArray(acceptBGFormats, ext) {
  496. //This file extension is supported
  497. thisbglist = append(thisbglist, filepath.Base(bg))
  498. }
  499. }
  500. thisTheme.Bglist = thisbglist
  501. desktopThemeList = append(desktopThemeList, *thisTheme)
  502. }
  503. }
  504. //Return the results as JSON string
  505. jsonString, err := json.Marshal(desktopThemeList)
  506. if err != nil {
  507. systemWideLogger.PrintAndLog("Desktop", "Unable to render desktop wallpaper list", err)
  508. utils.SendJSONResponse(w, string("[]"))
  509. return
  510. }
  511. utils.SendJSONResponse(w, string(jsonString))
  512. return
  513. } else if getUserTheme == "true" {
  514. //Get the user's theme from database
  515. result := ""
  516. sysdb.Read("desktop", username+"/theme", &result)
  517. if result == "" {
  518. //This user has not set a theme yet. Use default
  519. utils.SendJSONResponse(w, string("\"default\""))
  520. return
  521. } else {
  522. //This user already set a theme. Use its set theme
  523. utils.SendJSONResponse(w, string("\""+result+"\""))
  524. return
  525. }
  526. } else if loadUserTheme != "" {
  527. //Load user theme base on folder path
  528. targetFsh, err := userinfo.GetFileSystemHandlerFromVirtualPath(loadUserTheme)
  529. if err != nil {
  530. utils.SendErrorResponse(w, "Unable to resolve user root path")
  531. return
  532. }
  533. fshAbs := targetFsh.FileSystemAbstraction
  534. rpath, err := fshAbs.VirtualPathToRealPath(loadUserTheme, userinfo.Username)
  535. if err != nil {
  536. utils.SendErrorResponse(w, "Custom folder load failed")
  537. return
  538. }
  539. //Check if the folder exists
  540. if !fshAbs.FileExists(rpath) {
  541. utils.SendErrorResponse(w, "Custom folder load failed")
  542. return
  543. }
  544. if !userinfo.CanRead(loadUserTheme) {
  545. //No read permission
  546. utils.SendErrorResponse(w, "Permission denied")
  547. return
  548. }
  549. //Scan for jpg, gif or png
  550. imageList := []string{}
  551. /*
  552. scanPath := filepath.ToSlash(filepath.Clean(rpath)) + "/"
  553. pngFiles, _ := filepath.Glob(scanPath + "*.png")
  554. jpgFiles, _ := filepath.Glob(scanPath + "*.jpg")
  555. gifFiles, _ := filepath.Glob(scanPath + "*.gif")
  556. //Merge all 3 slice into one image list
  557. imageList = append(imageList, pngFiles...)
  558. imageList = append(imageList, jpgFiles...)
  559. imageList = append(imageList, gifFiles...)
  560. */
  561. files, err := fshAbs.ReadDir(rpath)
  562. if err != nil {
  563. utils.SendErrorResponse(w, err.Error())
  564. return
  565. }
  566. for _, file := range files {
  567. ext := filepath.Ext(file.Name())
  568. if utils.StringInArray([]string{".png", ".jpg", ".gif"}, ext) {
  569. imageList = append(imageList, arozfs.ToSlash(filepath.Join(rpath, file.Name())))
  570. }
  571. }
  572. //Convert the image list back to vpaths
  573. virtualImageList := []string{}
  574. for _, image := range imageList {
  575. vpath, err := fshAbs.RealPathToVirtualPath(image, userinfo.Username)
  576. if err != nil {
  577. continue
  578. }
  579. virtualImageList = append(virtualImageList, vpath)
  580. }
  581. js, _ := json.Marshal(virtualImageList)
  582. utils.SendJSONResponse(w, string(js))
  583. } else if targetTheme != "" {
  584. //Set the current user theme
  585. sysdb.Write("desktop", username+"/theme", targetTheme)
  586. utils.SendJSONResponse(w, "\"OK\"")
  587. return
  588. }
  589. }
  590. func desktop_preference_handler(w http.ResponseWriter, r *http.Request) {
  591. preferenceType, _ := utils.PostPara(r, "preference")
  592. value, _ := utils.PostPara(r, "value")
  593. remove, _ := utils.PostPara(r, "remove")
  594. username, err := authAgent.GetUserName(w, r)
  595. if err != nil {
  596. //user not logged in. Redirect to login page.
  597. utils.SendErrorResponse(w, "User not logged in")
  598. return
  599. }
  600. if preferenceType == "" && value == "" {
  601. //Invalid options. Return error reply.
  602. utils.SendErrorResponse(w, "Error. Undefined paramter.")
  603. return
  604. } else if preferenceType != "" && value == "" && remove == "" {
  605. //Getting config from the key.
  606. result := ""
  607. sysdb.Read("desktop", username+"/preference/"+preferenceType, &result)
  608. jsonString, _ := json.Marshal(result)
  609. utils.SendJSONResponse(w, string(jsonString))
  610. return
  611. } else if preferenceType != "" && value == "" && remove == "true" {
  612. //Remove mode
  613. sysdb.Delete("desktop", username+"/preference/"+preferenceType)
  614. utils.SendOK(w)
  615. return
  616. } else if preferenceType != "" && value != "" {
  617. //Setting config from the key
  618. sysdb.Write("desktop", username+"/preference/"+preferenceType, value)
  619. utils.SendOK(w)
  620. return
  621. } else {
  622. utils.SendErrorResponse(w, "Error. Undefined paramter.")
  623. return
  624. }
  625. }
  626. func desktop_shortcutHandler(w http.ResponseWriter, r *http.Request) {
  627. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  628. if err != nil {
  629. //user not logged in. Redirect to login page.
  630. utils.SendErrorResponse(w, "User not logged in")
  631. return
  632. }
  633. shortcutType, err := utils.PostPara(r, "stype")
  634. if err != nil {
  635. utils.SendErrorResponse(w, err.Error())
  636. return
  637. }
  638. shortcutText, err := utils.PostPara(r, "stext")
  639. if err != nil {
  640. utils.SendErrorResponse(w, err.Error())
  641. return
  642. }
  643. shortcutPath, err := utils.PostPara(r, "spath")
  644. if err != nil {
  645. utils.SendErrorResponse(w, err.Error())
  646. return
  647. }
  648. shortcutIcon, err := utils.PostPara(r, "sicon")
  649. if err != nil {
  650. utils.SendErrorResponse(w, err.Error())
  651. return
  652. }
  653. shortcutCreationDest, err := utils.PostPara(r, "sdest")
  654. if err != nil {
  655. //Default create on desktop
  656. shortcutCreationDest = "user:/Desktop/"
  657. }
  658. if !userinfo.CanWrite(shortcutCreationDest) {
  659. utils.SendErrorResponse(w, "Permission denied")
  660. return
  661. }
  662. //Resolve vpath to fsh and subpath
  663. fsh, subpath, err := GetFSHandlerSubpathFromVpath(shortcutCreationDest)
  664. if err != nil {
  665. utils.SendErrorResponse(w, err.Error())
  666. return
  667. }
  668. fshAbs := fsh.FileSystemAbstraction
  669. shorcutRealDest, err := fshAbs.VirtualPathToRealPath(subpath, userinfo.Username)
  670. if err != nil {
  671. utils.SendErrorResponse(w, err.Error())
  672. return
  673. }
  674. //Filter illegal characters in the shortcut filename
  675. shortcutText = arozfs.FilterIllegalCharInFilename(shortcutText, " ")
  676. //If dest not exists, create it
  677. if !fshAbs.FileExists(shorcutRealDest) {
  678. fshAbs.MkdirAll(shorcutRealDest, 0755)
  679. }
  680. //Generate a filename for the shortcut
  681. shortcutFilename := shorcutRealDest + "/" + shortcutText + ".shortcut"
  682. counter := 1
  683. for fshAbs.FileExists(shortcutFilename) {
  684. shortcutFilename = shorcutRealDest + "/" + shortcutText + "(" + strconv.Itoa(counter) + ")" + ".shortcut"
  685. counter++
  686. }
  687. //Write the shortcut to file
  688. shortcutContent := shortcut.GenerateShortcutBytes(shortcutPath, shortcutType, shortcutText, shortcutIcon)
  689. err = fshAbs.WriteFile(shortcutFilename, shortcutContent, 0775)
  690. if err != nil {
  691. utils.SendErrorResponse(w, err.Error())
  692. return
  693. }
  694. utils.SendOK(w)
  695. }