Пример #1
0
func Thumb(args martini.Params, res http.ResponseWriter, req *http.Request) {
	file := args["name"]

	org_dir := utils.ImageCfg.Root()
	temp_dir := utils.ImageCfg.Thumbs()

	org_file := org_dir + file
	temp_file := temp_dir + file

	if !Exists(temp_file) {
		okc := make(chan bool, 1)
		go utils.CreateThumb(okc, org_file, temp_file, 150, 150)
		<-okc
	}

	dir := http.Dir(temp_dir)

	f, err := dir.Open(file)
	if err != nil {
		log.Println(err)
		return
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return
	}

	res.Header().Set("X-Content-Type-Options", "nosniff")
	res.Header().Set("Expires", utils.ExpiresHeader())
	http.ServeContent(res, req, file, fi.ModTime(), f)
}
Пример #2
0
func Image(args martini.Params, res http.ResponseWriter, req *http.Request) {
	file := args["name"]
	fdir := utils.ImageCfg.Root()

	dir := http.Dir(fdir)

	f, err := dir.Open(file)
	if err != nil {
		// discard the error?
		http.NotFound(res, req)
		return
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		http.NotFound(res, req)
		return
	}

	res.Header().Set("X-Content-Type-Options", "nosniff")
	res.Header().Set("Expires", utils.ExpiresHeader())
	http.ServeContent(res, req, file, fi.ModTime(), f)
}
Пример #3
0
func QR(args martini.Params, su models.User, dbh *db.Dbh, session sessions.Session, r render.Render, res http.ResponseWriter, req *http.Request) {
	name := args["name"]

	album := dbh.GetAlbum(name)

	key := album.Privatekey
	private := album.Private

	if private && su.Id != album.User || album.Id == 0 {
		session.Set("flash", "Login Required")
		r.Redirect(strings.Join([]string{utils.AppCfg.Url(), "login"}, "/"), http.StatusFound)
		return
	}

	log.Printf("name: %s key: %s private: %t\n", name, key, private)

	file := createQR(name, key)

	dir := http.Dir(utils.ImageCfg.QR())
	f, err := dir.Open(file)
	if err != nil {
		// discard the error?
		return
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return
	}

	res.Header().Set("X-Content-Type-Options", "nosniff")
	res.Header().Set("Expires", utils.ExpiresHeader())
	res.Header().Add("Content-Type", "image/png")
	http.ServeContent(res, req, file, fi.ModTime(), f)
}
Пример #4
0
func main() {
	m := martini.Classic()

	// Gzip all
	m.Use(gzip.All())

	// Create sessions cookie store
	store := sessions.NewCookieStore([]byte(utils.AppCfg.SecretKey()))
	m.Use(sessions.Sessions("pixelrelay", store))

	// Setup render options
	m.Use(render.Renderer(render.Options{
		Directory: "templates",                            // Specify what path to load the templates from.
		Layout:    "layout",                               // Specify a layout template. Layouts can call {{ yield }} to render the current template.
		Charset:   "UTF-8",                                // Sets encoding for json and html content-types.
		Delims:    render.Delims{Left: "{[", Right: "]}"}, // Sets delimiters to the specified strings.
	}))

	// Setup DB
	dbh := db.Init(&db.Dbh{})
	m.Map(dbh)

	// Setup static file handling
	opts := martini.StaticOptions{SkipLogging: false, Expires: utils.ExpiresHeader}
	m.Use(martini.Static("static", opts))

	// Auth user and assign to session
	m.Use(middleware.UserAuth(models.User{}, dbh))

	// Encoder for .html or .json encoding
	m.Use(encoder.MapEncoder)

	// Setup Page
	p := models.InitPage(&models.Page{})
	m.Map(p)

	// Set up routes
	m.Get("/", controllers.Index)

	// Images
	m.Get("/image/:name", middleware.VerifyFile, controllers.ImagePage)
	m.Get("/o/:name", middleware.VerifyFile, controllers.Image)
	m.Get("/i/:name", middleware.VerifyFile, controllers.ImageModified)
	m.Get("/t/:name", middleware.VerifyFile, controllers.Thumb)
	m.Get("/image/trash/:album/:name", middleware.AuthRequired, controllers.ImageTrash)
	m.Get("/image/recover/:album/:name", middleware.AuthRequired, controllers.ImageRecover)

	// Albums
	m.Get("/albums", controllers.Albums)
	m.Get("/album/:name", controllers.Album)
	m.Get("/album/:name/qr", controllers.QR)
	m.Get("/:user/albums", controllers.Albums)
	m.Get("/:user/album/:name", controllers.Album)
	m.Get("/album/:name/private/:state", controllers.AlbumPrivate)

	m.Get("/album/:name/:key", controllers.Album)

	m.Post("/album/create", middleware.AuthRequired, controllers.AlbumCreate)
	m.Post("/album/update", middleware.AuthRequired, controllers.AlbumUpdate)
	m.Post("/album/delete/:name", middleware.AuthRequired, controllers.AlbumDelete)
	m.Post("/album/recover/:name", middleware.AuthRequired, controllers.AlbumRecover)
	m.Post("/album/move", middleware.AuthRequired, controllers.AlbumMove)

	// Tag
	m.Get("/tags", controllers.Tags)
	m.Get("/tag/:tag", controllers.Tagged)
	m.Post("/tag", middleware.AuthRequired, controllers.TagImage)

	// Auth
	m.Get("/login", controllers.Login)
	m.Post("/login", binding.Bind(forms.Login{}), binding.ErrorHandler, controllers.LoginPost)
	m.Get("/logout", controllers.Logout)

	// Upload
	m.Post("/up", middleware.Verify, binding.MultipartForm(models.ImageUpload{}), controllers.UploadImage)

	// 404
	m.NotFound(controllers.NotFound)

	// Account
	m.Get("/account", middleware.AuthRequired, controllers.Account)

	// Profile
	m.Get("/profile/:name", controllers.Profile)

	// Testing
	m.Get("/test/hash", test.Hash)
	m.Get("/test/hash/:user_id/:image_id", test.Hash)
	m.Get("/test/list", middleware.AuthRequired, test.List)
	m.Get("/test/listdb", middleware.AuthRequired, test.ListDB)
	m.Get("/test/listt", middleware.AuthRequired, test.ListThumb)
	m.Get("/test/uploader", middleware.AuthRequired, test.Uploader)

	// Start server and begin listening for HTTP requests
	// Watch for non-https requests and redirect to https
	// If request method is POST and path is /up
	//   discard file and redirect to correct https route
	log.Printf("Listening for \x1b[32;1mHTTP\x1b[0m connections on \x1b[32;1m%s\x1b[0m\n", utils.AppCfg.ListenOn())
	go http.ListenAndServe(utils.AppCfg.ListenOn(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		urlPath := r.URL.Path
		url := strings.Join([]string{utils.AppCfg.Url(), urlPath}, "")

		// Check if path is for the Upload controller.
		// Redirect client to HTTPS end point
		if urlPath == "/up" && r.Method == "POST" {
			ur := models.UploadResult{
				Code:   http.StatusFound,
				Result: "HTTPS Required",
				Name:   url,
			}
			log.Println(ur.String())

			// Move uploaded file to DevNull
			file, _, _ := r.FormFile("uploaded_file")
			defer file.Close()
			out, err := os.Create(os.DevNull)
			if err != nil {
				log.Println(err)
			}
			defer out.Close()
			_, err = io.Copy(out, file)
			if err != nil {
				log.Println(err)
			}

			// Respond with JSON that server requires HTTPS and correct path.
			w.Header().Set("X-Content-Type-Options", "nosniff")
			w.Header().Set("Expires", utils.ExpiresHeader())
			w.Header().Set("Content-Type", "application/json")
			fmt.Fprint(w, ur)
			return
		}

		log.Println("Redirect: ", url)
		http.Redirect(w, r, url, http.StatusFound)
	}))

	// Start server and begin listening for TLS requests
	log.Printf("Listening for \x1b[32;1mTLS\x1b[0m connections on \x1b[32;1m%s\x1b[0m\n", utils.AppCfg.TLSListenOn())
	go http.ListenAndServeTLS(utils.AppCfg.TLSListenOn(), "./tls/cert.pem", "./tls/key.pem", m)

	/******************************************
	*	INITIAL SETUP
	*
	*   Creates the initial tables
	*   Populates the default admin user
	*
	*   Potential security risks are present
	*   if this mode is left running.
	*	restart server with the "-init" flag
	*   unset.
	*
	*   usage: -init
	 */
	if *flagInit {
		fmt.Println("\x1b[31;1mInitial Setup flag (-init) has been set to \x1b[32;1mTRUE\x1b[0m")
		fmt.Println("\x1b[31;1mOnce setup is complete please restart server with this flag disabled.\x1b[0m")

		// Add default tables
		dbh.AddTables()

		su := martini.Classic()

		store := sessions.NewCookieStore([]byte(utils.AppCfg.SecretKey()))
		su.Use(sessions.Sessions("pixelrelay", store))
		su.Use(render.Renderer(render.Options{
			Directory: "templates", // Specify what path to load the templates from.
			Layout:    "layout",    // Specify a layout template. Layouts can call {{ yield }} to render the current template.
			Charset:   "UTF-8",     // Sets encoding for json and html content-types.
		}))
		su.Get("/setup", controllers.SetupAdmin)
		su.Post("/setup", binding.Bind(forms.SetupAdmin{}), binding.ErrorHandler, controllers.SetupAdminPost)
		// Start server and begin listening for requests
		log.Printf("Listening for connections on \x1b[32;1m%s\x1b[0m\n", utils.AppCfg.ListenOnSetup())

		go http.ListenAndServe(utils.AppCfg.ListenOnSetup(), su)
	}

	/******************************************
	*	MIGRATE DATABASE UPDATES
	*
	*   Migrates changes to database tables
	*
	*   You should backup the database before
	*   migrating. As there is a potential risk
	*   of data loss
	*
	*   usage: -migrate
	 */
	if *flagMigrate {
		dbh.MigrateDB()
	}

	select {}
}