desktop.go 22 KB

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