desktop.go 22 KB

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