예제 #1
0
파일: file.go 프로젝트: fxnn/gone
func (l *FilesystemLoader) processEvents() {
	for {
		select {
		case event, ok := <-l.watcher.Events:
			if !ok {
				log.Printf("watching filesystem templates stopped")
				return
			}
			var path, name = event.Name, l.templateNames[event.Name]
			var templateChan = l.templateChans[path]
			if event.Op == fsnotify.Write || event.Op == fsnotify.Chmod {
				if template, err := l.LoadHtmlTemplate(name); err != nil {
					log.Warnf("error while reloading template %s from %s: %s", name, path, err)
				} else {
					log.Printf("reloading template %s from %s", name, path)
					templateChan <- template
				}
			}
		case err, ok := <-l.watcher.Errors:
			if !ok {
				log.Printf("watching filesystem templates stopped")
				return
			}
			log.Printf("error while watching filesystem templates: %s", err)
		}
	}
}
예제 #2
0
파일: deliverer.go 프로젝트: fxnn/gone
func (e *TemplateDeliverer) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	if request.Method != "GET" {
		log.Printf("%s %s: wrong method for template handling", request.Method, request.URL)
		failer.ServeMethodNotAllowed(writer, request)
		return
	}

	readCloser, err := e.loader.LoadResource(request.URL.Path)
	if err != nil {
		log.Printf("%s %s: error while opening template resource: %s",
			request.Method, request.URL, err)
		failer.ServeNotFound(writer, request)
		return
	}
	defer readCloser.Close()

	writer.Header().Set("Content-Type", e.detectMimeType(request))

	_, err = io.Copy(writer, readCloser)
	if err != nil {
		log.Printf("%s %s: error while writing template resource to output: %s",
			request.Method, request.URL, err)
		failer.ServeInternalServerError(writer, request)
		return
	}
}
예제 #3
0
파일: http.go 프로젝트: fxnn/gone
func (a *HttpBasicAuthenticator) LoginHandler() http.Handler {
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		if a.loginRequiresHeader != "" && request.Header.Get(a.loginRequiresHeader) == "" {
			log.Printf("%s %s: deny login because of missing connection header '%s'",
				request.Method, request.URL, a.loginRequiresHeader)
			failer.ServeBadRequest(writer, request)
			return
		}

		var user = a.userAttemptingAuth(request)
		if user != "" {
			a.authenticate(writer, request)

			// NOTE: Delay request even if authentication was successful, so that the
			// attacker needs our response
			time.Sleep(a.bruteBlocker.Delay(user, request.RemoteAddr, a.requestAuth.IsAuthenticated(request)))

			if a.requestAuth.IsAuthenticated(request) && a.requestAuth.UserID(request) == user {
				log.Printf("%s %s: authenticated as %s", request.Method, request.URL, a.requestAuth.UserID(request))
				a.sessionAuth.SetUserID(writer, request, a.requestAuth.UserID(request))
				router.RedirectToViewMode(writer, request)
				return
			}
		}

		a.basicAuth.RequireAuth(writer, request)
	})
}
예제 #4
0
파일: editor.go 프로젝트: fxnn/gone
func (e *Editor) serveWriter(writer http.ResponseWriter, request *http.Request) {
	if !e.store.HasWriteAccessForRequest(request) {
		log.Printf("%s %s: no write permissions", request.Method, request.URL)
		failer.ServeUnauthorized(writer, request)
		return
	}

	var content = request.FormValue("content")
	if content == "" {
		log.Printf("%s %s: no valid content in request", request.Method, request.URL)
		failer.ServeBadRequest(writer, request)
		return
	}

	e.store.WriteString(request, content)
	if err := e.store.Err(); err != nil {
		log.Printf("%s %s: %s", request.Method, request.URL, err)
		failer.ServeInternalServerError(writer, request)
		return
	}
	log.Printf("%s %s: wrote %d bytes", request.Method, request.URL, len(content))

	if request.FormValue("saveAndReturn") != "" {
		router.RedirectToViewMode(writer, request)
		return
	}

	router.RedirectToEditMode(writer, request)
}
예제 #5
0
파일: gone.go 프로젝트: fxnn/gone
func htpasswdFilePath(contentRoot gopath.GoPath) gopath.GoPath {
	htpasswdFile := contentRoot.JoinPath(".htpasswd")
	if !htpasswdFile.IsExists() {
		log.Printf("no .htpasswd found")
	} else {
		log.Printf("using authentication data from .htpasswd")
	}
	return htpasswdFile
}
예제 #6
0
파일: cookie.go 프로젝트: fxnn/gone
func (s *CookieAuthenticator) session(request *http.Request) *sessions.Session {
	session, err := s.cookieStore.Get(request, authenticationStoreSessionName)
	if err != nil {
		log.Printf("%s %s: failed to decode existing cookie session", request.Method, request.URL)
	}
	return session
}
예제 #7
0
파일: cookie.go 프로젝트: fxnn/gone
func (s *CookieAuthenticator) removeCookie(writer http.ResponseWriter, request *http.Request) {
	var session = s.session(request)
	session.Options.MaxAge = -1
	if err := s.cookieStore.Save(request, writer, session); err != nil {
		log.Printf("%s %s: failed to clear cookie", request.Method, request.URL)
	}
}
예제 #8
0
파일: editor.go 프로젝트: fxnn/gone
func (e *Editor) serveDeleter(writer http.ResponseWriter, request *http.Request) {
	if !e.store.HasDeleteAccessForRequest(request) {
		log.Printf("%s %s: no delete permissions", request.Method, request.URL)
		failer.ServeUnauthorized(writer, request)
		return
	}

	e.store.Delete(request)
	if err := e.store.Err(); err != nil {
		log.Printf("%s %s: %s", request.Method, request.URL, err)
		failer.ServeInternalServerError(writer, request)
		return
	}
	log.Printf("%s %s: deleted", request.Method, request.URL)

	fmt.Fprintf(writer, "Successfully deleted")
}
예제 #9
0
파일: logger.go 프로젝트: fxnn/gone
func RequestLogger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var start = time.Now()
		var stats = &responseWriterWithStats{wrapped: w}

		next.ServeHTTP(stats, r)

		log.Printf("[%s] %d %s %s [%d bytes in %s]", clientIP(r), stats.status, r.Method, r.URL, stats.bytesWritten, time.Since(start))
	})
}
예제 #10
0
파일: cookie.go 프로젝트: fxnn/gone
func (s *CookieAuthenticator) SetUserID(writer http.ResponseWriter, request *http.Request, userId string) {
	if userId == "" {
		s.removeCookie(writer, request)
	} else {
		var session = s.session(request)
		session.Values[userIDKey] = userId
		if err := s.cookieStore.Save(request, writer, session); err != nil {
			log.Printf("%s %s: failed to store userid in cookie", request.Method, request.URL)
		}
	}
}
예제 #11
0
파일: rawFormatter.go 프로젝트: fxnn/gone
func (f rawFormatter) serveFromReader(reader io.Reader, writer http.ResponseWriter, request *http.Request) {
	writer.Header().Set("Content-Type", f.mimeType)

	// TODO: Use http.ServeContent instead
	_, err := io.Copy(writer, reader)
	if err != nil {
		log.Printf("%s %s: %s", request.Method, request.URL, err)
		failer.ServeInternalServerError(writer, request)
		return
	}
}
예제 #12
0
파일: cookie.go 프로젝트: fxnn/gone
func (s *CookieAuthenticator) UserID(request *http.Request) string {
	var session = s.session(request)
	var userId = session.Values[userIDKey]
	if userId != nil {
		if strVal, ok := userId.(string); ok {
			return strVal
		} else {
			log.Printf("%s %s: failed to read userId from value %s", request.Method, request.URL, userId)
		}
	}
	return ""
}
예제 #13
0
파일: gone.go 프로젝트: fxnn/gone
func templatePath(contentRoot gopath.GoPath, cfg config.Config) (result gopath.GoPath) {
	// configuration
	result = gopath.FromPath(cfg.TemplatePath)
	if !result.IsEmpty() {
		if !result.IsDirectory() {
			log.Fatalf("configured template path is no directory: %s", result.Path())
		}
		log.Printf("using templates from %s (by configuration)", result.Path())
		return result
	}

	// convention
	result = contentRoot.JoinPath(defaultTemplateDirectoryName)
	if result.IsDirectory() {
		log.Printf("using templates from %s (by convention)", result.Path())
		return result
	}

	// default
	log.Printf("using default templates")
	return gopath.Empty()
}
예제 #14
0
파일: gone.go 프로젝트: fxnn/gone
func main() {
	log.Printf("--- gone startup ---")

	cfg := config.FromCommandline()

	switch cfg.Command {
	case config.CommandExportTemplates:
		exportTemplates(cfg)
	case config.CommandListen:
		listen(cfg)
	case config.CommandHelp:
		config.PrintUsage()
	}
}
예제 #15
0
파일: Viewer.go 프로젝트: fxnn/gone
func (v *Viewer) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	if !v.store.HasReadAccessForRequest(request) {
		log.Printf("%s %s: no read permissions", request.Method, request.URL)
		failer.ServeUnauthorized(writer, request)
		return
	}

	if request.Method != "GET" {
		v.serveNonGET(writer, request)
		return
	}

	v.serveGET(writer, request)
}
예제 #16
0
파일: router.go 프로젝트: fxnn/gone
func (r Router) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	var err = request.ParseForm()
	if err != nil {
		log.Printf("%s %s: %s", request.Method, request.URL, err)
		failer.ServeBadRequest(writer, request)
	} else if Is(ModeTemplate, request) {
		r.templateDeliverer.ServeHTTP(writer, request)
	} else if Is(ModeLogin, request) {
		r.authenticator.ServeHTTP(writer, request)
	} else if Is(ModeEdit, request) || Is(ModeCreate, request) || Is(ModeDelete, request) {
		r.editor.ServeHTTP(writer, request)
	} else {
		r.viewer.ServeHTTP(writer, request)
	}
}
예제 #17
0
파일: editor.go 프로젝트: fxnn/gone
func (e *Editor) serveEditUI(writer http.ResponseWriter, request *http.Request) {
	if !e.store.HasWriteAccessForRequest(request) {
		log.Printf("%s %s: no write permissions", request.Method, request.URL)
		failer.ServeUnauthorized(writer, request)
		return
	}
	if !router.Is(router.ModeCreate, request) && !e.store.HasReadAccessForRequest(request) {
		log.Printf("%s %s: no read permissions", request.Method, request.URL)
		failer.ServeUnauthorized(writer, request)
		return
	}

	mimeType := e.store.MimeTypeForRequest(request)
	if err := e.assertEditableTextFile(request, mimeType); err != nil {
		log.Printf("%s %s: no editable text file: %s", request.Method, request.URL, err)
		failer.ServeUnsupportedMediaType(writer, request)
		return
	}

	var content = e.store.ReadString(request)
	if err := e.store.Err(); err != nil {
		if !store.IsPathNotFoundError(err) {
			log.Printf("%s %s: %s", request.Method, request.URL, err)
			failer.ServeInternalServerError(writer, request)
			return
		} else if router.Is(router.ModeEdit, request) {
			log.Printf("%s %s: file to be edited does not exist: %s", request.Method, request.URL, err)
			failer.ServeNotFound(writer, request)
			return
		}
	} else if router.Is(router.ModeCreate, request) {
		log.Printf("%s %s: file to be created already exists: %s", request.Method, request.URL, err)
		failer.ServeConflict(writer, request)
		return
	}

	err := e.renderer.Render(writer, request.URL, content, mimeType,
		router.Is(router.ModeEdit, request))
	if err != nil {
		log.Printf("%s %s: %s", request.Method, request.URL, err)
		failer.ServeInternalServerError(writer, request)
		return
	}

	log.Printf("%s %s: served from template", request.Method, request.URL)
}
예제 #18
0
파일: file.go 프로젝트: fxnn/gone
func (l *FilesystemLoader) WatchHtmlTemplate(name string) <-chan *template.Template {
	var path = l.templatePath(name).Path()

	l.templateNames[path] = name
	templateChan, ok := l.templateChans[path]
	if !ok {
		templateChan = make(chan *template.Template)
		l.templateChans[path] = templateChan
	}

	if err := l.watcher.Add(path); err != nil {
		log.Printf("couldn't watch filesystem template %s: %s", path, err)
		return make(chan *template.Template)
	}

	return templateChan
}
예제 #19
0
파일: editor.go 프로젝트: fxnn/gone
func (e *Editor) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	if e.isServeWriter(request) {
		e.serveWriter(writer, request)
		return
	}

	if e.isServeDeleter(request) {
		e.serveDeleter(writer, request)
		return
	}

	if e.isServeCreateUI(request) || e.isServeEditUI(request) {
		e.serveEditUI(writer, request)
		return
	}

	log.Printf("%s %s: method not allowed", request.Method, request.URL)
	failer.ServeMethodNotAllowed(writer, request)
}
예제 #20
0
파일: gone.go 프로젝트: fxnn/gone
func createHttpAuthenticator(
	auth authenticator.Authenticator,
	contentRoot gopath.GoPath,
	cfg config.Config,
) authenticator.HttpAuthenticator {
	var bruteBlocker = bruteblocker.New(
		cfg.BruteforceMaxDelay,
		cfg.BruteforceDelayStep,
		cfg.BruteforceDelayStep/5,
		cfg.BruteforceDelayStep/20,
		cfg.BruteforceDropDelayAfter,
	)
	if cfg.RequireSSLHeader != "" {
		log.Printf("Requiring SSL header %s on login (by configuration)", cfg.RequireSSLHeader)
	}
	return authenticator.NewHttpBasicAuthenticator(
		auth,
		htpasswdFilePath(contentRoot),
		cfg.RequireSSLHeader,
		bruteBlocker,
	)
}
예제 #21
0
파일: mime.go 프로젝트: fxnn/gone
func registerExtension(ext string, mimeType string) {
	if err := mime.AddExtensionType("."+ext, mimeType); err != nil {
		log.Printf("error adding %s as extension for Mime type %s: %s", ext, mimeType, err)
	}
}
예제 #22
0
파일: Viewer.go 프로젝트: fxnn/gone
func (v *Viewer) log(request *http.Request, err error) {
	log.Printf("%s %s: %s", request.Method, request.URL, err)
}