func (self *Themeset) Load() error { themeNames := make([]string, 0) // build a unique list of theme names from all ThemeDirs for _, iconPath := range self.ThemeDirs { if themeDirs, err := filepath.Glob(path.Join(iconPath, `*`)); err == nil { for _, themeDir := range themeDirs { if stat, err := os.Stat(themeDir); err == nil && stat.IsDir() { name := path.Base(themeDir) if !sliceutil.ContainsString(themeNames, name) { themeNames = append(themeNames, name) } } } } } // assemble and load all themes for _, themeName := range themeNames { theme := NewTheme(themeName) theme.ThemeDirs = self.ThemeDirs if err := theme.Refresh(); err == nil { self.Themes = append(self.Themes, theme) if _, ok := self.themeIndex[theme.InternalName]; !ok { self.themeIndex[theme.InternalName] = theme } } else { continue } } return nil }
func (self *Server) setupTemplateHandler(method string, route *Route) { method = strings.ToUpper(method) endpointPath := route.Path if self.RoutePrefix != `` { endpointPath = fmt.Sprintf("%s/%s", self.RoutePrefix, endpointPath) } log.Debugf("Creating endpoint: %s %s", method, endpointPath) self.router.Handle(method, endpointPath, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { allParams := make(map[string]interface{}) bindingData := make(map[string]interface{}) // evaluate all bindings that this route is attached to routeBindings := self.GetBindings(req, route) // populate data values for evaluated bindings for _, binding := range routeBindings { for k, v := range binding.Params { allParams[k] = v } } payload := map[string]interface{}{ `route`: map[string]interface{}{ `index`: route.Index, `pattern`: route.Path, `path`: endpointPath, }, `request`: map[string]interface{}{ `method`: req.Method, `url`: map[string]interface{}{ `full`: req.URL.String(), `scheme`: req.URL.Scheme, `host`: req.URL.Host, `path`: req.URL.Path, `query`: req.URL.Query(), }, `headers`: req.Header, `protocol`: map[string]interface{}{ `name`: req.Proto, `major`: req.ProtoMajor, `minor`: req.ProtoMinor, }, `length`: req.ContentLength, `remote`: map[string]interface{}{ `address`: req.RemoteAddr, }, }, `params`: allParams, } for key, binding := range routeBindings { if data, err := binding.Evaluate(req, params); err == nil { bindingData[key] = data } else { log.Errorf("Binding '%s' failed to evaluate: %v", key, err) } } payload[`data`] = bindingData protectedKeys := make([]string, 0) for k, _ := range payload { protectedKeys = append(protectedKeys, k) } // add global config payload keys for k, v := range self.Config.Options.Payload { if !sliceutil.ContainsString(protectedKeys, k) { payload[k] = v } } // add external payload keys for k, v := range self.Payload { if !sliceutil.ContainsString(protectedKeys, k) { payload[k] = v } } // add global config headers for name, value := range self.Config.Options.Headers { w.Header().Set(name, value) } // add route config headers for name, value := range route.Headers { w.Header().Set(name, value) } if err := route.Render(w, payload); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }) }
func (self *SessionModule) LoadRoutes(router *httprouter.Router) error { router.GET(`/api/session/workspaces`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if workspaces, err := self.GetAllWorkspaces(); err == nil { util.Respond(w, http.StatusOK, workspaces, nil) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.GET(`/api/session/workspaces/current`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if workspaces, err := self.GetAllWorkspaces(); err == nil { for _, workspace := range workspaces { if workspace.IsCurrent { util.Respond(w, http.StatusOK, workspace, nil) return } } util.Respond(w, http.StatusNotFound, nil, fmt.Errorf("Current workspace not found")) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.GET(`/api/session/windows`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if windows, err := self.GetAllWindows(); err == nil { for i, _ := range windows { windows[i].IconUri = fmt.Sprintf("/api/session/windows/%d/icon", windows[i].ID) } util.Respond(w, http.StatusOK, windows, nil) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.GET(`/api/session/windows/:id`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if window, err := self.GetWindow(params.ByName(`id`)); err == nil { window.IconUri = fmt.Sprintf("/api/session/windows/%s/icon", params.ByName(`id`)) util.Respond(w, http.StatusOK, window, nil) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.GET(`/api/session/windows/:id/icon`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { var buffer bytes.Buffer width := uint(16) height := uint(16) if w := req.URL.Query().Get(`w`); w != `` { if value, err := stringutil.ConvertToInteger(w); err == nil { width = uint(value) } } if h := req.URL.Query().Get(`h`); h != `` { if value, err := stringutil.ConvertToInteger(h); err == nil { height = uint(value) } } if height != width { height = width } if err := self.WriteWindowIcon(params.ByName(`id`), width, height, &buffer); err == nil { w.Header().Set(`Content-Type`, `image/png`) w.Write(buffer.Bytes()) return } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.GET(`/api/session/windows/:id/image`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { var buffer bytes.Buffer if err := self.WriteWindowImage(params.ByName(`id`), &buffer); err == nil { w.Header().Set(`Content-Type`, `image/png`) w.Write(buffer.Bytes()) return } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.PUT(`/api/session/windows/:id/do/:action`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { var err error id := params.ByName(`id`) switch params.ByName(`action`) { case `maximize`: err = self.MaximizeWindow(id) case `max-x`: err = self.MaximizeWindowHorizontal(id) case `max-y`: err = self.MaximizeWindowVertical(id) case `minimize`: err = self.MinimizeWindow(id) case `restore`: err = self.RestoreWindow(id) case `hide`: err = self.HideWindow(id) case `show`: err = self.ShowWindow(id) case `raise`: err = self.RaiseWindow(id) default: util.Respond(w, http.StatusBadRequest, nil, fmt.Errorf("Unknown action '%s'", params.ByName(`action`))) return } if err == nil { util.Respond(w, http.StatusAccepted, nil, nil) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.PUT(`/api/session/windows/:id/move/:x/:y`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { id := params.ByName(`id`) var x, y int if value, err := stringutil.ConvertToInteger(params.ByName(`x`)); err == nil { x = int(value) } else { util.Respond(w, http.StatusBadRequest, nil, err) return } if value, err := stringutil.ConvertToInteger(params.ByName(`y`)); err == nil { y = int(value) } else { util.Respond(w, http.StatusBadRequest, nil, err) return } if err := self.MoveWindow(id, x, y); err == nil { util.Respond(w, http.StatusAccepted, nil, nil) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.PUT(`/api/session/windows/:id/resize/:x/:y`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { id := params.ByName(`id`) var width, height uint if value, err := stringutil.ConvertToInteger(params.ByName(`width`)); err == nil { width = uint(value) } else { util.Respond(w, http.StatusBadRequest, nil, err) return } if value, err := stringutil.ConvertToInteger(params.ByName(`height`)); err == nil { height = uint(value) } else { util.Respond(w, http.StatusBadRequest, nil, err) return } if err := self.ResizeWindow(id, width, height); err == nil { util.Respond(w, http.StatusAccepted, nil, nil) } else { util.Respond(w, http.StatusInternalServerError, nil, err) } }) router.GET(`/api/session/applications`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { keys := make([]string, 0) for key, _ := range self.Applications.Entries { keys = append(keys, key) } sort.Strings(keys) util.Respond(w, http.StatusOK, keys, nil) }) router.GET(`/api/session/applications/:name`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { key := params.ByName(`name`) if app, ok := self.Applications.Entries[key]; ok { util.Respond(w, http.StatusOK, app, nil) } else { util.Respond(w, http.StatusNotFound, nil, fmt.Errorf("Could not locate application '%s'", key)) } }) router.GET(`/api/session/icons/list/:type`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { var filterMinSize, filterMaxSize int rv := make([]string, 0) listType := params.ByName(`type`) // filters filterThemes := strings.Split(req.URL.Query().Get(`themes`), `,`) filterIconContextTypes := strings.Split(req.URL.Query().Get(`contexts`), `,`) filterIconFileTypes := strings.Split(req.URL.Query().Get(`filetypes`), `,`) filterMinSizeS := req.URL.Query().Get(`minsize`) filterMaxSizeS := req.URL.Query().Get(`maxsize`) filterIsScalable := req.URL.Query().Get(`scalable`) if filterMinSizeS != `` { if v, err := stringutil.ConvertToInteger(filterMinSizeS); err == nil { filterMinSize = int(v) } else { util.Respond(w, http.StatusBadRequest, nil, err) return } } if filterMaxSizeS != `` { if v, err := stringutil.ConvertToInteger(filterMaxSizeS); err == nil { filterMaxSize = int(v) } else { util.Respond(w, http.StatusBadRequest, nil, err) return } } for _, theme := range self.Themeset.Themes { if len(filterThemes) > 0 && filterThemes[0] != `` { if !sliceutil.ContainsString(filterThemes, strings.ToLower(theme.InternalName)) { inInherited := false for _, inheritedThemeName := range theme.Inherits { if sliceutil.ContainsString(filterThemes, strings.ToLower(inheritedThemeName)) { inInherited = true break } } if !inInherited { continue } } } switch listType { case `themes`: if !sliceutil.ContainsString(rv, theme.Name) { rv = append(rv, theme.InternalName) } default: for _, icon := range theme.Icons { // filter context types if len(filterIconContextTypes) > 0 && filterIconContextTypes[0] != `` { if !sliceutil.ContainsString(filterIconContextTypes, strings.ToLower(icon.Context.Name)) { continue } } // filter icon filetypes if len(filterIconFileTypes) > 0 && filterIconFileTypes[0] != `` { if !sliceutil.ContainsString(filterIconFileTypes, icon.Type) { continue } } // filter icon size contraints if filterMinSize > 0 && icon.Context.MinSize < filterMinSize { continue } if filterMaxSize > 0 && icon.Context.MaxSize > filterMaxSize { continue } // filter for scalable/non-scalable icons if filterIsScalable == `true` && icon.Context.Type != icons.IconContextScalable { continue } else if filterIsScalable == `false` && icon.Context.Type == icons.IconContextScalable { continue } var value string switch listType { case `names`: value = icon.Name case `contexts`: value = strings.ToLower(icon.Context.Name) case `display-names`: value = icon.DisplayName case `sizes`: if v, err := stringutil.ToString(icon.Context.Size); err == nil { value = v } default: util.Respond(w, http.StatusBadRequest, nil, fmt.Errorf("Unrecognized list type '%s'", listType)) return } if value != `` { if !sliceutil.ContainsString(rv, value) { rv = append(rv, value) } } } } } sort.Strings(rv) util.Respond(w, http.StatusOK, rv, nil) }) router.GET(`/api/session/icons/view/:name/size/:size`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { var iconSize int iconNames := strings.Split(params.ByName(`name`), `,`) iconSizeS := params.ByName(`size`) themeName := req.URL.Query().Get(`theme`) if themeName == `` { themeName = self.Themeset.DefaultTheme } if v, err := stringutil.ConvertToInteger(iconSizeS); err == nil { iconSize = int(v) var icon *icons.Icon switch req.URL.Query().Get(`mode`) { case `hicolor-first`: if hiColorIcon, ok := self.Themeset.FindIconViaTheme(`hicolor`, iconNames, iconSize); ok { icon = hiColorIcon } else if themeIcon, ok := self.Themeset.FindIconViaTheme(themeName, iconNames, iconSize); ok { icon = themeIcon } default: if themeIcon, ok := self.Themeset.FindIconViaTheme(themeName, iconNames, iconSize); ok { icon = themeIcon } } if icon != nil { var contentType string switch icon.Type { case `png`: contentType = `image/png` case `svg`: contentType = `image/svg+xml` default: util.Respond(w, http.StatusBadRequest, nil, fmt.Errorf("Unsupported icon type '%s'", icon.Type)) return } defer icon.Close() if data, err := ioutil.ReadAll(icon); err == nil { w.Header().Set(`Content-Type`, contentType) w.Write(data) } else { util.Respond(w, http.StatusBadRequest, nil, err) } } else { util.Respond(w, http.StatusNotFound, nil, fmt.Errorf("Could not locate icon")) } } else { util.Respond(w, http.StatusBadRequest, nil, err) } }) // router.GET(`/api/session/applications/find/:pattern`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { // }) router.PUT(`/api/session/applications/:name/launch`, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { if err := self.Applications.LaunchEntry(params.ByName(`name`)); err == nil { util.Respond(w, http.StatusAccepted, nil, nil) } else { util.Respond(w, http.StatusNotFound, nil, err) } }) return nil }