desktop.go 20 KB

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