This commit is contained in:
Liang Ding 2019-05-17 00:41:52 +08:00
parent 003354ffe4
commit 5989d0fb7b
No known key found for this signature in database
GPG Key ID: 136F30F901A2231D
26 changed files with 378 additions and 481 deletions

View File

@ -57,13 +57,8 @@ func main() {
// Configuration. // Configuration.
type conf struct { type conf struct {
IP string // server ip, ${ip} Server string // server
Port string // server port
Context string // server context
Server string // server host and port ({IP}:{Port})
StaticServer string // static resources server scheme, host and port (http://{IP}:{Port})
LogLevel string // logging level: trace/debug/info/warn/error LogLevel string // logging level: trace/debug/info/warn/error
Channel string // channel (ws://{IP}:{Port})
HTTPSessionMaxAge int // HTTP session max age (in seciond) HTTPSessionMaxAge int // HTTP session max age (in seciond)
StaticResourceVersion string // version of static resources StaticResourceVersion string // version of static resources
MaxProcs int // Go max procs MaxProcs int // Go max procs
@ -93,8 +88,8 @@ var Docker bool
const DockerImageGo = "golang" const DockerImageGo = "golang"
// Load loads the Wide configurations from wide.json and users' configurations from users/{userId}.json. // Load loads the Wide configurations from wide.json and users' configurations from users/{userId}.json.
func Load(confPath, confUsers, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel, confPlayground string, confUsersWorkspaces string) { func Load(confPath, confUsers, confServer, confLogLevel, confPlayground string, confUsersWorkspaces string) {
initWide(confPath, confUsers, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel, confPlayground, confUsersWorkspaces) initWide(confPath, confUsers, confServer, confLogLevel, confPlayground, confUsersWorkspaces)
initUsers() initUsers()
cmd := exec.Command("docker", "version") cmd := exec.Command("docker", "version")
@ -168,7 +163,7 @@ func initUsers() {
initCustomizedConfs() initCustomizedConfs()
} }
func initWide(confPath, confUsers, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel, confPlayground string, confUsersWorkspaces string) { func initWide(confPath, confUsers, confServer, confLogLevel, confPlayground string, confUsersWorkspaces string) {
bytes, err := ioutil.ReadFile(confPath) bytes, err := ioutil.ReadFile(confPath)
if nil != err { if nil != err {
logger.Error(err) logger.Error(err)
@ -236,54 +231,14 @@ func initWide(confPath, confUsers, confIP, confPort, confServer, confLogLevel, c
} }
} }
// IP
if "" != confIP {
Wide.IP = confIP
} else {
ip, err := util.Net.LocalIP()
if nil != err {
logger.Error(err)
os.Exit(-1)
}
logger.Debugf("${ip} [%s]", ip)
Wide.IP = strings.Replace(Wide.IP, "${ip}", ip, 1)
}
if "" != confPort {
Wide.Port = confPort
}
// Server // Server
Wide.Server = strings.Replace(Wide.Server, "{IP}", Wide.IP, 1)
Wide.Server = strings.Replace(Wide.Server, "{Port}", Wide.Port, 1)
if "" != confServer { if "" != confServer {
Wide.Server = confServer Wide.Server = confServer
} }
// Static Server
Wide.StaticServer = strings.Replace(Wide.StaticServer, "{IP}", Wide.IP, 1)
Wide.StaticServer = strings.Replace(Wide.StaticServer, "{Port}", Wide.Port, 1)
if "" != confStaticServer {
Wide.StaticServer = confStaticServer
}
// Context
if "" != confContext {
Wide.Context = confContext
}
time := strconv.FormatInt(time.Now().UnixNano(), 10) time := strconv.FormatInt(time.Now().UnixNano(), 10)
logger.Debugf("${time} [%s]", time) logger.Debugf("${time} [%s]", time)
Wide.StaticResourceVersion = strings.Replace(Wide.StaticResourceVersion, "${time}", time, 1) Wide.StaticResourceVersion = strings.Replace(Wide.StaticResourceVersion, "${time}", time, 1)
// Channel
Wide.Channel = strings.Replace(Wide.Channel, "{IP}", Wide.IP, 1)
Wide.Channel = strings.Replace(Wide.Channel, "{Port}", Wide.Port, 1)
if "" != confChannel {
Wide.Channel = confChannel
}
} }
// FixedTimeCheckEnv checks Wide runtime enviorment periodically (7 minutes). // FixedTimeCheckEnv checks Wide runtime enviorment periodically (7 minutes).

View File

@ -1,11 +1,6 @@
{ {
"IP": "${ip}", "Server": "http://127.0.0.1:7070",
"Port": "7070",
"Context": "",
"Server": "{IP}:{Port}",
"StaticServer": "",
"LogLevel": "debug", "LogLevel": "debug",
"Channel": "ws://{IP}:{Port}",
"HTTPSessionMaxAge": 86400, "HTTPSessionMaxAge": 86400,
"StaticResourceVersion": "${time}", "StaticResourceVersion": "${time}",
"MaxProcs": 4, "MaxProcs": 4,

View File

@ -41,7 +41,7 @@ var logger = log.NewLogger(os.Stdout)
// WSHandler handles request of creating editor channel. // WSHandler handles request of creating editor channel.
// XXX: NOT used at present // XXX: NOT used at present
func WSHandler(w http.ResponseWriter, r *http.Request) { func WSHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -111,7 +111,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -182,7 +182,7 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
uid := session.Values["uid"].(string) uid := session.Values["uid"].(string)
var args map[string]interface{} var args map[string]interface{}
@ -253,7 +253,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -341,7 +341,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -34,7 +34,7 @@ func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -74,7 +74,7 @@ func initAPINode() {
// The Go API source code package also as a child node, // 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. // so that users can easily view the Go API source code in file tree.
func GetFilesHandler(w http.ResponseWriter, r *http.Request) { func GetFilesHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -123,7 +123,7 @@ func GetFilesHandler(w http.ResponseWriter, r *http.Request) {
// RefreshDirectoryHandler handles request of refresh a directory of file tree. // RefreshDirectoryHandler handles request of refresh a directory of file tree.
func RefreshDirectoryHandler(w http.ResponseWriter, r *http.Request) { func RefreshDirectoryHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -156,7 +156,7 @@ func RefreshDirectoryHandler(w http.ResponseWriter, r *http.Request) {
// GetFileHandler handles request of opening file by editor. // GetFileHandler handles request of opening file by editor.
func GetFileHandler(w http.ResponseWriter, r *http.Request) { func GetFileHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -232,7 +232,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
// SaveFileHandler handles request of saving file. // SaveFileHandler handles request of saving file.
func SaveFileHandler(w http.ResponseWriter, r *http.Request) { func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -288,7 +288,7 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
// NewFileHandler handles request of creating file or directory. // NewFileHandler handles request of creating file or directory.
func NewFileHandler(w http.ResponseWriter, r *http.Request) { func NewFileHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -340,7 +340,7 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
// RemoveFileHandler handles request of removing file or directory. // RemoveFileHandler handles request of removing file or directory.
func RemoveFileHandler(w http.ResponseWriter, r *http.Request) { func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -386,7 +386,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
// RenameFileHandler handles request of renaming file or directory. // RenameFileHandler handles request of renaming file or directory.
func RenameFileHandler(w http.ResponseWriter, r *http.Request) { func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -451,7 +451,7 @@ func (f foundPaths) Less(i, j int) bool { return f[i].score > f[j].score }
// FindHandler handles request of find files under the specified directory with the specified filename pattern. // FindHandler handles request of find files under the specified directory with the specified filename pattern.
func FindHandler(w http.ResponseWriter, r *http.Request) { func FindHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -505,7 +505,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
// SearchTextHandler handles request of searching files under the specified directory with the specified keyword. // SearchTextHandler handles request of searching files under the specified directory with the specified keyword.
func SearchTextHandler(w http.ResponseWriter, r *http.Request) { func SearchTextHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

150
main.go
View File

@ -49,13 +49,8 @@ var logger *log.Logger
func init() { func init() {
confPath := flag.String("conf", "conf/wide.json", "path of wide.json") confPath := flag.String("conf", "conf/wide.json", "path of wide.json")
confUsers := flag.String("users", "conf/users", "path of users") confUsers := flag.String("users", "conf/users", "path of users")
confIP := flag.String("ip", "", "this will overwrite Wide.IP if specified")
confPort := flag.String("port", "", "this will overwrite Wide.Port if specified")
confServer := flag.String("server", "", "this will overwrite Wide.Server if specified") confServer := flag.String("server", "", "this will overwrite Wide.Server if specified")
confLogLevel := flag.String("log_level", "", "this will overwrite Wide.LogLevel if specified") confLogLevel := flag.String("log_level", "", "this will overwrite Wide.LogLevel if specified")
confStaticServer := flag.String("static_server", "", "this will overwrite Wide.StaticServer if specified")
confContext := flag.String("context", "", "this will overwrite Wide.Context if specified")
confChannel := flag.String("channel", "", "this will overwrite Wide.Channel if specified")
confStat := flag.Bool("stat", false, "whether report statistics periodically") confStat := flag.Bool("stat", false, "whether report statistics periodically")
confPlayground := flag.String("playground", "", "this will overwrite Wide.Playground if specified") confPlayground := flag.String("playground", "", "this will overwrite Wide.Playground if specified")
confUsersWorkspaces := flag.String("users_workspaces", "", "this will overwrite Wide.UsersWorkspaces if specified") confUsersWorkspaces := flag.String("users_workspaces", "", "this will overwrite Wide.UsersWorkspaces if specified")
@ -74,7 +69,7 @@ func init() {
i18n.Load() i18n.Load()
event.Load() event.Load()
conf.Load(*confPath, *confUsers, *confIP, *confPort, *confServer, *confLogLevel, *confStaticServer, *confContext, *confChannel, *confPlayground, *confUsersWorkspaces) conf.Load(*confPath, *confUsers, *confServer, *confLogLevel, *confPlayground, *confUsersWorkspaces)
conf.FixedTimeCheckEnv() conf.FixedTimeCheckEnv()
session.FixedTimeSave() session.FixedTimeSave()
@ -95,86 +90,91 @@ func main() {
handleSignal() handleSignal()
// IDE // IDE
http.HandleFunc(conf.Wide.Context+"/", handlerGzWrapper(indexHandler)) http.HandleFunc("/", handlerGzWrapper(indexHandler))
http.HandleFunc(conf.Wide.Context+"/start", handlerWrapper(startHandler)) http.HandleFunc("/start", handlerWrapper(startHandler))
http.HandleFunc(conf.Wide.Context+"/about", handlerWrapper(aboutHandler)) http.HandleFunc("/about", handlerWrapper(aboutHandler))
http.HandleFunc(conf.Wide.Context+"/keyboard_shortcuts", handlerWrapper(keyboardShortcutsHandler)) http.HandleFunc("/keyboard_shortcuts", handlerWrapper(keyboardShortcutsHandler))
// static resources // static resources
http.Handle(conf.Wide.Context+"/static/", http.StripPrefix(conf.Wide.Context+"/static/", http.FileServer(http.Dir("static")))) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
serveSingle("/favicon.ico", "./static/favicon.ico") serveSingle("/favicon.ico", "./static/favicon.ico")
// oauth
http.HandleFunc("/oauth/github", session.RedirectGitHubHandler)
http.HandleFunc("/oauth/github/callback", session.GithubCallbackHandler)
// workspaces // workspaces
for _, user := range conf.Users { for _, user := range conf.Users {
http.Handle(conf.Wide.Context+"/workspace/"+user.Name+"/", http.Handle("/workspace/"+user.Name+"/",
http.StripPrefix(conf.Wide.Context+"/workspace/"+user.Name+"/", http.FileServer(http.Dir(user.WorkspacePath())))) http.StripPrefix("/workspace/"+user.Name+"/", http.FileServer(http.Dir(user.WorkspacePath()))))
} }
// session // session
http.HandleFunc(conf.Wide.Context+"/session/ws", handlerWrapper(session.WSHandler)) http.HandleFunc("/session/ws", handlerWrapper(session.WSHandler))
http.HandleFunc(conf.Wide.Context+"/session/save", handlerWrapper(session.SaveContentHandler)) http.HandleFunc("/session/save", handlerWrapper(session.SaveContentHandler))
// run // run
http.HandleFunc(conf.Wide.Context+"/build", handlerWrapper(output.BuildHandler)) http.HandleFunc("/build", handlerWrapper(output.BuildHandler))
http.HandleFunc(conf.Wide.Context+"/run", handlerWrapper(output.RunHandler)) http.HandleFunc("/run", handlerWrapper(output.RunHandler))
http.HandleFunc(conf.Wide.Context+"/stop", handlerWrapper(output.StopHandler)) http.HandleFunc("/stop", handlerWrapper(output.StopHandler))
http.HandleFunc(conf.Wide.Context+"/go/test", handlerWrapper(output.GoTestHandler)) http.HandleFunc("/go/test", handlerWrapper(output.GoTestHandler))
http.HandleFunc(conf.Wide.Context+"/go/vet", handlerWrapper(output.GoVetHandler)) http.HandleFunc("/go/vet", handlerWrapper(output.GoVetHandler))
http.HandleFunc(conf.Wide.Context+"/go/get", handlerWrapper(output.GoGetHandler)) http.HandleFunc("/go/get", handlerWrapper(output.GoGetHandler))
http.HandleFunc(conf.Wide.Context+"/go/install", handlerWrapper(output.GoInstallHandler)) http.HandleFunc("/go/install", handlerWrapper(output.GoInstallHandler))
http.HandleFunc(conf.Wide.Context+"/output/ws", handlerWrapper(output.WSHandler)) http.HandleFunc("/output/ws", handlerWrapper(output.WSHandler))
// cross-compilation // cross-compilation
http.HandleFunc(conf.Wide.Context+"/cross", handlerWrapper(output.CrossCompilationHandler)) http.HandleFunc("/cross", handlerWrapper(output.CrossCompilationHandler))
// file tree // file tree
http.HandleFunc(conf.Wide.Context+"/files", handlerWrapper(file.GetFilesHandler)) http.HandleFunc("/files", handlerWrapper(file.GetFilesHandler))
http.HandleFunc(conf.Wide.Context+"/file/refresh", handlerWrapper(file.RefreshDirectoryHandler)) http.HandleFunc("/file/refresh", handlerWrapper(file.RefreshDirectoryHandler))
http.HandleFunc(conf.Wide.Context+"/file", handlerWrapper(file.GetFileHandler)) http.HandleFunc("/file", handlerWrapper(file.GetFileHandler))
http.HandleFunc(conf.Wide.Context+"/file/save", handlerWrapper(file.SaveFileHandler)) http.HandleFunc("/file/save", handlerWrapper(file.SaveFileHandler))
http.HandleFunc(conf.Wide.Context+"/file/new", handlerWrapper(file.NewFileHandler)) http.HandleFunc("/file/new", handlerWrapper(file.NewFileHandler))
http.HandleFunc(conf.Wide.Context+"/file/remove", handlerWrapper(file.RemoveFileHandler)) http.HandleFunc("/file/remove", handlerWrapper(file.RemoveFileHandler))
http.HandleFunc(conf.Wide.Context+"/file/rename", handlerWrapper(file.RenameFileHandler)) http.HandleFunc("/file/rename", handlerWrapper(file.RenameFileHandler))
http.HandleFunc(conf.Wide.Context+"/file/search/text", handlerWrapper(file.SearchTextHandler)) http.HandleFunc("/file/search/text", handlerWrapper(file.SearchTextHandler))
http.HandleFunc(conf.Wide.Context+"/file/find/name", handlerWrapper(file.FindHandler)) http.HandleFunc("/file/find/name", handlerWrapper(file.FindHandler))
// outline // outline
http.HandleFunc(conf.Wide.Context+"/outline", handlerWrapper(file.GetOutlineHandler)) http.HandleFunc("/outline", handlerWrapper(file.GetOutlineHandler))
// file export/import // file export/import
http.HandleFunc(conf.Wide.Context+"/file/zip/new", handlerWrapper(file.CreateZipHandler)) http.HandleFunc("/file/zip/new", handlerWrapper(file.CreateZipHandler))
http.HandleFunc(conf.Wide.Context+"/file/zip", handlerWrapper(file.GetZipHandler)) http.HandleFunc("/file/zip", handlerWrapper(file.GetZipHandler))
http.HandleFunc(conf.Wide.Context+"/file/decompress", handlerWrapper(file.DecompressHandler)) http.HandleFunc("/file/decompress", handlerWrapper(file.DecompressHandler))
// editor // editor
http.HandleFunc(conf.Wide.Context+"/editor/ws", handlerWrapper(editor.WSHandler)) http.HandleFunc("/editor/ws", handlerWrapper(editor.WSHandler))
http.HandleFunc(conf.Wide.Context+"/go/fmt", handlerWrapper(editor.GoFmtHandler)) http.HandleFunc("/go/fmt", handlerWrapper(editor.GoFmtHandler))
http.HandleFunc(conf.Wide.Context+"/autocomplete", handlerWrapper(editor.AutocompleteHandler)) http.HandleFunc("/autocomplete", handlerWrapper(editor.AutocompleteHandler))
http.HandleFunc(conf.Wide.Context+"/exprinfo", handlerWrapper(editor.GetExprInfoHandler)) http.HandleFunc("/exprinfo", handlerWrapper(editor.GetExprInfoHandler))
http.HandleFunc(conf.Wide.Context+"/find/decl", handlerWrapper(editor.FindDeclarationHandler)) http.HandleFunc("/find/decl", handlerWrapper(editor.FindDeclarationHandler))
http.HandleFunc(conf.Wide.Context+"/find/usages", handlerWrapper(editor.FindUsagesHandler)) http.HandleFunc("/find/usages", handlerWrapper(editor.FindUsagesHandler))
// notification // notification
http.HandleFunc(conf.Wide.Context+"/notification/ws", handlerWrapper(notification.WSHandler)) http.HandleFunc("/notification/ws", handlerWrapper(notification.WSHandler))
// user // user
http.HandleFunc(conf.Wide.Context+"/logout", handlerWrapper(session.LogoutHandler)) http.HandleFunc("/logout", handlerWrapper(session.LogoutHandler))
http.HandleFunc(conf.Wide.Context+"/preference", handlerWrapper(session.PreferenceHandler)) http.HandleFunc("/preference", handlerWrapper(session.PreferenceHandler))
// playground // playground
http.HandleFunc(conf.Wide.Context+"/playground", handlerWrapper(playground.IndexHandler)) http.HandleFunc("/playground", handlerWrapper(playground.IndexHandler))
http.HandleFunc(conf.Wide.Context+"/playground/", handlerWrapper(playground.IndexHandler)) http.HandleFunc("/playground/", handlerWrapper(playground.IndexHandler))
http.HandleFunc(conf.Wide.Context+"/playground/ws", handlerWrapper(playground.WSHandler)) http.HandleFunc("/playground/ws", handlerWrapper(playground.WSHandler))
http.HandleFunc(conf.Wide.Context+"/playground/save", handlerWrapper(playground.SaveHandler)) http.HandleFunc("/playground/save", handlerWrapper(playground.SaveHandler))
http.HandleFunc(conf.Wide.Context+"/playground/short-url", handlerWrapper(playground.ShortURLHandler)) http.HandleFunc("/playground/short-url", handlerWrapper(playground.ShortURLHandler))
http.HandleFunc(conf.Wide.Context+"/playground/build", handlerWrapper(playground.BuildHandler)) http.HandleFunc("/playground/build", handlerWrapper(playground.BuildHandler))
http.HandleFunc(conf.Wide.Context+"/playground/run", handlerWrapper(playground.RunHandler)) http.HandleFunc("/playground/run", handlerWrapper(playground.RunHandler))
http.HandleFunc(conf.Wide.Context+"/playground/stop", handlerWrapper(playground.StopHandler)) http.HandleFunc("/playground/stop", handlerWrapper(playground.StopHandler))
http.HandleFunc(conf.Wide.Context+"/playground/autocomplete", handlerWrapper(playground.AutocompleteHandler)) http.HandleFunc("/playground/autocomplete", handlerWrapper(playground.AutocompleteHandler))
logger.Infof("Wide is running [%s]", conf.Wide.Server+conf.Wide.Context) logger.Infof("Wide is running [%s]", conf.Wide.Server)
err := http.ListenAndServe(conf.Wide.Server, nil) listen := conf.Wide.Server[strings.Index(conf.Wide.Server, "://")+3:]
err := http.ListenAndServe(listen, nil)
if err != nil { if err != nil {
logger.Error(err) logger.Error(err)
} }
@ -182,37 +182,34 @@ func main() {
// indexHandler handles request of Wide index. // indexHandler handles request of Wide index.
func indexHandler(w http.ResponseWriter, r *http.Request) { func indexHandler(w http.ResponseWriter, r *http.Request) {
if conf.Wide.Context+"/" != r.RequestURI { if "/" != r.RequestURI {
http.Redirect(w, r, conf.Wide.Context+"/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
return return
} }
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/start", http.StatusFound)
return return
} }
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)
if "playground" == uid { // reserved user for Playground if "playground" == uid { // reserved user for Playground
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/start", http.StatusFound)
return return
} }
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
user := conf.GetUser(uid) user := conf.GetUser(uid)
if nil == user { if nil == user {
logger.Warnf("Not found user [%s]", uid) logger.Warnf("Not found user [%s]", uid)
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/start", http.StatusFound)
return return
} }
@ -264,17 +261,14 @@ func serveSingle(pattern string, filename string) {
// startHandler handles request of start page. // startHandler handles request of start page.
func startHandler(w http.ResponseWriter, r *http.Request) { func startHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/login", http.StatusFound)
return return
} }
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)
@ -304,17 +298,14 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
// keyboardShortcutsHandler handles request of keyboard shortcuts page. // keyboardShortcutsHandler handles request of keyboard shortcuts page.
func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) { func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/start", http.StatusFound)
return return
} }
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)
@ -336,17 +327,14 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
// aboutHandle handles request of about page. // aboutHandle handles request of about page.
func aboutHandler(w http.ResponseWriter, r *http.Request) { func aboutHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/login", http.StatusFound)
return return
} }
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)

View File

@ -62,7 +62,7 @@ func event2Notification(e *event.Event) {
return return
} }
httpSession, _ := session.HTTPSession.Get(wsChannel.Request, "wide-session") httpSession, _ := session.HTTPSession.Get(wsChannel.Request, session.CookieName)
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)
locale := conf.GetUser(uid).Locale locale := conf.GetUser(uid).Locale

View File

@ -38,7 +38,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -37,7 +37,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -35,7 +35,7 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -37,7 +37,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -35,7 +35,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -35,7 +35,7 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -37,7 +37,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -32,7 +32,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -35,7 +35,7 @@ func SaveHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
@ -101,7 +101,7 @@ func ShortURLHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
session, _ := session.HTTPSession.Get(r, "wide-session") session, _ := session.HTTPSession.Get(r, session.CookieName)
if session.IsNew { if session.IsNew {
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)

View File

@ -40,16 +40,13 @@ var logger = log.NewLogger(os.Stdout)
// IndexHandler handles request of Playground index. // IndexHandler handles request of Playground index.
func IndexHandler(w http.ResponseWriter, r *http.Request) { func IndexHandler(w http.ResponseWriter, r *http.Request) {
// create a HTTP session // create a HTTP session
httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
if httpSession.IsNew { if httpSession.IsNew {
httpSession.Values["id"] = strconv.Itoa(rand.Int()) httpSession.Values["id"] = strconv.Itoa(rand.Int())
httpSession.Values["uid"] = "playground" httpSession.Values["uid"] = "playground"
} }
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)

View File

@ -16,13 +16,15 @@ package session
import ( import (
"crypto/tls" "crypto/tls"
"github.com/b3log/wide/conf"
"math/rand" "math/rand"
"net/http" "net/http"
"os"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/b3log/wide/conf"
"github.com/b3log/wide/util" "github.com/b3log/wide/util"
"github.com/parnurzeal/gorequest" "github.com/parnurzeal/gorequest"
) )
@ -58,6 +60,7 @@ func RedirectGitHubHandler(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(referer, "/") { if strings.HasSuffix(referer, "/") {
referer = referer[:len(referer)-1] referer = referer[:len(referer)-1]
} }
referer += "__1"
state := util.Rand.String(16) + referer state := util.Rand.String(16) + referer
states[state] = state states[state] = state
path := loginAuthURL + "?client_id=" + clientId + "&state=" + state + "&scope=public_repo,read:user,user:follow" path := loginAuthURL + "?client_id=" + clientId + "&state=" + state + "&scope=public_repo,read:user,user:follow"
@ -93,7 +96,7 @@ func GithubCallbackHandler(w http.ResponseWriter, r *http.Request) {
githubId := githubUser["userId"].(string) githubId := githubUser["userId"].(string)
userName := githubUser["userName"].(string) userName := githubUser["userName"].(string)
avatar := githubUser["userAvatar"].(string) avatar := githubUser["userAvatarURL"].(string)
result := util.NewResult() result := util.NewResult()
defer util.RetResult(w, r, result) defer util.RetResult(w, r, result)
@ -110,14 +113,10 @@ func GithubCallbackHandler(w http.ResponseWriter, r *http.Request) {
} }
// create a HTTP session // create a HTTP session
httpSession, _ := HTTPSession.Get(r, "wide-session") httpSession, _ := HTTPSession.Get(r, CookieName)
httpSession.Values["uid"] = githubId httpSession.Values["uid"] = githubId
httpSession.Values["id"] = strconv.Itoa(rand.Int()) httpSession.Values["id"] = strconv.Itoa(rand.Int())
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
logger.Debugf("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), githubId) logger.Debugf("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), githubId)
@ -141,3 +140,140 @@ func GitHubUserInfo(accessToken string) (ret map[string]interface{}) {
return result["data"].(map[string]interface{}) return result["data"].(map[string]interface{})
} }
// LogoutHandler handles request of user logout (exit).
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult()
defer util.RetResult(w, r, result)
httpSession, _ := HTTPSession.Get(r, CookieName)
httpSession.Options.MaxAge = -1
httpSession.Save(r, w)
}
// addUser add a user with the specified user id, username and avatar.
//
// 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(userId, userName, userAvatar string) string {
if !conf.Wide.AllowRegister {
return notAllowRegister
}
if "playground" == userId {
return userExists
}
addUserMutex.Lock()
defer addUserMutex.Unlock()
for _, user := range conf.Users {
if strings.ToLower(user.Id) == strings.ToLower(userId) {
return userExists
}
}
workspace := filepath.Join(conf.Wide.UsersWorkspaces, userId)
newUser := conf.NewUser(userId, userName, userAvatar, workspace)
conf.Users = append(conf.Users, newUser)
if !newUser.Save() {
return userCreateError
}
conf.CreateWorkspaceDir(workspace)
helloWorld(workspace)
conf.UpdateCustomizedConf(userId)
http.Handle("/workspace/"+userId+"/",
http.StripPrefix("/workspace/"+userId+"/", http.FileServer(http.Dir(newUser.WorkspacePath()))))
logger.Infof("Created a user [%s]", userId)
return userCreated
}
// helloWorld generates the 'Hello, 世界' source code.
// 1. src/hello/main.go
// 2. src/web/main.go
func helloWorld(workspace string) {
consoleHello(workspace)
webHello(workspace)
}
func consoleHello(workspace string) {
dir := workspace + conf.PathSeparator + "src" + conf.PathSeparator + "hello"
if err := os.MkdirAll(dir, 0755); nil != err {
logger.Error(err)
return
}
fout, err := os.Create(dir + conf.PathSeparator + "main.go")
if nil != err {
logger.Error(err)
return
}
fout.WriteString(conf.HelloWorld)
fout.Close()
}
func webHello(workspace string) {
dir := workspace + conf.PathSeparator + "src" + conf.PathSeparator + "web"
if err := os.MkdirAll(dir, 0755); nil != err {
logger.Error(err)
return
}
fout, err := os.Create(dir + conf.PathSeparator + "main.go")
if nil != err {
logger.Error(err)
return
}
code := `package main
import (
"fmt"
"math/rand"
"net/http"
"strconv"
"time"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, 世界"))
})
port := getPort()
// you may need to change the address
fmt.Println("Open https://wide.b3log.org:" + port + " in your browser to see the result")
if err := http.ListenAndServe(":"+port, nil); nil != err {
fmt.Println(err)
}
}
func getPort() string {
rand.Seed(time.Now().UnixNano())
return strconv.Itoa(7000 + rand.Intn(8000-7000))
}
`
fout.WriteString(code)
fout.Close()
}

View File

@ -47,6 +47,8 @@ import (
const ( const (
sessionStateActive = iota sessionStateActive = iota
sessionStateClosed // (not used so far) sessionStateClosed // (not used so far)
CookieName = "wide-sess"
) )
// Logger. // Logger.
@ -220,7 +222,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
wSession := WideSessions.Get(sid) wSession := WideSessions.Get(sid)
if nil == wSession { if nil == wSession {
httpSession, _ := HTTPSession.Get(r, "wide-session") httpSession, _ := HTTPSession.Get(r, CookieName)
if httpSession.IsNew { if httpSession.IsNew {
return return

View File

@ -17,7 +17,6 @@ package session
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@ -44,18 +43,15 @@ var addUserMutex sync.Mutex
// PreferenceHandler handles request of preference page. // PreferenceHandler handles request of preference page.
func PreferenceHandler(w http.ResponseWriter, r *http.Request) { func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
httpSession, _ := HTTPSession.Get(r, "wide-session") httpSession, _ := HTTPSession.Get(r, CookieName)
if httpSession.IsNew { if httpSession.IsNew {
http.Redirect(w, r, conf.Wide.Context+"/login", http.StatusFound) http.Redirect(w, r, "/start", http.StatusFound)
return return
} }
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
if "" != conf.Wide.Context {
httpSession.Options.Path = conf.Wide.Context
}
httpSession.Save(r, w) httpSession.Save(r, w)
uid := httpSession.Values["uid"].(string) uid := httpSession.Values["uid"].(string)
@ -154,17 +150,6 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
result.Succ = user.Save() result.Succ = user.Save()
} }
// LogoutHandler handles request of user logout (exit).
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
result := util.NewResult()
defer util.RetResult(w, r, result)
httpSession, _ := HTTPSession.Get(r, "wide-session")
httpSession.Options.MaxAge = -1
httpSession.Save(r, w)
}
// FixedTimeSave saves online users' configurations periodically (1 minute). // FixedTimeSave saves online users' configurations periodically (1 minute).
// //
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time. // Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
@ -230,129 +215,3 @@ func getOnlineUsers() []*conf.User {
return ret return ret
} }
// addUser add a user with the specified user id, username and avatar.
//
// 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(userId, userName, userAvatar string) string {
if !conf.Wide.AllowRegister {
return notAllowRegister
}
if "playground" == userId {
return userExists
}
addUserMutex.Lock()
defer addUserMutex.Unlock()
for _, user := range conf.Users {
if strings.ToLower(user.Id) == strings.ToLower(userId) {
return userExists
}
}
workspace := filepath.Join(conf.Wide.UsersWorkspaces, userId)
newUser := conf.NewUser(userId, userName, userAvatar, workspace)
conf.Users = append(conf.Users, newUser)
if !newUser.Save() {
return userCreateError
}
conf.CreateWorkspaceDir(workspace)
helloWorld(workspace)
conf.UpdateCustomizedConf(userId)
http.Handle("/workspace/"+userId+"/",
http.StripPrefix("/workspace/"+userId+"/", http.FileServer(http.Dir(newUser.WorkspacePath()))))
logger.Infof("Created a user [%s]", userId)
return userCreated
}
// helloWorld generates the 'Hello, 世界' source code.
// 1. src/hello/main.go
// 2. src/web/main.go
func helloWorld(workspace string) {
consoleHello(workspace)
webHello(workspace)
}
func consoleHello(workspace string) {
dir := workspace + conf.PathSeparator + "src" + conf.PathSeparator + "hello"
if err := os.MkdirAll(dir, 0755); nil != err {
logger.Error(err)
return
}
fout, err := os.Create(dir + conf.PathSeparator + "main.go")
if nil != err {
logger.Error(err)
return
}
fout.WriteString(conf.HelloWorld)
fout.Close()
}
func webHello(workspace string) {
dir := workspace + conf.PathSeparator + "src" + conf.PathSeparator + "web"
if err := os.MkdirAll(dir, 0755); nil != err {
logger.Error(err)
return
}
fout, err := os.Create(dir + conf.PathSeparator + "main.go")
if nil != err {
logger.Error(err)
return
}
code := `package main
import (
"fmt"
"math/rand"
"net/http"
"strconv"
"time"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, 世界"))
})
port := getPort()
// you may need to change the address
fmt.Println("Open https://wide.b3log.org:" + port + " in your browser to see the result")
if err := http.ListenAndServe(":"+port, nil); nil != err {
fmt.Println(err)
}
}
func getPort() string {
rand.Seed(time.Now().UnixNano())
return strconv.Itoa(7000 + rand.Intn(8000-7000))
}
`
fout.WriteString(code)
fout.Close()
}

View File

@ -1,6 +1,6 @@
<div class="item"> <div class="item">
<div class="fn-clear"> <div class="fn-clear">
<img class="logo" src="{{.conf.StaticServer}}/static/images/wide-logo.png" alt="wide logi"/> <img class="logo" src="{{.conf.Server}}/static/images/wide-logo.png" alt="wide logi"/>
<div class="fn-left"> <div class="fn-left">
<h2>Hello, 世界</h2> <h2>Hello, 世界</h2>
<h3>Coding with Go on the Wide way.</h3> <h3>Coding with Go on the Wide way.</h3>

View File

@ -8,27 +8,27 @@
<meta name="author" content="B3log"> <meta name="author" content="B3log">
<meta property="og:description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/> <meta property="og:description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/>
{{if eq $.conf.RuntimeMode "dev"}} {{if eq $.conf.RuntimeMode "dev"}}
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/jquery-layout/layout-default-latest.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/jquery-layout/layout-default-latest.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/show-hint.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/show-hint.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/lint.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/lint.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.css">
{{range $index, $theme := .editorThemes}} {{range $index, $theme := .editorThemes}}
<link rel="stylesheet" href="{{$.conf.StaticServer}}/static/js/overwrite/codemirror/theme/{{$theme}}.css">{{end}} <link rel="stylesheet" href="{{$.conf.Server}}/static/js/overwrite/codemirror/theme/{{$theme}}.css">{{end}}
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/dialog.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/dialog.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/base.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/base.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/wide.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/wide.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/side.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/side.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/start.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/start.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/about.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/about.css?{{.conf.StaticResourceVersion}}">
{{else}} {{else}}
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/lib.min.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/lib.min.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/wide.min.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/wide.min.css?{{.conf.StaticResourceVersion}}">
{{end}} {{end}}
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/ztree/zTreeStyle.min.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/ztree/zTreeStyle.min.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/user/{{.username}}/style.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/user/{{.uid}}/style.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/themes/{{.user.Theme}}.css?{{.conf.StaticResourceVersion}}" id="themesLink"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/themes/{{.user.Theme}}.css?{{.conf.StaticResourceVersion}}" id="themesLink">
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head> </head>
@ -347,7 +347,7 @@
<div class="fn-right"> <div class="fn-right">
<img class="gravatar" <img class="gravatar"
onerror="this.src='{{.conf.StaticServer}}/static/images/user-thumbnail.png'" onerror="this.src='{{.conf.Server}}/static/images/user-thumbnail.png'"
src="https://secure.gravatar.com/avatar/{{.user.Gravatar}}?s=17&d=https://hacpai.com/images/user-thumbnail.png" src="https://secure.gravatar.com/avatar/{{.user.Gravatar}}?s=17&d=https://hacpai.com/images/user-thumbnail.png"
title="{{.user.Name}}"/> title="{{.user.Name}}"/>
<span class="font-ico ico-share"></span> &nbsp; <span class="font-ico ico-share"></span> &nbsp;
@ -560,7 +560,7 @@
<script> <script>
var config = { var config = {
"context": {{.conf.Context}}, "context": {{.conf.Context}},
"staticServer": '{{.conf.StaticServer}}', "staticServer": '{{.conf.Server}}',
"pathSeparator": '{{.pathSeparator}}', "pathSeparator": '{{.pathSeparator}}',
"label": {{.i18n}}, "label": {{.i18n}},
"channel": {{.conf.Channel}}, "channel": {{.conf.Channel}},
@ -581,71 +581,71 @@
</script> </script>
{{if eq $.conf.RuntimeMode "dev"}} {{if eq $.conf.RuntimeMode "dev"}}
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-ui.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-ui.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-layout/jquery.layout-latest.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-layout/jquery.layout-latest.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/reconnecting-websocket.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/Autolinker.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/Autolinker.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/lint.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/lint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/json-lint.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/json-lint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/selection/active-line.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/selection/active-line.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/overwrite/codemirror/addon/hint/show-hint.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/overwrite/codemirror/addon/hint/show-hint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/anyword-hint.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/anyword-hint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/display/rulers.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/display/rulers.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closebrackets.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closebrackets.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/matchbrackets.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/matchbrackets.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closetag.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closetag.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/searchcursor.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/searchcursor.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/search.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/search.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/match-highlighter.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/match-highlighter.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldcode.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldcode.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/brace-fold.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/brace-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/xml-fold.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/xml-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/markdown-fold.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/markdown-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/comment-fold.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/comment-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/mode/loadmode.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/mode/loadmode.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/comment/comment.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/comment/comment.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/meta.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/meta.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/go/go.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/go/go.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/clike/clike.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/clike/clike.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/xml/xml.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/xml/xml.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/htmlmixed/htmlmixed.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/htmlmixed/htmlmixed.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/javascript/javascript.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/javascript/javascript.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/markdown/markdown.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/markdown/markdown.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/css/css.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/css/css.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/shell/shell.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/shell/shell.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/sql/sql.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/sql/sql.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/keymap/vim.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/keymap/vim.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/lint/json-lint.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/lint/json-lint.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/lint/go-lint.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/lint/go-lint.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/emmet.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/emmet.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/js-beautify-1.5.4/beautify.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/js-beautify-1.5.4/beautify.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/js-beautify-1.5.4/beautify-html.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/js-beautify-1.5.4/beautify-html.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/js-beautify-1.5.4/beautify-css.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/js-beautify-1.5.4/beautify-css.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-file-upload-9.8.0/vendor/jquery.ui.widget.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-file-upload-9.8.0/vendor/jquery.ui.widget.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-file-upload-9.8.0/jquery.iframe-transport.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-file-upload-9.8.0/jquery.iframe-transport.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-file-upload-9.8.0/jquery.fileupload.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-file-upload-9.8.0/jquery.fileupload.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tabs.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/tabs.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/dialog.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/dialog.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/editors.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/editors.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/notification.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/notification.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tree.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/tree.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/wide.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/wide.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/session.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/session.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/windows.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/windows.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/hotkeys.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/hotkeys.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/bottomGroup.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/bottomGroup.js?{{.conf.StaticResourceVersion}}"></script>
{{else}} {{else}}
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/wide.min.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/wide.min.js?{{.conf.StaticResourceVersion}}"></script>
{{end}} {{end}}
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/zeroclipboard/ZeroClipboard.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/zeroclipboard/ZeroClipboard.min.js"></script>
</body> </body>
</html> </html>

View File

@ -8,20 +8,20 @@
<meta name="description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/> <meta name="description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/>
<meta name="author" content="B3log"> <meta name="author" content="B3log">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/show-hint.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/show-hint.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.css"> <link rel="stylesheet" href="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.css">
<link rel="stylesheet" href="{{$.conf.StaticServer}}/static/js/overwrite/codemirror/theme/wide.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{$.conf.Server}}/static/js/overwrite/codemirror/theme/wide.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/dialog.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/dialog.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/base.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/base.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/wide.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/wide.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/about.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/about.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/themes/default.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/themes/default.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/sign.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/sign.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/side.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/side.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/playground.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/playground.css?{{.conf.StaticResourceVersion}}">
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head> </head>
@ -30,7 +30,7 @@
<ul class="fn-left"> <ul class="fn-left">
<li> <li>
<a href="/" target="_blank"> <a href="/" target="_blank">
<img title="Wide, a Web-based IDE for Teams using Golang." src="{{.conf.StaticServer}}/static/images/wide-logo.png" <img title="Wide, a Web-based IDE for Teams using Golang." src="{{.conf.Server}}/static/images/wide-logo.png"
class="logo"/></a> class="logo"/></a>
</li> </li>
<li> <li>
@ -84,7 +84,7 @@
<script> <script>
var config = { var config = {
"context": "{{.conf.Context}}", "context": "{{.conf.Context}}",
"staticServer": "{{.conf.StaticServer}}", "staticServer": "{{.conf.Server}}",
"channel": "{{.conf.Channel}}", "channel": "{{.conf.Channel}}",
"wideSessionId": "{{.sid}}", "wideSessionId": "{{.sid}}",
"label": {{.i18n}}, "label": {{.i18n}},
@ -99,32 +99,32 @@
</script> </script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/reconnecting-websocket.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/selection/active-line.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/selection/active-line.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/overwrite/codemirror/addon/hint/show-hint.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/overwrite/codemirror/addon/hint/show-hint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/anyword-hint.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/anyword-hint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/display/rulers.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/display/rulers.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closebrackets.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closebrackets.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/matchbrackets.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/matchbrackets.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closetag.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closetag.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/searchcursor.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/searchcursor.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/search.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/search.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/match-highlighter.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/match-highlighter.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldcode.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldcode.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/brace-fold.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/brace-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/comment-fold.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/comment-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/mode/loadmode.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/mode/loadmode.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/comment/comment.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/comment/comment.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/meta.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/meta.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/go/go.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/go/go.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/dialog.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/dialog.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/playground.js?{{.conf.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/playground.js?{{.conf.StaticResourceVersion}}"></script>
</body> </body>
</html> </html>

View File

@ -115,7 +115,7 @@
<input data-value="{{.user.Password}}" value="{{.user.Password}}" name="password" type="password"/> <input data-value="{{.user.Password}}" value="{{.user.Password}}" name="password" type="password"/>
</label> </label>
<label class="fn-clear"> <label class="fn-clear">
<img onerror="this.src='{{.conf.StaticServer}}/static/images/user-thumbnail.png'" <img onerror="this.src='{{.conf.Server}}/static/images/user-thumbnail.png'"
src="https://secure.gravatar.com/avatar/{{.user.Gravatar}}?s=48&d=https://hacpai.com/images/user-thumbnail.png" src="https://secure.gravatar.com/avatar/{{.user.Gravatar}}?s=48&d=https://hacpai.com/images/user-thumbnail.png"
title="{{.user.Name}}" class='gravatar'/> title="{{.user.Name}}" class='gravatar'/>
<a href="http://gravatar.com/" target="_blank">{{.i18n.change_avatar}} Gravatar.com</a> <a href="http://gravatar.com/" target="_blank">{{.i18n.change_avatar}} Gravatar.com</a>

View File

@ -1,35 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{.i18n.wide}}</title>
<meta name="keywords" content="Wide, Golang, IDE, Team, Cloud, B3log, Shell"/>
<meta name="description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/>
<meta name="author" content="B3log">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/shell.css?{{.conf.StaticResourceVersion}}">
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body>
<input id="shellInput" placeholder="Command..."/>
<div>
<textarea id="shellOutput" rows="40" ></textarea>
</div>
<script type="text/javascript">
var config = {
channel: {
shell: '{{.conf.ShellChannel}}'
},
wideSessionId: {{.sid}}
};</script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/shell.js?{{.conf.StaticResourceVersion}}"></script>
</body>
</html>

View File

@ -8,15 +8,15 @@
<meta name="description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/> <meta name="description" content="A Web-based IDE for Teams using Golang, do your development anytime, anywhere."/>
<meta name="author" content="B3log"> <meta name="author" content="B3log">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/base.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/base.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/sign.css?{{.conf.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.Server}}/static/css/sign.css?{{.conf.StaticResourceVersion}}">
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head> </head>
<body> <body>
<div class="header"> <div class="header">
<div class="wrapper fn-clear"> <div class="wrapper fn-clear">
<a href="/login" rel="login"> <a href="/login" rel="login">
<img title="Wide, a Web-based IDE for Teams using Golang." src="{{.conf.StaticServer}}/static/images/wide-logo.png" <img title="Wide, a Web-based IDE for Teams using Golang." src="{{.conf.Server}}/static/images/wide-logo.png"
class="logo"/></a> class="logo"/></a>
<ul class="fn-right"> <ul class="fn-right">
<li><a href="/playground" target="_blank" style="color: #cd504a">Play</a></li> <li><a href="/playground" target="_blank" style="color: #cd504a">Play</a></li>
@ -56,7 +56,7 @@
</div> </div>
</div> </div>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="{{.conf.Server}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script> <script>
(function () { (function () {
var contentH = $(window).height() - $(".footer").height() - $(".header").height() - 18; var contentH = $(window).height() - $(".footer").height() - $(".header").height() - 18;