コード例 #1
0
ファイル: editors.go プロジェクト: ForeverAct/wide
func setCmdEnv(cmd *exec.Cmd, username string) {
	userWorkspace := conf.GetUserWorkspace(username)

	cmd.Env = append(cmd.Env,
		"GOPATH="+userWorkspace,
		"GOOS="+runtime.GOOS,
		"GOARCH="+runtime.GOARCH,
		"GOROOT="+runtime.GOROOT(),
		"PATH="+os.Getenv("PATH"))
}
コード例 #2
0
ファイル: files.go プロジェクト: azureplus/wide
// FindHandler handles request of find files under the specified directory with the specified filename pattern.
func FindHandler(w http.ResponseWriter, r *http.Request) {
	httpSession, _ := session.HTTPSession.Get(r, "wide-session")
	if httpSession.IsNew {
		http.Error(w, "Forbidden", http.StatusForbidden)

		return
	}
	username := httpSession.Values["username"].(string)

	result := util.NewResult()
	defer util.RetResult(w, r, result)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		result.Succ = false

		return
	}

	path := args["path"].(string) // path of selected file in file tree
	if !util.Go.IsAPI(path) && !session.CanAccess(username, path) {
		http.Error(w, "Forbidden", http.StatusForbidden)

		return
	}

	name := args["name"].(string)

	userWorkspace := conf.GetUserWorkspace(username)
	workspaces := filepath.SplitList(userWorkspace)

	if "" != path && !util.File.IsDir(path) {
		path = filepath.Dir(path)
	}

	founds := foundPaths{}

	for _, workspace := range workspaces {
		rs := find(workspace+conf.PathSeparator+"src", name, []*string{})

		for _, r := range rs {
			substr := util.Str.LCS(path, *r)

			founds = append(founds, &foundPath{Path: filepath.ToSlash(*r), score: len(substr)})
		}
	}

	sort.Sort(founds)

	result.Data = founds
}
コード例 #3
0
ファイル: users.go プロジェクト: toyang/wide
// CanAccess determines whether the user specified by the given username can access the specified path.
func CanAccess(username, path string) bool {
	path = filepath.FromSlash(path)

	userWorkspace := conf.GetUserWorkspace(username)
	workspaces := filepath.SplitList(userWorkspace)

	for _, workspace := range workspaces {
		if strings.HasPrefix(path, workspace) {
			return true
		}
	}

	return false
}
コード例 #4
0
ファイル: files.go プロジェクト: azureplus/wide
// SearchTextHandler handles request of searching files under the specified directory with the specified keyword.
func SearchTextHandler(w http.ResponseWriter, r *http.Request) {
	httpSession, _ := session.HTTPSession.Get(r, "wide-session")
	if httpSession.IsNew {
		http.Error(w, "Forbidden", http.StatusForbidden)

		return
	}

	result := util.NewResult()
	defer util.RetResult(w, r, result)

	var args map[string]interface{}

	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		result.Succ = false

		return
	}

	sid := args["sid"].(string)
	wSession := session.WideSessions.Get(sid)
	if nil == wSession {
		result.Succ = false

		return
	}

	// XXX: just one directory

	dir := args["dir"].(string)
	if "" == dir {
		userWorkspace := conf.GetUserWorkspace(wSession.Username)
		workspaces := filepath.SplitList(userWorkspace)
		dir = workspaces[0]
	}

	extension := args["extension"].(string)
	text := args["text"].(string)

	founds := []*Snippet{}
	if util.File.IsDir(dir) {
		founds = search(dir, extension, text, []*Snippet{})
	} else {
		founds = searchInFile(dir, text)
	}

	result.Data = founds
}
コード例 #5
0
ファイル: outputs.go プロジェクト: EricRobert/wide
func setCmdEnv(cmd *exec.Cmd, username string) {
	userWorkspace := conf.GetUserWorkspace(username)

	cmd.Env = append(cmd.Env,
		"GOPATH="+userWorkspace,
		"GOOS="+runtime.GOOS,
		"GOARCH="+runtime.GOARCH,
		"GOROOT="+runtime.GOROOT(),
		"PATH="+os.Getenv("PATH"))

	if util.OS.IsWindows() {
		// FIXME: for some weird issues on Windows, such as: The requested service provider could not be loaded or initialized.
		cmd.Env = append(cmd.Env, os.Environ()...)
	}
}
コード例 #6
0
ファイル: files.go プロジェクト: azureplus/wide
// GetFilesHandler handles request of constructing user workspace file tree.
//
// The Go API source code package also as a child node,
// so that users can easily view the Go API source code in file tree.
func GetFilesHandler(w http.ResponseWriter, r *http.Request) {
	httpSession, _ := session.HTTPSession.Get(r, "wide-session")
	if httpSession.IsNew {
		http.Error(w, "Forbidden", http.StatusForbidden)

		return
	}
	username := httpSession.Values["username"].(string)

	result := util.NewResult()
	defer util.RetGzResult(w, r, result)

	userWorkspace := conf.GetUserWorkspace(username)
	workspaces := filepath.SplitList(userWorkspace)

	root := Node{Name: "root", Path: "", IconSkin: "ico-ztree-dir ", Type: "d", IsParent: true, Children: []*Node{}}

	if nil == apiNode { // lazy init
		initAPINode()
	}

	// workspace node process
	for _, workspace := range workspaces {
		workspacePath := workspace + conf.PathSeparator + "src"

		workspaceNode := Node{
			Id:        filepath.ToSlash(workspacePath), // jQuery API can't accept "\", so we convert it to "/"
			Name:      workspace[strings.LastIndex(workspace, conf.PathSeparator)+1:],
			Path:      filepath.ToSlash(workspacePath),
			IconSkin:  "ico-ztree-dir-workspace ",
			Type:      "d",
			Creatable: true,
			Removable: false,
			IsGoAPI:   false,
			Children:  []*Node{}}

		walk(workspacePath, &workspaceNode, true, true, false)

		// add workspace node
		root.Children = append(root.Children, &workspaceNode)
	}

	// add Go API node
	root.Children = append(root.Children, apiNode)

	result.Data = root
}
コード例 #7
0
ファイル: files.go プロジェクト: EricRobert/wide
func authWorkspace(username, path string) bool {
	path = filepath.FromSlash(path)

	if strings.HasPrefix(path, util.Go.GetAPIPath()) {
		return true
	}

	userWorkspace := conf.GetUserWorkspace(username)
	workspaces := filepath.SplitList(userWorkspace)

	for _, workspace := range workspaces {
		if strings.HasPrefix(path, workspace) {
			return true
		}
	}

	return false
}
コード例 #8
0
ファイル: users.go プロジェクト: toyang/wide
// addUser add a user with the specified username, password and email.
//
//  1. create the user's workspace
//  2. generate 'Hello, 世界' demo code in the workspace (a console version and a HTTP version)
//  3. update the user customized configurations, such as style.css
//  4. serve files of the user's workspace via HTTP
//
// Note: user [playground] is a reserved mock user
func addUser(username, password, email string) string {
	if !conf.Wide.AllowRegister {
		return notAllowRegister
	}

	if "playground" == username {
		return userExists
	}

	addUserMutex.Lock()
	defer addUserMutex.Unlock()

	for _, user := range conf.Users {
		if strings.ToLower(user.Name) == strings.ToLower(username) {
			return userExists
		}

		if strings.ToLower(user.Email) == strings.ToLower(email) {
			return emailExists
		}
	}

	firstUserWorkspace := conf.GetUserWorkspace(conf.Users[0].Name)
	dir := filepath.Dir(firstUserWorkspace)
	workspace := filepath.Join(dir, username)

	newUser := conf.NewUser(username, password, email, workspace)
	conf.Users = append(conf.Users, newUser)

	if !newUser.Save() {
		return userCreateError
	}

	conf.CreateWorkspaceDir(workspace)
	helloWorld(workspace)
	conf.UpdateCustomizedConf(username)

	http.Handle("/workspace/"+username+"/",
		http.StripPrefix("/workspace/"+username+"/", http.FileServer(http.Dir(newUser.GetWorkspace()))))

	logger.Infof("Created a user [%s]", username)

	return userCreated
}
コード例 #9
0
ファイル: main.go プロジェクト: toyang/wide
// startHandler handles request of start page.
func startHandler(w http.ResponseWriter, r *http.Request) {
	httpSession, _ := session.HTTPSession.Get(r, "wide-session")
	if httpSession.IsNew {
		http.Redirect(w, r, conf.Wide.Context+"login", http.StatusFound)

		return
	}

	httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
	if "" != conf.Wide.Context {
		httpSession.Options.Path = conf.Wide.Context
	}
	httpSession.Save(r, w)

	username := httpSession.Values["username"].(string)
	locale := conf.GetUser(username).Locale
	userWorkspace := conf.GetUserWorkspace(username)

	sid := r.URL.Query()["sid"][0]
	wSession := session.WideSessions.Get(sid)
	if nil == wSession {
		logger.Errorf("Session [%s] not found", sid)
	}

	model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
		"username": username, "workspace": userWorkspace, "ver": conf.WideVersion, "sid": sid}

	t, err := template.ParseFiles("views/start.html")

	if nil != err {
		logger.Error(err)
		http.Error(w, err.Error(), 500)

		return
	}

	t.Execute(w, model)
}
コード例 #10
0
ファイル: sessions.go プロジェクト: EricRobert/wide
// New creates a wide session.
func (sessions *wSessions) New(httpSession *sessions.Session, sid string) *WideSession {
	mutex.Lock()
	defer mutex.Unlock()

	username := httpSession.Values["username"].(string)
	now := time.Now()

	ret := &WideSession{
		ID:          sid,
		Username:    username,
		HTTPSession: httpSession,
		EventQueue:  nil,
		State:       sessionStateActive,
		Content:     &conf.LatestSessionContent{},
		Created:     now,
		Updated:     now,
	}

	*sessions = append(*sessions, ret)

	if "playground" == username {
		return ret
	}

	// create user event queue
	ret.EventQueue = event.UserEventQueues.New(sid)

	// add a filesystem watcher to notify front-end after the files changed
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		logger.Error(err)

		return ret
	}

	go func() {
		defer util.Recover()

		workspaces := filepath.SplitList(conf.GetUserWorkspace(username))
		for _, workspace := range workspaces {
			filepath.Walk(filepath.Join(workspace, "src"), func(dirPath string, f os.FileInfo, err error) error {
				if ".git" == f.Name() { // XXX: discard other unconcered dirs
					return filepath.SkipDir
				}

				if f.IsDir() {
					if err = watcher.Add(dirPath); nil != err {
						logger.Error(err, dirPath)
					}

					logger.Tracef("Added a file watcher [%s]", dirPath)
				}

				return nil
			})

		}

		ret.FileWatcher = watcher
	}()

	go func() {
		defer util.Recover()

		for {
			ch := SessionWS[sid]
			if nil == ch {
				return // release this gorutine
			}

			select {
			case event := <-watcher.Events:
				path := event.Name
				dir := filepath.Dir(path)

				ch = SessionWS[sid]
				if nil == ch {
					return // release this gorutine
				}

				if event.Op&fsnotify.Create == fsnotify.Create {
					if err = watcher.Add(path); nil != err {
						logger.Warn(err, path)
					}

					logger.Tracef("Added a file watcher [%s]", path)

					cmd := map[string]interface{}{"path": path, "dir": dir, "cmd": "create-file"}
					ch.WriteJSON(&cmd)
				} else if event.Op&fsnotify.Remove == fsnotify.Remove {
					cmd := map[string]interface{}{"path": path, "dir": dir, "cmd": "remove-file"}
					ch.WriteJSON(&cmd)

				} else if event.Op&fsnotify.Rename == fsnotify.Rename {
					cmd := map[string]interface{}{"path": path, "dir": dir, "cmd": "rename-file"}
					ch.WriteJSON(&cmd)
				}
			case err := <-watcher.Errors:
				if nil != err {
					logger.Error("File watcher ERROR: ", err)
				}
			}
		}
	}()

	return ret
}
コード例 #11
0
ファイル: users.go プロジェクト: toyang/wide
// SignUpUserHandler handles request of registering user.
func SignUpUserHandler(w http.ResponseWriter, r *http.Request) {
	if "GET" == r.Method {
		// show the user sign up page

		firstUserWorkspace := conf.GetUserWorkspace(conf.Users[0].Name)
		dir := filepath.Dir(firstUserWorkspace)

		model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(conf.Wide.Locale),
			"locale": conf.Wide.Locale, "ver": conf.WideVersion, "dir": dir,
			"pathSeparator": conf.PathSeparator, "year": time.Now().Year()}

		t, err := template.ParseFiles("views/sign_up.html")

		if nil != err {
			logger.Error(err)
			http.Error(w, err.Error(), 500)

			return
		}

		t.Execute(w, model)

		return
	}

	// non-GET request as add user request

	result := util.NewResult()
	defer util.RetResult(w, r, result)

	var args map[string]interface{}

	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		result.Succ = false

		return
	}

	username := args["username"].(string)
	password := args["password"].(string)
	email := args["email"].(string)

	msg := addUser(username, password, email)
	if userCreated != msg {
		result.Succ = false
		result.Msg = msg

		return
	}

	// create a HTTP session
	httpSession, _ := HTTPSession.Get(r, "wide-session")
	httpSession.Values["username"] = username
	httpSession.Values["id"] = strconv.Itoa(rand.Int())
	httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
	if "" != conf.Wide.Context {
		httpSession.Options.Path = conf.Wide.Context
	}
	httpSession.Save(r, w)
}
コード例 #12
0
ファイル: editors.go プロジェクト: ForeverAct/wide
// AutocompleteHandler handles request of code autocompletion.
func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
	var args map[string]interface{}

	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		logger.Error(err)
		http.Error(w, err.Error(), 500)

		return
	}

	session, _ := session.HTTPSession.Get(r, "wide-session")
	if session.IsNew {
		http.Error(w, "Forbidden", http.StatusForbidden)

		return
	}
	username := session.Values["username"].(string)

	path := args["path"].(string)

	fout, err := os.Create(path)

	if nil != err {
		logger.Error(err)
		http.Error(w, err.Error(), 500)

		return
	}

	code := args["code"].(string)
	fout.WriteString(code)

	if err := fout.Close(); nil != err {
		logger.Error(err)
		http.Error(w, err.Error(), 500)

		return
	}

	line := int(args["cursorLine"].(float64))
	ch := int(args["cursorCh"].(float64))

	offset := getCursorOffset(code, line, ch)

	logger.Tracef("offset: %d", offset)

	userWorkspace := conf.GetUserWorkspace(username)
	workspaces := filepath.SplitList(userWorkspace)
	libPath := ""
	for _, workspace := range workspaces {
		userLib := workspace + conf.PathSeparator + "pkg" + conf.PathSeparator +
			runtime.GOOS + "_" + runtime.GOARCH
		libPath += userLib + conf.PathListSeparator
	}

	logger.Tracef("gocode set lib-path [%s]", libPath)

	// FIXME: using gocode set lib-path has some issues while accrossing workspaces
	gocode := util.Go.GetExecutableInGOBIN("gocode")
	exec.Command(gocode, []string{"set", "lib-path", libPath}...).Run()

	argv := []string{"-f=json", "--in=" + path, "autocomplete", strconv.Itoa(offset)}
	cmd := exec.Command(gocode, argv...)

	output, err := cmd.CombinedOutput()
	if nil != err {
		logger.Error(err)
		http.Error(w, err.Error(), 500)

		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(output)
}