<commit_before>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

package endpoint

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/codegangsta/negroni"
	"github.com/documize/community/documize/api/plugins"
	"github.com/documize/community/documize/database"
	"github.com/documize/community/documize/web"
	"github.com/documize/community/wordsmith/environment"
	"github.com/documize/community/wordsmith/log"
	"github.com/gorilla/mux"
)

const (
	// AppVersion does what it says
	// Versioning scheme major.minor where "minor" is optional
	// e.g. 1, 2, 3, 4.1, 4.2, 5, 6, 7, 7.1, 8, 9, 10, ..... 127, 127.1, 128
	AppVersion = "13.1"
)

var port, certFile, keyFile, forcePort2SSL string

func init() {
	environment.GetString(&certFile, "cert", false, "the cert.pem file used for https", nil)
	environment.GetString(&keyFile, "key", false, "the key.pem file used for https", nil)
	environment.GetString(&port, "port", false, "http/https port number", nil)
	environment.GetString(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", nil)
}

var testHost string // used during automated testing

// Serve the Documize endpoint.
func Serve(ready chan struct{}) {
	err := plugins.LibSetup()

	if err != nil {
		log.Error("Terminating before running - invalid plugin.json", err)
		os.Exit(1)
	}

	log.Info(fmt.Sprintf("Documize version %s", AppVersion))

	router := mux.NewRouter()

	router.PathPrefix("/api/public/").Handler(negroni.New(
		negroni.HandlerFunc(cors),
		negroni.Wrap(buildUnsecureRoutes()),
	))

	router.PathPrefix("/api").Handler(negroni.New(
		negroni.HandlerFunc(Authorize),
		negroni.Wrap(buildSecureRoutes()),
	))

	router.PathPrefix("/").Handler(negroni.New(
		negroni.HandlerFunc(cors),
		negroni.Wrap(AppRouter()),
	))

	n := negroni.New()
	n.Use(negroni.NewStatic(web.StaticAssetsFileSystem()))
	n.Use(negroni.HandlerFunc(cors))
	n.Use(negroni.HandlerFunc(metrics))
	n.UseHandler(router)
	ready <- struct{}{}

	if certFile == "" && keyFile == "" {
		if port == "" {
			port = "80"
		}

		log.Info("Starting non-SSL server on " + port)

		n.Run(testHost + ":" + port)
	} else {
		if port == "" {
			port = "443"
		}

		if forcePort2SSL != "" {
			log.Info("Starting non-SSL server on " + forcePort2SSL + " and redirecting to SSL server on  " + port)

			go func() {
				err := http.ListenAndServe(":"+forcePort2SSL, http.HandlerFunc(
					func(w http.ResponseWriter, req *http.Request) {
						var host = strings.Replace(req.Host, forcePort2SSL, port, 1) + req.RequestURI
						http.Redirect(w, req, "https://"+host, http.StatusMovedPermanently)
					}))
				if err != nil {
					log.Error("ListenAndServe on "+forcePort2SSL, err)
				}
			}()
		}

		log.Info("Starting SSL server on " + port + " with " + certFile + " " + keyFile)

		server := &http.Server{Addr: ":" + port, Handler: n}
		server.SetKeepAlivesEnabled(true)
		if err := server.ListenAndServeTLS(certFile, keyFile); err != nil {
			log.Error("ListenAndServeTLS on "+port, err)
		}
	}
}

func buildUnsecureRoutes() *mux.Router {
	router := mux.NewRouter()

	router.HandleFunc("/api/public/meta", GetMeta).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/public/authenticate", Authenticate).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/validate", ValidateAuthToken).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/public/forgot", ForgotUserPassword).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/reset/{token}", ResetUserPassword).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/share/{folderID}", AcceptSharedFolder).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/attachments/{orgID}/{job}/{fileID}", AttachmentDownload).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/public/version", version).Methods("GET", "OPTIONS")

	return router
}

func buildSecureRoutes() *mux.Router {
	router := mux.NewRouter()

	// Import & Convert Document
	router.HandleFunc("/api/import/folder/{folderID}", UploadConvertDocument).Methods("POST", "OPTIONS")

	// Document
	router.HandleFunc("/api/documents/{documentID}/export", GetDocumentAsDocx).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents", GetDocumentsByTag).Methods("GET", "OPTIONS").Queries("filter", "tag")
	router.HandleFunc("/api/documents", GetDocumentsByFolder).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}", GetDocument).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}", UpdateDocument).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}", DeleteDocument).Methods("DELETE", "OPTIONS")

	// Document Meta
	router.HandleFunc("/api/documents/{documentID}/meta", GetDocumentMeta).Methods("GET", "OPTIONS")

	// Document Page
	router.HandleFunc("/api/documents/{documentID}/pages/level", ChangeDocumentPageLevel).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/sequence", ChangeDocumentPageSequence).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/batch", GetDocumentPagesBatch).Methods("POST", "OPTIONS")
	// router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/revisions", GetDocumentPageRevisions).Methods("GET", "OPTIONS")
	// router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/revisions/{revisionID}", GetDocumentPageDiff).Methods("GET", "OPTIONS")
	// router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/revisions/{revisionID}", RollbackDocumentPage).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages", GetDocumentPages).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", UpdateDocumentPage).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", DeleteDocumentPage).Methods("DELETE", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", DeleteDocumentPages).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", GetDocumentPage).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages", AddDocumentPage).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/attachments", GetAttachments).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/attachments/{attachmentID}", DeleteAttachment).Methods("DELETE", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/attachments", AddAttachments).Methods("POST", "OPTIONS")

	// Document Meta
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/meta", GetDocumentPageMeta).Methods("GET", "OPTIONS")

	// Organization
	router.HandleFunc("/api/organizations/{orgID}", GetOrganization).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/organizations/{orgID}", UpdateOrganization).Methods("PUT", "OPTIONS")

	// Folder
	router.HandleFunc("/api/folders/{folderID}/move/{moveToId}", RemoveFolder).Methods("DELETE", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}/permissions", SetFolderPermissions).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}/permissions", GetFolderPermissions).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}/invitation", InviteToFolder).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/folders", GetFolderVisibility).Methods("GET", "OPTIONS").Queries("filter", "viewers")
	router.HandleFunc("/api/folders", AddFolder).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/folders", GetFolders).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}", GetFolder).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}", UpdateFolder).Methods("PUT", "OPTIONS")

	// Users
	router.HandleFunc("/api/users/{userID}/password", ChangeUserPassword).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/users/{userID}/permissions", GetUserFolderPermissions).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users", AddUser).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/users/folder/{folderID}", GetFolderUsers).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users", GetOrganizationUsers).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users/{userID}", GetUser).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users/{userID}", UpdateUser).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/users/{userID}", DeleteUser).Methods("DELETE", "OPTIONS")

	// Search
	router.HandleFunc("/api/search", SearchDocuments).Methods("GET", "OPTIONS")

	// Templates
	router.HandleFunc("/api/templates", SaveAsTemplate).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/templates", GetSavedTemplates).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/templates/stock", GetStockTemplates).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/templates/{templateID}/folder/{folderID}", StartDocumentFromStockTemplate).Methods("POST", "OPTIONS").Queries("type", "stock")
	router.HandleFunc("/api/templates/{templateID}/folder/{folderID}", StartDocumentFromSavedTemplate).Methods("POST", "OPTIONS").Queries("type", "saved")

	// Sections
	router.HandleFunc("/api/sections", GetSections).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/sections", RunSectionCommand).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/sections/refresh", RefreshSections).Methods("GET", "OPTIONS")

	return router
}

func cors(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS, PATCH")
	w.Header().Set("Access-Control-Allow-Headers", "host, content-type, accept, authorization, origin, referer, user-agent, cache-control, x-requested-with")
	w.Header().Set("Access-Control-Expose-Headers", "x-documize-version")

	if r.Method == "OPTIONS" {
		if _, err := w.Write([]byte("")); err != nil {
			log.Error("cors", err)
		}
		return
	}

	next(w, r)
}

func metrics(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Add("X-Documize-Version", AppVersion)
	w.Header().Add("Cache-Control", "no-cache")

	// if certFile != "" && keyFile != "" {
	// 	w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
	// }

	next(w, r)
}

func version(w http.ResponseWriter, r *http.Request) {
	if _, err := w.Write([]byte(AppVersion)); err != nil {
		log.Error("versionHandler", err)
	}
}

// AppRouter configures single page app handler.
func AppRouter() *mux.Router {

	router := mux.NewRouter()

	switch web.SiteMode {
	case web.SiteModeOffline:
		log.Info("Serving OFFLINE web app")
	case web.SiteModeSetup:
		log.Info("Serving SETUP web app")
		router.HandleFunc("/setup", database.Create).Methods("POST", "OPTIONS")
	case web.SiteModeBadDB:
		log.Info("Serving BAD DATABASE web app")
	default:
		log.Info("Starting web app")
	}

	router.HandleFunc("/robots.txt", GetRobots).Methods("GET", "OPTIONS")
	router.HandleFunc("/sitemap.xml", GetSitemap).Methods("GET", "OPTIONS")
	router.HandleFunc("/{rest:.*}", web.EmberHandler)

	return router
}
<commit_msg>initial commit<commit_after>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

package endpoint

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/codegangsta/negroni"
	"github.com/documize/community/documize/api/plugins"
	"github.com/documize/community/documize/database"
	"github.com/documize/community/documize/web"
	"github.com/documize/community/wordsmith/environment"
	"github.com/documize/community/wordsmith/log"
	"github.com/gorilla/mux"
)

const (
	// AppVersion does what it says
	// Versioning scheme: http://semver.org
	AppVersion = "1.0.0"
)

var port, certFile, keyFile, forcePort2SSL string

func init() {
	environment.GetString(&certFile, "cert", false, "the cert.pem file used for https", nil)
	environment.GetString(&keyFile, "key", false, "the key.pem file used for https", nil)
	environment.GetString(&port, "port", false, "http/https port number", nil)
	environment.GetString(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", nil)
}

var testHost string // used during automated testing

// Serve the Documize endpoint.
func Serve(ready chan struct{}) {
	err := plugins.LibSetup()

	if err != nil {
		log.Error("Terminating before running - invalid plugin.json", err)
		os.Exit(1)
	}

	log.Info(fmt.Sprintf("Documize version %s", AppVersion))

	router := mux.NewRouter()

	router.PathPrefix("/api/public/").Handler(negroni.New(
		negroni.HandlerFunc(cors),
		negroni.Wrap(buildUnsecureRoutes()),
	))

	router.PathPrefix("/api").Handler(negroni.New(
		negroni.HandlerFunc(Authorize),
		negroni.Wrap(buildSecureRoutes()),
	))

	router.PathPrefix("/").Handler(negroni.New(
		negroni.HandlerFunc(cors),
		negroni.Wrap(AppRouter()),
	))

	n := negroni.New()
	n.Use(negroni.NewStatic(web.StaticAssetsFileSystem()))
	n.Use(negroni.HandlerFunc(cors))
	n.Use(negroni.HandlerFunc(metrics))
	n.UseHandler(router)
	ready <- struct{}{}

	if certFile == "" && keyFile == "" {
		if port == "" {
			port = "80"
		}

		log.Info("Starting non-SSL server on " + port)

		n.Run(testHost + ":" + port)
	} else {
		if port == "" {
			port = "443"
		}

		if forcePort2SSL != "" {
			log.Info("Starting non-SSL server on " + forcePort2SSL + " and redirecting to SSL server on  " + port)

			go func() {
				err := http.ListenAndServe(":"+forcePort2SSL, http.HandlerFunc(
					func(w http.ResponseWriter, req *http.Request) {
						var host = strings.Replace(req.Host, forcePort2SSL, port, 1) + req.RequestURI
						http.Redirect(w, req, "https://"+host, http.StatusMovedPermanently)
					}))
				if err != nil {
					log.Error("ListenAndServe on "+forcePort2SSL, err)
				}
			}()
		}

		log.Info("Starting SSL server on " + port + " with " + certFile + " " + keyFile)

		server := &http.Server{Addr: ":" + port, Handler: n}
		server.SetKeepAlivesEnabled(true)
		if err := server.ListenAndServeTLS(certFile, keyFile); err != nil {
			log.Error("ListenAndServeTLS on "+port, err)
		}
	}
}

func buildUnsecureRoutes() *mux.Router {
	router := mux.NewRouter()

	router.HandleFunc("/api/public/meta", GetMeta).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/public/authenticate", Authenticate).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/validate", ValidateAuthToken).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/public/forgot", ForgotUserPassword).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/reset/{token}", ResetUserPassword).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/share/{folderID}", AcceptSharedFolder).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/public/attachments/{orgID}/{job}/{fileID}", AttachmentDownload).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/public/version", version).Methods("GET", "OPTIONS")

	return router
}

func buildSecureRoutes() *mux.Router {
	router := mux.NewRouter()

	// Import & Convert Document
	router.HandleFunc("/api/import/folder/{folderID}", UploadConvertDocument).Methods("POST", "OPTIONS")

	// Document
	router.HandleFunc("/api/documents/{documentID}/export", GetDocumentAsDocx).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents", GetDocumentsByTag).Methods("GET", "OPTIONS").Queries("filter", "tag")
	router.HandleFunc("/api/documents", GetDocumentsByFolder).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}", GetDocument).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}", UpdateDocument).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}", DeleteDocument).Methods("DELETE", "OPTIONS")

	// Document Meta
	router.HandleFunc("/api/documents/{documentID}/meta", GetDocumentMeta).Methods("GET", "OPTIONS")

	// Document Page
	router.HandleFunc("/api/documents/{documentID}/pages/level", ChangeDocumentPageLevel).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/sequence", ChangeDocumentPageSequence).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/batch", GetDocumentPagesBatch).Methods("POST", "OPTIONS")
	// router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/revisions", GetDocumentPageRevisions).Methods("GET", "OPTIONS")
	// router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/revisions/{revisionID}", GetDocumentPageDiff).Methods("GET", "OPTIONS")
	// router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/revisions/{revisionID}", RollbackDocumentPage).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages", GetDocumentPages).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", UpdateDocumentPage).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", DeleteDocumentPage).Methods("DELETE", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", DeleteDocumentPages).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}", GetDocumentPage).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/pages", AddDocumentPage).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/attachments", GetAttachments).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/attachments/{attachmentID}", DeleteAttachment).Methods("DELETE", "OPTIONS")
	router.HandleFunc("/api/documents/{documentID}/attachments", AddAttachments).Methods("POST", "OPTIONS")

	// Document Meta
	router.HandleFunc("/api/documents/{documentID}/pages/{pageID}/meta", GetDocumentPageMeta).Methods("GET", "OPTIONS")

	// Organization
	router.HandleFunc("/api/organizations/{orgID}", GetOrganization).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/organizations/{orgID}", UpdateOrganization).Methods("PUT", "OPTIONS")

	// Folder
	router.HandleFunc("/api/folders/{folderID}/move/{moveToId}", RemoveFolder).Methods("DELETE", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}/permissions", SetFolderPermissions).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}/permissions", GetFolderPermissions).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}/invitation", InviteToFolder).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/folders", GetFolderVisibility).Methods("GET", "OPTIONS").Queries("filter", "viewers")
	router.HandleFunc("/api/folders", AddFolder).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/folders", GetFolders).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}", GetFolder).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/folders/{folderID}", UpdateFolder).Methods("PUT", "OPTIONS")

	// Users
	router.HandleFunc("/api/users/{userID}/password", ChangeUserPassword).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/users/{userID}/permissions", GetUserFolderPermissions).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users", AddUser).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/users/folder/{folderID}", GetFolderUsers).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users", GetOrganizationUsers).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users/{userID}", GetUser).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/users/{userID}", UpdateUser).Methods("PUT", "OPTIONS")
	router.HandleFunc("/api/users/{userID}", DeleteUser).Methods("DELETE", "OPTIONS")

	// Search
	router.HandleFunc("/api/search", SearchDocuments).Methods("GET", "OPTIONS")

	// Templates
	router.HandleFunc("/api/templates", SaveAsTemplate).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/templates", GetSavedTemplates).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/templates/stock", GetStockTemplates).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/templates/{templateID}/folder/{folderID}", StartDocumentFromStockTemplate).Methods("POST", "OPTIONS").Queries("type", "stock")
	router.HandleFunc("/api/templates/{templateID}/folder/{folderID}", StartDocumentFromSavedTemplate).Methods("POST", "OPTIONS").Queries("type", "saved")

	// Sections
	router.HandleFunc("/api/sections", GetSections).Methods("GET", "OPTIONS")
	router.HandleFunc("/api/sections", RunSectionCommand).Methods("POST", "OPTIONS")
	router.HandleFunc("/api/sections/refresh", RefreshSections).Methods("GET", "OPTIONS")

	return router
}

func cors(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS, PATCH")
	w.Header().Set("Access-Control-Allow-Headers", "host, content-type, accept, authorization, origin, referer, user-agent, cache-control, x-requested-with")
	w.Header().Set("Access-Control-Expose-Headers", "x-documize-version")

	if r.Method == "OPTIONS" {
		if _, err := w.Write([]byte("")); err != nil {
			log.Error("cors", err)
		}
		return
	}

	next(w, r)
}

func metrics(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	w.Header().Add("X-Documize-Version", AppVersion)
	w.Header().Add("Cache-Control", "no-cache")

	// if certFile != "" && keyFile != "" {
	// 	w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
	// }

	next(w, r)
}

func version(w http.ResponseWriter, r *http.Request) {
	if _, err := w.Write([]byte(AppVersion)); err != nil {
		log.Error("versionHandler", err)
	}
}

// AppRouter configures single page app handler.
func AppRouter() *mux.Router {

	router := mux.NewRouter()

	switch web.SiteMode {
	case web.SiteModeOffline:
		log.Info("Serving OFFLINE web app")
	case web.SiteModeSetup:
		log.Info("Serving SETUP web app")
		router.HandleFunc("/setup", database.Create).Methods("POST", "OPTIONS")
	case web.SiteModeBadDB:
		log.Info("Serving BAD DATABASE web app")
	default:
		log.Info("Starting web app")
	}

	router.HandleFunc("/robots.txt", GetRobots).Methods("GET", "OPTIONS")
	router.HandleFunc("/sitemap.xml", GetSitemap).Methods("GET", "OPTIONS")
	router.HandleFunc("/{rest:.*}", web.EmberHandler)

	return router
}
<|endoftext|>


<commit_before>// Package nominatim is a geo-golang based MapRequest Nominatim geocode/reverse geocode client
package nominatim

import (
	"fmt"
	"github.com/codingsince1985/geo-golang"
	"strconv"
)

type baseUrl string

type geocodeResponse map[string]interface{}

func Geocoder() geo.Geocoder {
	return geo.Geocoder{
		baseUrl("http://open.mapquestapi.com/nominatim/v1/"),
		&geocodeResponse{},
	}
}

func (b baseUrl) GeocodeUrl(address string) string {
	return string(b) + "search.php?format=json&limit=1&q=" + address
}

func (b baseUrl) ReverseGeocodeUrl(l geo.Location) string {
	return string(b) + fmt.Sprintf("reverse.php?format=json&lat=%f&lon=%f", l.Lat, l.Lng)
}

func (r *geocodeResponse) Location() (l geo.Location) {
	if (*r)["lat"] != nil && (*r)["lon"] != nil {
		return geo.Location{parseFloat((*r)["lat"]), parseFloat((*r)["lon"])}
	}
	return
}

func (r *geocodeResponse) Address() (address string) {
	if (*r)["error"] == nil {
		address = (*r)["display_name"].(string)
	}
	return
}

func (r *geocodeResponse) ResponseObject() geo.ResponseParser {
	return r
}

func parseFloat(value interface{}) float64 {
	f, _ := strconv.ParseFloat(value.(string), 64)
	return f
}
<commit_msg>response object change<commit_after>// Package nominatim is a geo-golang based MapRequest Nominatim geocode/reverse geocode client
package nominatim

import (
	"fmt"
	"github.com/codingsince1985/geo-golang"
	"strconv"
)

type baseUrl string

type geocodeResponse struct {
	Display_Name, Lat, Lon, Error string
}

func Geocoder() geo.Geocoder {
	return geo.Geocoder{
		baseUrl("http://open.mapquestapi.com/nominatim/v1/"),
		&geocodeResponse{},
	}
}

func (b baseUrl) GeocodeUrl(address string) string {
	return string(b) + "search.php?format=json&limit=1&q=" + address
}

func (b baseUrl) ReverseGeocodeUrl(l geo.Location) string {
	return string(b) + fmt.Sprintf("reverse.php?format=json&lat=%f&lon=%f", l.Lat, l.Lng)
}

func (r *geocodeResponse) Location() (l geo.Location) {
	if r.Error == "" {
		l = geo.Location{parseFloat(r.Lat), parseFloat(r.Lon)}
	}
	return
}

func (r *geocodeResponse) Address() (address string) {
	if r.Error == "" {
		address = r.Display_Name
	}
	return
}

func (r *geocodeResponse) ResponseObject() geo.ResponseParser {
	return r
}

func parseFloat(value interface{}) float64 {
	f, _ := strconv.ParseFloat(value.(string), 64)
	return f
}
<|endoftext|>


<commit_before><commit_msg>veyron/services/mgmt/build: minor cleanup<commit_after><|endoftext|>


<commit_before>package services

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"
	"errors"
	"strings"

	datatypes "github.com/TheWeatherCompany/softlayer-go/data_types"
	softlayer "github.com/TheWeatherCompany/softlayer-go/softlayer"
	"os"
)

const (
	OUTLET_PACKAGE = "OUTLET"
)

type softLayer_Product_Package_Service struct {
	client softlayer.Client
}

func NewSoftLayer_Product_Package_Service(client softlayer.Client) *softLayer_Product_Package_Service {
	return &softLayer_Product_Package_Service{
		client: client,
	}
}

func (slpp *softLayer_Product_Package_Service) GetName() string {
	return "SoftLayer_Product_Package"
}

func (slpp *softLayer_Product_Package_Service) GetItemPrices(packageId int) ([]datatypes.SoftLayer_Item_Price, error) {
	response, err := slpp.client.DoRawHttpRequestWithObjectMask(fmt.Sprintf("%s/%d/getItemPrices.json", slpp.GetName(), packageId), []string{"id", "item.id", "item.description", "item.capacity"}, "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	itemPrices := []datatypes.SoftLayer_Item_Price{}
	err = json.Unmarshal(response, &itemPrices)
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	return itemPrices, nil
}

func (slpp *softLayer_Product_Package_Service) GetItemPricesBySize(packageId int, size int) ([]datatypes.SoftLayer_Item_Price, error) {
	keyName := strconv.Itoa(size) + "_GB_PERFORMANCE_STORAGE_SPACE"
	filter := string(`{"itemPrices":{"item":{"keyName":{"operation":"` + keyName + `"}}}}`)

	response, err := slpp.client.DoRawHttpRequestWithObjectFilterAndObjectMask(fmt.Sprintf("%s/%d/getItemPrices.json", slpp.GetName(), packageId), []string{"id", "locationGroupId", "item.id", "item.keyName", "item.units", "item.description", "item.capacity"}, fmt.Sprintf(string(filter)), "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	itemPrices := []datatypes.SoftLayer_Item_Price{}
	err = json.Unmarshal(response, &itemPrices)
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	return itemPrices, nil
}

func (slpp *softLayer_Product_Package_Service) GetItemsByType(packageType string) ([]datatypes.SoftLayer_Product_Item, error) {

	productPackage, err := slpp.GetOnePackageByType(packageType)
	if err != nil {
		return []datatypes.SoftLayer_Product_Item{}, err
	}

	return slpp.GetItems(productPackage.Id)
}

func (slpp *softLayer_Product_Package_Service) GetItems(packageId int) ([]datatypes.SoftLayer_Product_Item, error) {

	objectMasks := []string{
		"id",
		"capacity",
		"description",
		"prices.id",
		"prices.categories.id",
		"prices.categories.name",
	}

	response, err := slpp.client.DoRawHttpRequestWithObjectMask(fmt.Sprintf("%s/%d/getItems.json", slpp.GetName(), packageId), objectMasks, "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.SoftLayer_Product_Item{}, err
	}

	productItems := []datatypes.SoftLayer_Product_Item{}
	err = json.Unmarshal(response, &productItems)
	if err != nil {
		return []datatypes.SoftLayer_Product_Item{}, err
	}

	return productItems, nil
}

func (slpp *softLayer_Product_Package_Service) GetOnePackageByType(packageType string) (datatypes.Softlayer_Product_Package, error) {

	productPackages, err := slpp.GetPackagesByType(packageType)
	if err != nil {
		return datatypes.Softlayer_Product_Package{}, err
	}

	if len(productPackages) == 0 {
		return datatypes.Softlayer_Product_Package{}, errors.New(fmt.Sprintf("No packages available for type '%s'.", packageType))
	}

	return productPackages[0], nil
}

func (slpp *softLayer_Product_Package_Service) GetPackagesByType(packageType string) ([]datatypes.Softlayer_Product_Package, error) {

	objectMasks := []string{
		"id",
		"name",
		"description",
		"isActive",
		"type.keyName",
	}

	filterObject := string(`{"type":{"keyName":{"operation":"` + packageType + `"}}}`)

	response, err := slpp.client.DoRawHttpRequestWithObjectFilterAndObjectMask(fmt.Sprintf("%s/getAllObjects.json", slpp.GetName()), objectMasks, filterObject, "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.Softlayer_Product_Package{}, err
	}

	productPackages := []*datatypes.Softlayer_Product_Package{}
	err = json.Unmarshal(response, &productPackages)
	if err != nil {
		return []datatypes.Softlayer_Product_Package{}, err
	}

	// Remove packages designated as OUTLET
	nonOutletPackages := slpp.filterProducts(productPackages, func(productPackage *datatypes.Softlayer_Product_Package) bool {
		return !strings.Contains(productPackage.Description, OUTLET_PACKAGE) && !strings.Contains(productPackage.Name, OUTLET_PACKAGE)
	})

	return nonOutletPackages, nil
}

// Utility method for filtering product packages using provided predicate
func (slpp *softLayer_Product_Package_Service) filterProducts(array []*datatypes.Softlayer_Product_Package, predicate func(*datatypes.Softlayer_Product_Package) bool) []datatypes.Softlayer_Product_Package {
    filtered := make([]datatypes.Softlayer_Product_Package, 0)
    for _, element := range array {
        if predicate(element) {
            filtered = append(filtered, *element)
        }
	}
    return filtered
}

<commit_msg>#4 Tiny changes in the imports<commit_after>package services

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"
	"errors"
	"strings"

	datatypes "github.com/TheWeatherCompany/softlayer-go/data_types"
	softlayer "github.com/TheWeatherCompany/softlayer-go/softlayer"
)

const (
	OUTLET_PACKAGE = "OUTLET"
)

type softLayer_Product_Package_Service struct {
	client softlayer.Client
}

func NewSoftLayer_Product_Package_Service(client softlayer.Client) *softLayer_Product_Package_Service {
	return &softLayer_Product_Package_Service{
		client: client,
	}
}

func (slpp *softLayer_Product_Package_Service) GetName() string {
	return "SoftLayer_Product_Package"
}

func (slpp *softLayer_Product_Package_Service) GetItemPrices(packageId int) ([]datatypes.SoftLayer_Item_Price, error) {
	response, err := slpp.client.DoRawHttpRequestWithObjectMask(fmt.Sprintf("%s/%d/getItemPrices.json", slpp.GetName(), packageId), []string{"id", "item.id", "item.description", "item.capacity"}, "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	itemPrices := []datatypes.SoftLayer_Item_Price{}
	err = json.Unmarshal(response, &itemPrices)
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	return itemPrices, nil
}

func (slpp *softLayer_Product_Package_Service) GetItemPricesBySize(packageId int, size int) ([]datatypes.SoftLayer_Item_Price, error) {
	keyName := strconv.Itoa(size) + "_GB_PERFORMANCE_STORAGE_SPACE"
	filter := string(`{"itemPrices":{"item":{"keyName":{"operation":"` + keyName + `"}}}}`)

	response, err := slpp.client.DoRawHttpRequestWithObjectFilterAndObjectMask(fmt.Sprintf("%s/%d/getItemPrices.json", slpp.GetName(), packageId), []string{"id", "locationGroupId", "item.id", "item.keyName", "item.units", "item.description", "item.capacity"}, fmt.Sprintf(string(filter)), "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	itemPrices := []datatypes.SoftLayer_Item_Price{}
	err = json.Unmarshal(response, &itemPrices)
	if err != nil {
		return []datatypes.SoftLayer_Item_Price{}, err
	}

	return itemPrices, nil
}

func (slpp *softLayer_Product_Package_Service) GetItemsByType(packageType string) ([]datatypes.SoftLayer_Product_Item, error) {

	productPackage, err := slpp.GetOnePackageByType(packageType)
	if err != nil {
		return []datatypes.SoftLayer_Product_Item{}, err
	}

	return slpp.GetItems(productPackage.Id)
}

func (slpp *softLayer_Product_Package_Service) GetItems(packageId int) ([]datatypes.SoftLayer_Product_Item, error) {

	objectMasks := []string{
		"id",
		"capacity",
		"description",
		"prices.id",
		"prices.categories.id",
		"prices.categories.name",
	}

	response, err := slpp.client.DoRawHttpRequestWithObjectMask(fmt.Sprintf("%s/%d/getItems.json", slpp.GetName(), packageId), objectMasks, "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.SoftLayer_Product_Item{}, err
	}

	productItems := []datatypes.SoftLayer_Product_Item{}
	err = json.Unmarshal(response, &productItems)
	if err != nil {
		return []datatypes.SoftLayer_Product_Item{}, err
	}

	return productItems, nil
}

func (slpp *softLayer_Product_Package_Service) GetOnePackageByType(packageType string) (datatypes.Softlayer_Product_Package, error) {

	productPackages, err := slpp.GetPackagesByType(packageType)
	if err != nil {
		return datatypes.Softlayer_Product_Package{}, err
	}

	if len(productPackages) == 0 {
		return datatypes.Softlayer_Product_Package{}, errors.New(fmt.Sprintf("No packages available for type '%s'.", packageType))
	}

	return productPackages[0], nil
}

func (slpp *softLayer_Product_Package_Service) GetPackagesByType(packageType string) ([]datatypes.Softlayer_Product_Package, error) {

	objectMasks := []string{
		"id",
		"name",
		"description",
		"isActive",
		"type.keyName",
	}

	filterObject := string(`{"type":{"keyName":{"operation":"` + packageType + `"}}}`)

	response, err := slpp.client.DoRawHttpRequestWithObjectFilterAndObjectMask(fmt.Sprintf("%s/getAllObjects.json", slpp.GetName()), objectMasks, filterObject, "GET", new(bytes.Buffer))
	if err != nil {
		return []datatypes.Softlayer_Product_Package{}, err
	}

	productPackages := []*datatypes.Softlayer_Product_Package{}
	err = json.Unmarshal(response, &productPackages)
	if err != nil {
		return []datatypes.Softlayer_Product_Package{}, err
	}

	// Remove packages designated as OUTLET
	nonOutletPackages := slpp.filterProducts(productPackages, func(productPackage *datatypes.Softlayer_Product_Package) bool {
		return !strings.Contains(productPackage.Description, OUTLET_PACKAGE) && !strings.Contains(productPackage.Name, OUTLET_PACKAGE)
	})

	return nonOutletPackages, nil
}

// Utility method for filtering product packages using provided predicate
func (slpp *softLayer_Product_Package_Service) filterProducts(array []*datatypes.Softlayer_Product_Package, predicate func(*datatypes.Softlayer_Product_Package) bool) []datatypes.Softlayer_Product_Package {
    filtered := make([]datatypes.Softlayer_Product_Package, 0)
    for _, element := range array {
        if predicate(element) {
            filtered = append(filtered, *element)
        }
	}
    return filtered
}

<|endoftext|>


<commit_before>package gom

import (
	"fmt"
	"reflect"
)

type CreateSql func(TableModel) (string, []interface{})

type SqlGenerator struct {
	createSql   CreateSql
	tableModels []TableModel
}
type SqlFactory interface {
	Insert(TableModel) (string, []interface{})
	Update(TableModel) (string, []interface{})
	Replace(TableModel) (string, []interface{})
	Delete(TableModel) (string, []interface{})
	Query(TableModel) (string, []interface{})
}
type RowChooser interface {
	Scan(dest ...interface{}) error
}

type TableModel struct {
	ModelType  reflect.Type
	ModelValue reflect.Value
	TableName  string
	Columns    []Column
	Primary    Column
	Cnd        Condition
}
type Column struct {
	ColumnType reflect.Type
	ColumnName string
	FieldName  string
	IsPrimary  bool
	Auto       bool
}
type Condition interface {
	State() string
	Value() []interface{}
}
type Conditions struct {
	states string
	values []interface{}
}

func Cnd(sql string, values ...interface{}) Conditions {
	return Conditions{sql, values}
}
func (c Conditions) State() string {
	return c.states
}
func (c Conditions) Value() []interface{} {
	return c.values
}
func (c Conditions) And(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " and "
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func (c Conditions) Or(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " or "
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func splitArrays(values interface{}) []interface{} {
	var results []interface{}
	val := reflect.ValueOf(values)
	_, ptr, sli := getType(values)
	if ptr {
		val = val.Elem()
	}
	if sli {
		lens := val.Len()
		if lens > 0 {
			for i := 0; i < lens; i++ {
				datas := splitArrays(val.Index(i).Interface())
				results = append(results, datas...)
			}
		}
	} else {
		results = append(results, val.Interface())
	}
	return results

}

func makeInSql(name string, values ...interface{}) (string, []interface{}) {
	sql := name + " in ("
	var datas []interface{}
	if len(values) == 0 {
		return "", datas
	}
	datas = splitArrays(values)
	for i := 0; i < len(datas); i++ {
		if i == 0 {
			sql += " ? "
		} else {
			sql += ", ? "
		}
	}
	sql += ")"
	if debug {
		fmt.Println("make in sql was :", sql, datas)
	}
	return sql, datas
}
func (c Conditions) AndIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " and "
		}
		sql, datas := makeInSql(name, values...)
		c.states += sql
		c.values = append(c.values, datas)
	}
	return c
}

func (c Conditions) OrIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " or "
		}
		sql, datas := makeInSql(name, values...)
		c.states += sql
		c.values = append(c.values, datas)
	}
	return c
}
func (c Conditions) Sql(sql string, values ...interface{}) Conditions {
	c.states += sql
	c.values = append(c.values, values)
	return c
}

func (mo TableModel) InsertValues() []interface{} {
	var interfaces []interface{}
	results := reflect.Indirect(reflect.ValueOf(&interfaces))
	for _, column := range mo.Columns {
		vars := reflect.ValueOf(mo.ModelValue.FieldByName(column.FieldName).Interface())
		if results.Kind() == reflect.Ptr {
			results.Set(reflect.Append(results, vars.Addr()))
		} else {
			results.Set(reflect.Append(results, vars))
		}
	}
	return interfaces
}
func (m TableModel) GetPrimary() interface{} {
	return m.ModelValue.FieldByName(m.Primary.FieldName).Interface()
}
func (m TableModel) GetPrimaryCondition() Condition {
	if IsEmpty(m.GetPrimary()) || m.Primary.IsPrimary == false {
		return nil
	} else {
		return Conditions{"`" + m.Primary.ColumnName + "` = ?", []interface{}{m.GetPrimary()}}
	}
}
<commit_msg>And sql拼写错误的bug修复<commit_after>package gom

import (
	"fmt"
	"reflect"
)

type CreateSql func(TableModel) (string, []interface{})

type SqlGenerator struct {
	createSql   CreateSql
	tableModels []TableModel
}
type SqlFactory interface {
	Insert(TableModel) (string, []interface{})
	Update(TableModel) (string, []interface{})
	Replace(TableModel) (string, []interface{})
	Delete(TableModel) (string, []interface{})
	Query(TableModel) (string, []interface{})
}
type RowChooser interface {
	Scan(dest ...interface{}) error
}

type TableModel struct {
	ModelType  reflect.Type
	ModelValue reflect.Value
	TableName  string
	Columns    []Column
	Primary    Column
	Cnd        Condition
}
type Column struct {
	ColumnType reflect.Type
	ColumnName string
	FieldName  string
	IsPrimary  bool
	Auto       bool
}
type Condition interface {
	State() string
	Value() []interface{}
}
type Conditions struct {
	states string
	values []interface{}
}

func Cnd(sql string, values ...interface{}) Conditions {
	return Conditions{sql, values}
}
func (c Conditions) State() string {
	return c.states
}
func (c Conditions) Value() []interface{} {
	return c.values
}
func (c Conditions) And(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " and "
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func (c Conditions) Or(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " or "
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func splitArrays(values interface{}) []interface{} {
	var results []interface{}
	val := reflect.ValueOf(values)
	_, ptr, sli := getType(values)
	if ptr {
		val = val.Elem()
	}
	if sli {
		lens := val.Len()
		if lens > 0 {
			for i := 0; i < lens; i++ {
				datas := splitArrays(val.Index(i).Interface())
				results = append(results, datas...)
			}
		}
	} else {
		results = append(results, val.Interface())
	}
	return results

}

func makeInSql(name string, values ...interface{}) (string, []interface{}) {
	sql := name + " in ("
	var datas []interface{}
	if len(values) == 0 {
		return "", datas
	}
	datas = splitArrays(values)
	for i := 0; i < len(datas); i++ {
		if i == 0 {
			sql += " ? "
		} else {
			sql += ", ? "
		}
	}
	sql += ")"
	if debug {
		fmt.Println("make in sql was :", sql, datas)
	}
	return sql, datas
}
func (c Conditions) AndIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " and "
		}
		sql, datas := makeInSql(name, values...)
		c.states += sql
		c.values = append(c.values, datas...)
	}
	return c
}

func (c Conditions) OrIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " or "
		}
		sql, datas := makeInSql(name, values...)
		c.states += sql
		c.values = append(c.values, datas...)
	}
	return c
}
func (c Conditions) Sql(sql string, values ...interface{}) Conditions {
	c.states += sql
	c.values = append(c.values, values)
	return c
}

func (mo TableModel) InsertValues() []interface{} {
	var interfaces []interface{}
	results := reflect.Indirect(reflect.ValueOf(&interfaces))
	for _, column := range mo.Columns {
		vars := reflect.ValueOf(mo.ModelValue.FieldByName(column.FieldName).Interface())
		if results.Kind() == reflect.Ptr {
			results.Set(reflect.Append(results, vars.Addr()))
		} else {
			results.Set(reflect.Append(results, vars))
		}
	}
	return interfaces
}
func (m TableModel) GetPrimary() interface{} {
	return m.ModelValue.FieldByName(m.Primary.FieldName).Interface()
}
func (m TableModel) GetPrimaryCondition() Condition {
	if IsEmpty(m.GetPrimary()) || m.Primary.IsPrimary == false {
		return nil
	} else {
		return Conditions{"`" + m.Primary.ColumnName + "` = ?", []interface{}{m.GetPrimary()}}
	}
}
<|endoftext|>


<commit_before>package subnets

import (
	"net"
)

type bitset []byte

type stack struct {
	data []*matchNode
	idx  int
}

func newStack(size int) *stack {
	return &stack{
		data: make([]*matchNode, size),
		idx:  -1,
	}
}

func (s *stack) Push(val *matchNode) {
	s.idx++
	s.data[s.idx] = val
}

func (s *stack) Pop() (ret *matchNode) {
	ret = s.data[s.idx]
	s.idx--
	return
}

func (s *stack) Clear() {
	s.idx = -1
}

func (s bitset) Get(idx int) int {
	bdx := idx >> 3
	bmask := byte(128 >> uint(idx&7))
	if s[bdx]&bmask != 0 {
		return 1
	}
	return 0
}

type matchNode struct {
	Full  bool
	Child [2]*matchNode
}

type matcher struct {
	limit int
	root  *matchNode
	stack *stack
}

// Matcher for ipv4 address space
type IPv4Matcher struct {
	matcher
}

// Matcher for ipv6 address space
type IPv6Matcher struct {
	matcher
}

var pool []matchNode

func newNode() (ret *matchNode) {
	if len(pool) == 0 {
		pool = make([]matchNode, 1024)
	}
	ret = &pool[0]
	pool = pool[1:]
	return
}

// Create a new empty matcher for ipv4 address space.
func Newv4Matcher() *IPv4Matcher {
	return &IPv4Matcher{
		matcher: matcher{
			limit: 32,
			root:  newNode(),
		},
	}
}

// Create a new empty matcher for ipv6 address space.
func Newv6Matcher() *IPv6Matcher {
	return &IPv6Matcher{
		matcher: matcher{
			limit: 128,
			root:  newNode(),
		},
	}
}

func (me *matcher) Match(ip bitset) bool {
	now := me.root
	for idx := 0; idx < me.limit; idx++ {
		if now.Full {
			return true
		}
		next := ip.Get(idx)
		if now.Child[next] == nil {
			return false
		}
		now = now.Child[next]
	}
	return false
}

func (me *matcher) Add(ip bitset, plen int) {
	now := me.root
	// Go down to add entry.
	if me.stack == nil {
		me.stack = newStack(me.limit)
	}
	s := me.stack
	s.Clear()
	for idx := 0; idx < plen; idx++ {
		if now.Full {
			// Do not go further, since the subnet is covered.
			return
		}
		s.Push(now)
		next := ip.Get(idx)
		if now.Child[next] == nil {
			now.Child[next] = newNode()
		}
		now = now.Child[next]
	}
	now.Full = true
	for idx := 0; idx < plen; idx++ {
		now = s.Pop()
		if (now.Child[0] != nil && now.Child[0].Full) &&
			(now.Child[1] != nil && now.Child[1].Full) {
			now.Full = true
			now.Child[0], now.Child[1] = nil, nil
		} else {
			return
		}
	}
}

// Try to match an IPv4 address, returns true if the address is in one of its subnet, false otherwise.
// NOTE: please use 4 byte net.IP, net.IP4 returns 16 byte version, which can be converted using `IP.To4` method.
func (me *IPv4Matcher) Match(ipv4 net.IP) bool {
	if len(ipv4) != net.IPv4len {
		return false
	}
	return me.matcher.Match(bitset(ipv4))
}

// Add a ipv4 subnet to matcher, with network `ipv4` and prefix length `plen`.
// NOTE: please use 4 byte net.IP, net.IP4 returns 16 byte version, which can be converted using `IP.To4` method.
func (me *IPv4Matcher) Add(ipv4 net.IP, plen int) {
	if len(ipv4) != net.IPv4len || plen > net.IPv4len<<3 {
		return
	}
	me.matcher.Add(bitset(ipv4), plen)
}

// Try to match an IPv6 address, returns true if the address is in one of its subnet, false otherwise.
func (me *IPv6Matcher) Match(ipv6 net.IP) bool {
	if len(ipv6) != net.IPv6len {
		return false
	}
	return me.matcher.Match(bitset(ipv6))
}

// Add a ipv6 subnet to matcher, with network `ipv6` and prefix length `plen`.
func (me *IPv6Matcher) Add(ipv6 net.IP, plen int) {
	if len(ipv6) != net.IPv6len || plen > net.IPv6len<<3 {
		return
	}
	me.matcher.Add(bitset(ipv6), plen)
}

// Add a ipv4 subnet using IPNet interface. You can get it using net.ParseCIDR.
func (me *IPv4Matcher) AddNet(ipnet *net.IPNet) {
	if ipnet == nil {
		return
	}
	if ones, bits := ipnet.Mask.Size(); len(ipnet.IP) != net.IPv4len || (ones == 0 && bits == 0) || bits != net.IPv4len<<3 {
		return
	} else {
		me.matcher.Add(bitset(ipnet.IP), ones)
	}
}

// Add a ipv6 subnet using IPNet interface. You can get it using net.ParseCIDR.
func (me *IPv6Matcher) AddNet(ipnet *net.IPNet) {
	if ipnet == nil {
		return
	}
	if ones, bits := ipnet.Mask.Size(); len(ipnet.IP) != net.IPv6len || (ones == 0 && bits == 0) || bits != net.IPv6len<<3 {
		return
	} else {
		me.matcher.Add(bitset(ipnet.IP), ones)
	}
}
<commit_msg>Some more godoc improvements.<commit_after>package subnets

import (
	"net"
)

type bitset []byte

type stack struct {
	data []*matchNode
	idx  int
}

func newStack(size int) *stack {
	return &stack{
		data: make([]*matchNode, size),
		idx:  -1,
	}
}

func (s *stack) Push(val *matchNode) {
	s.idx++
	s.data[s.idx] = val
}

func (s *stack) Pop() (ret *matchNode) {
	ret = s.data[s.idx]
	s.idx--
	return
}

func (s *stack) Clear() {
	s.idx = -1
}

func (s bitset) Get(idx int) int {
	bdx := idx >> 3
	bmask := byte(128 >> uint(idx&7))
	if s[bdx]&bmask != 0 {
		return 1
	}
	return 0
}

type matchNode struct {
	Full  bool
	Child [2]*matchNode
}

type matcher struct {
	limit int
	root  *matchNode
	stack *stack
}

// A IPv4Matcher is a matcher instance wrapper for ipv4 address space
type IPv4Matcher struct {
	matcher
}

// A IPv6Matcher is a matcher instance wrapper for ipv6 address space
type IPv6Matcher struct {
	matcher
}

var pool []matchNode

func newNode() (ret *matchNode) {
	if len(pool) == 0 {
		pool = make([]matchNode, 1024)
	}
	ret = &pool[0]
	pool = pool[1:]
	return
}

// Newv4Matcher creates a new empty matcher for ipv4 address space.
func Newv4Matcher() *IPv4Matcher {
	return &IPv4Matcher{
		matcher: matcher{
			limit: 32,
			root:  newNode(),
		},
	}
}

// Newv6Matcher creates a new empty matcher for ipv6 address space.
func Newv6Matcher() *IPv6Matcher {
	return &IPv6Matcher{
		matcher: matcher{
			limit: 128,
			root:  newNode(),
		},
	}
}

func (me *matcher) Match(ip bitset) bool {
	now := me.root
	for idx := 0; idx < me.limit; idx++ {
		if now.Full {
			return true
		}
		next := ip.Get(idx)
		if now.Child[next] == nil {
			return false
		}
		now = now.Child[next]
	}
	return false
}

func (me *matcher) Add(ip bitset, plen int) {
	now := me.root
	// Go down to add entry.
	if me.stack == nil {
		me.stack = newStack(me.limit)
	}
	s := me.stack
	s.Clear()
	for idx := 0; idx < plen; idx++ {
		if now.Full {
			// Do not go further, since the subnet is covered.
			return
		}
		s.Push(now)
		next := ip.Get(idx)
		if now.Child[next] == nil {
			now.Child[next] = newNode()
		}
		now = now.Child[next]
	}
	now.Full = true
	for idx := 0; idx < plen; idx++ {
		now = s.Pop()
		if (now.Child[0] != nil && now.Child[0].Full) &&
			(now.Child[1] != nil && now.Child[1].Full) {
			now.Full = true
			now.Child[0], now.Child[1] = nil, nil
		} else {
			return
		}
	}
}

// Match tries to match an IPv4 address, returns true if the address is in one of its subnet, false otherwise.
// NOTE: please use 4 byte net.IP, net.IP4 returns 16 byte version, which can be converted using `IP.To4` method.
func (me *IPv4Matcher) Match(ipv4 net.IP) bool {
	if len(ipv4) != net.IPv4len {
		return false
	}
	return me.matcher.Match(bitset(ipv4))
}

// Add a ipv4 subnet to matcher, with network `ipv4` and prefix length `plen`.
// NOTE: please use 4 byte net.IP, net.IP4 returns 16 byte version, which can be converted using `IP.To4` method.
func (me *IPv4Matcher) Add(ipv4 net.IP, plen int) {
	if len(ipv4) != net.IPv4len || plen > net.IPv4len<<3 {
		return
	}
	me.matcher.Add(bitset(ipv4), plen)
}

// Match tries to match an IPv6 address, returns true if the address is in one of its subnet, false otherwise.
func (me *IPv6Matcher) Match(ipv6 net.IP) bool {
	if len(ipv6) != net.IPv6len {
		return false
	}
	return me.matcher.Match(bitset(ipv6))
}

// Add a ipv6 subnet to matcher, with network `ipv6` and prefix length `plen`.
func (me *IPv6Matcher) Add(ipv6 net.IP, plen int) {
	if len(ipv6) != net.IPv6len || plen > net.IPv6len<<3 {
		return
	}
	me.matcher.Add(bitset(ipv6), plen)
}

// AddNet is a wrapper for Add using IPNet interface. You can get it using net.ParseCIDR.
func (me *IPv4Matcher) AddNet(ipnet *net.IPNet) {
	if ipnet == nil {
		return
	}
	if ones, bits := ipnet.Mask.Size(); len(ipnet.IP) != net.IPv4len || (ones == 0 && bits == 0) || bits != net.IPv4len<<3 {
		return
	} else {
		me.matcher.Add(bitset(ipnet.IP), ones)
	}
}

// AddNet is a wrapper for Add using IPNet interface. You can get it using net.ParseCIDR.
func (me *IPv6Matcher) AddNet(ipnet *net.IPNet) {
	if ipnet == nil {
		return
	}
	if ones, bits := ipnet.Mask.Size(); len(ipnet.IP) != net.IPv6len || (ones == 0 && bits == 0) || bits != net.IPv6len<<3 {
		return
	} else {
		me.matcher.Add(bitset(ipnet.IP), ones)
	}
}
<|endoftext|>


<commit_before>// Package afutil includes utility functions for afto.
package afutil

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"

	"github.com/hako/afto/deb"
	"github.com/hako/afto/release"
)

var (
	debFilesNotFound = "No .deb file(s) found. Unable to continue."
	debFileNotFound  = " not found. Unable to continue."
)

// ParseDir checks to see if a directory has the required files for a cydia repo.
// might move to separate util package.
func ParseDir(indir string) (bool, error) {
	var reqfiles = []string{"Packages", "Release"}
	var valid = false
	var reqcount = 0

	files, err := ioutil.ReadDir(indir)
	if err != nil {
		return valid, errors.New("directory " + indir + " not found or valid.")
	}
	for _, file := range files {
		for _, reqfile := range reqfiles {
			if file.Name() == reqfile {
				reqcount++
			}
		}
	}

	if reqcount < len(reqfiles) {
		count := len(reqfiles) - reqcount
		return valid, errors.New(strconv.Itoa(count) + " required files missing. (Need Packages and Release)")
	}
	valid = true
	return valid, nil
}

// CheckDPKG checks the host system has the dpkg command installed.
func CheckDPKG() error {
	_, err := exec.LookPath("dpkg")
	if err != nil {
		return errors.New("Unable to find required command 'dpkg'")
	}
	return nil
}

// CheckBzip2 checks the host system has the bzip2 command installed. (Sometimes this happens.)
func CheckBzip2() error {
	_, err := exec.LookPath("bzip2")
	if err != nil {
		return errors.New("Unable to find required command 'bzip2'")
	}
	return nil
}

// GetRepo checks if the string dir matches a valid repo in the current directory.
// This can be from a name or a path.
func GetRepo(dir string) (string, error) {
	// Check if the input directory has the valid files for a cydia repo.
	_, direrr := ParseDir(dir)
	if direrr != nil {
		return "", errors.New(direrr.Error())
	}

	// Get the absolute path from dir.
	finalPath, abserr := filepath.Abs(dir)
	if abserr != nil {
		return "", errors.New(abserr.Error())
	}

	return finalPath, nil
}

// ParseDeb parses a deb file and returns a *deb.Control struct.
func ParseDeb(debName string) (*deb.Control, error) {
	// Run dpkg --field *.deb
	fields, parseerr := exec.Command("dpkg", "-f", debName).Output()
	if parseerr != nil {
		return nil, parseerr
	}
	c := deb.NewControl()
	controlFile, errs := c.ParseString(string(fields))
	if errs != nil {
		return nil, errs
	}

	return controlFile, nil
}

// BzipPackages compresses the 'Packages' file Pacakges.bz2.
// Note: The stlib package "compress/bzip2" does not support compression.
func BzipPackages() error {
	// Run bzip2 -kf Packages.
	_, bzcmderr := exec.Command("bzip2", "-kf", "Packages").Output()
	if bzcmderr != nil {
		return bzcmderr
	}
	return nil
}

// CheckDeb checks if the user has deb files ready to go to the repo.
func CheckDeb() ([]string, error) {
	cwdir, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	files, err := ioutil.ReadDir(cwdir)
	if err != nil {
		return nil, err
	}

	var deb []string
	for _, file := range files {
		if IsDeb(file.Name()) == true {
			deb = append(deb, file.Name())
		}
	}
	// Return error if ultimately no deb files are found.
	if len(deb) == 0 {
		return nil, errors.New(debFilesNotFound)
	}
	return deb, nil
}

// CheckDebWithPath is like CheckDeb but a path is required.
func CheckDebWithPath(path string) ([]string, error) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}

	var deb []string
	for _, file := range files {
		if IsDeb(file.Name()) == true {
			deb = append(deb, file.Name())
		}
	}
	// Return error if ultimately no deb files are found.
	if len(deb) == 0 {
		return nil, errors.New(debFilesNotFound)
	}
	return deb, nil
}

// CheckDebWithFile is like CheckDeb but a filepath is required.
func CheckDebWithFile(fp string) (string, error) {
	path, fperr := filepath.Abs(fp)
	if fperr != nil {
		return "", errors.New("\"" + fp + "\"" + debFileNotFound)
	}

	// Return error if the deb does not exist.
	if IsDeb(path) != true {
		return "", errors.New("\"" + fp + "\"" + debFileNotFound)
	}
	return path, nil
}

// SignRepo signs the repo's Packages and Packages.bz
func SignRepo(fp string) {

}

// IsDeb returns whether the string is a deb file with regex.
func IsDeb(filename string) bool {
	re := regexp.MustCompile(`(\.deb)`)
	return re.MatchString(filename)
}

// ReleaseFile generates a release file based on origin, label, desc codename and suite.
// It is recommended to generate this file for hosting a repo.
func ReleaseFile(origin string, label string, desc string, codename string, suite string) (string, error) {
	r := release.NewRelease()
	r.SetOrigin(origin)
	r.SetLabel(label)
	r.SetDescription(desc)
	r.SetCodename(codename)
	r.SetSuite(suite)

	// Get Packages and Packages.bz2
	packages, err := ioutil.ReadFile("Packages")
	if err != nil {
		return "", err
	}
	packagesbz, err := ioutil.ReadFile("Packages.bz2")
	if err != nil {
		return "", err
	}

	r.AddPackageSignature(packages, packagesbz)
	return r.Generate(), nil
}

// Copy copies a file from source to destination.
// Note: Copy is not in the stdlib so kudos to @elazarl
func Copy(source string, destination string) error {
	src, ferr := os.Open(source)
	if ferr != nil {
		return ferr
	}

	defer src.Close()
	dst, derr := os.Create(destination)
	if derr != nil {
		return derr
	}

	if _, err := io.Copy(dst, src); err != nil {
		dst.Close()
		return err
	}
	return dst.Close()
}

// DetectPlatform returns what host system the user is running.
func DetectPlatform() (string, error) {
	hostOS := runtime.GOOS
	switch hostOS {
	case "darwin":
		return "Since you're on a Mac, you can install dpkg via brew. \nIf you have brew installed type `brew install dpkg` and try again.", nil
	case "linux":
		return "Since you're on Linux, you can install dpkg by using `sudo apt-get install dpkg`.", nil
	case "windows":
		return "It looks like dpkg is not available on Windows. \nYou can stil use afto, you cannot build your repo without dpkg.", nil
	default:
		return "", errors.New("Unable to detect your OS.")
	}
}
<commit_msg>Implemented repo signing function<commit_after>// Package afutil includes utility functions for afto.
package afutil

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"

	"github.com/hako/afto/deb"
	"github.com/hako/afto/release"
)

var (
	debFilesNotFound = "No .deb file(s) found. Unable to continue."
	debFileNotFound  = " not found. Unable to continue."
)

// ParseDir checks to see if a directory has the required files for a cydia repo.
// might move to separate util package.
func ParseDir(indir string) (bool, error) {
	var reqfiles = []string{"Packages", "Release"}
	var valid = false
	var reqcount = 0

	files, err := ioutil.ReadDir(indir)
	if err != nil {
		return valid, errors.New("directory " + indir + " not found or valid.")
	}
	for _, file := range files {
		for _, reqfile := range reqfiles {
			if file.Name() == reqfile {
				reqcount++
			}
		}
	}

	if reqcount < len(reqfiles) {
		count := len(reqfiles) - reqcount
		return valid, errors.New(strconv.Itoa(count) + " required files missing. (Need Packages and Release)")
	}
	valid = true
	return valid, nil
}

// CheckDPKG checks the host system has the dpkg command installed.
func CheckDPKG() error {
	_, err := exec.LookPath("dpkg")
	if err != nil {
		return errors.New("Unable to find required command 'dpkg'")
	}
	return nil
}

// CheckBzip2 checks the host system has the bzip2 command installed. (Sometimes this happens.)
func CheckBzip2() error {
	_, err := exec.LookPath("bzip2")
	if err != nil {
		return errors.New("Unable to find required command 'bzip2'")
	}
	return nil
}

// GetRepo checks if the string dir matches a valid repo in the current directory.
// This can be from a name or a path.
func GetRepo(dir string) (string, error) {
	// Check if the input directory has the valid files for a cydia repo.
	_, direrr := ParseDir(dir)
	if direrr != nil {
		return "", errors.New(direrr.Error())
	}

	// Get the absolute path from dir.
	finalPath, abserr := filepath.Abs(dir)
	if abserr != nil {
		return "", errors.New(abserr.Error())
	}

	return finalPath, nil
}

// ParseDeb parses a deb file and returns a *deb.Control struct.
func ParseDeb(debName string) (*deb.Control, error) {
	// Run dpkg --field *.deb
	fields, parseerr := exec.Command("dpkg", "-f", debName).Output()
	if parseerr != nil {
		return nil, parseerr
	}
	c := deb.NewControl()
	controlFile, errs := c.ParseString(string(fields))
	if errs != nil {
		return nil, errs
	}

	return controlFile, nil
}

// BzipPackages compresses the 'Packages' file Pacakges.bz2.
// Note: The stlib package "compress/bzip2" does not support compression.
func BzipPackages() error {
	// Run bzip2 -kf Packages.
	_, bzcmderr := exec.Command("bzip2", "-kf", "Packages").Output()
	if bzcmderr != nil {
		return bzcmderr
	}
	return nil
}

// CheckDeb checks if the user has deb files ready to go to the repo.
func CheckDeb() ([]string, error) {
	cwdir, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	files, err := ioutil.ReadDir(cwdir)
	if err != nil {
		return nil, err
	}

	var deb []string
	for _, file := range files {
		if IsDeb(file.Name()) == true {
			deb = append(deb, file.Name())
		}
	}
	// Return error if ultimately no deb files are found.
	if len(deb) == 0 {
		return nil, errors.New(debFilesNotFound)
	}
	return deb, nil
}

// CheckDebWithPath is like CheckDeb but a path is required.
func CheckDebWithPath(path string) ([]string, error) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}

	var deb []string
	for _, file := range files {
		if IsDeb(file.Name()) == true {
			deb = append(deb, file.Name())
		}
	}
	// Return error if ultimately no deb files are found.
	if len(deb) == 0 {
		return nil, errors.New(debFilesNotFound)
	}
	return deb, nil
}

// CheckDebWithFile is like CheckDeb but a filepath is required.
func CheckDebWithFile(fp string) (string, error) {
	path, fperr := filepath.Abs(fp)
	if fperr != nil {
		return "", errors.New("\"" + fp + "\"" + debFileNotFound)
	}

	// Return error if the deb does not exist.
	if IsDeb(path) != true {
		return "", errors.New("\"" + fp + "\"" + debFileNotFound)
	}
	return path, nil
}

// SignRepo signs the repo's Packages and Packages.bz2 using GPG
func SignRepo(fp string) {
	path, fperr := ParseDir(fp)
	packagesCheck, err := ioutil.ReadFile("Release")
	if err != nil {
		return "", err
	}
	_, gpgerr := exec.Command("gpg", "-abs", "-o", "Release.gpg", path+"\"Release").Output()
	if gpgerr != nil {
		return gpgerr
	}
}

// IsDeb returns whether the string is a deb file with regex.
func IsDeb(filename string) bool {
	re := regexp.MustCompile(`(\.deb)`)
	return re.MatchString(filename)
}

// ReleaseFile generates a release file based on origin, label, desc codename and suite.
// It is recommended to generate this file for hosting a repo.
func ReleaseFile(origin string, label string, desc string, codename string, suite string) (string, error) {
	r := release.NewRelease()
	r.SetOrigin(origin)
	r.SetLabel(label)
	r.SetDescription(desc)
	r.SetCodename(codename)
	r.SetSuite(suite)

	// Get Packages and Packages.bz2
	packages, err := ioutil.ReadFile("Packages")
	if err != nil {
		return "", err
	}
	packagesbz, err := ioutil.ReadFile("Packages.bz2")
	if err != nil {
		return "", err
	}

	r.AddPackageSignature(packages, packagesbz)
	return r.Generate(), nil
}

// Copy copies a file from source to destination.
// Note: Copy is not in the stdlib so kudos to @elazarl
func Copy(source string, destination string) error {
	src, ferr := os.Open(source)
	if ferr != nil {
		return ferr
	}

	defer src.Close()
	dst, derr := os.Create(destination)
	if derr != nil {
		return derr
	}

	if _, err := io.Copy(dst, src); err != nil {
		dst.Close()
		return err
	}
	return dst.Close()
}

// DetectPlatform returns what host system the user is running.
func DetectPlatform() (string, error) {
	hostOS := runtime.GOOS
	switch hostOS {
	case "darwin":
		return "Since you're on a Mac, you can install dpkg via brew. \nIf you have brew installed type `brew install dpkg` and try again.", nil
	case "linux":
		return "Since you're on Linux, you can install dpkg by using `sudo apt-get install dpkg`.", nil
	case "windows":
		return "It looks like dpkg is not available on Windows. \nYou can stil use afto, you cannot build your repo without dpkg.", nil
	default:
		return "", errors.New("Unable to detect your OS.")
	}
}
<|endoftext|>


<commit_before>package agent

// You can overridden buildVersion at compile time by using:
//
//  go run -ldflags "-X github.com/buildkite/agent/agent.buildVersion abc" *.go --version
//
// On CI, the binaries are always build with the buildVersion variable set.

var baseVersion string = "2.0.3"
var buildVersion string = ""

func Version() string {
	return baseVersion
}

func BuildVersion() string {
	if buildVersion != "" {
		return buildVersion
	} else {
		return "x"
	}
}
<commit_msg>Bumped to version 2.0.4<commit_after>package agent

// You can overridden buildVersion at compile time by using:
//
//  go run -ldflags "-X github.com/buildkite/agent/agent.buildVersion abc" *.go --version
//
// On CI, the binaries are always build with the buildVersion variable set.

var baseVersion string = "2.0.4"
var buildVersion string = ""

func Version() string {
	return baseVersion
}

func BuildVersion() string {
	if buildVersion != "" {
		return buildVersion
	} else {
		return "x"
	}
}
<|endoftext|>


<commit_before>package x86

import (
	cs "github.com/bnagy/gapstone"
	uc "github.com/lunixbochs/unicorn"

    "../../models"
)

var Arch = &models.Arch{
	Bits:      32,
	Radare:    "x86",
	CS_ARCH:   cs.CS_ARCH_X86,
	CS_MODE:   cs.CS_MODE_32,
	UC_ARCH:   uc.UC_ARCH_X86,
	UC_MODE:   uc.UC_MODE_32,
	SP:        uc.UC_X86_REG_ESP,
	Syscall:   syscall,
	Interrupt: interrupt,
}

func syscall(u models.Usercorn) {

}

func interrupt(u models.Usercorn, intno uint32) {
    if intno == 0x80 {
        syscall(u)
    }
}
<commit_msg>basic working x86 syscall backend<commit_after>package x86

import (
    cs "github.com/bnagy/gapstone"
    uc "github.com/lunixbochs/unicorn"
    "fmt"
    "syscall"

    "../../models"
)

var Arch = &models.Arch{
	Bits:      32,
	Radare:    "x86",
	CS_ARCH:   cs.CS_ARCH_X86,
	CS_MODE:   cs.CS_MODE_32,
	UC_ARCH:   uc.UC_ARCH_X86,
	UC_MODE:   uc.UC_MODE_32,
	SP:        uc.UC_X86_REG_ESP,
	Syscall:   Syscall,
	Interrupt: Interrupt,
}

func Syscall(u models.Usercorn) {
    // TODO: handle errors or something
    var regs = []int{uc.UC_X86_REG_EBX, uc.UC_X86_REG_ECX, uc.UC_X86_REG_EDX, uc.UC_X86_REG_ESI, uc.UC_X86_REG_EDI, uc.UC_X86_REG_EBP}
    var args [6]uint64
    for i, r := range regs {
        n, _ := u.RegRead(r)
        args[i] = n
    }

    eax, _ := u.RegRead(uc.UC_X86_REG_EAX)
    var ret uint64
    switch eax {
    case 1: // exit
        syscall.Exit(int(args[0]))
    case 2: // fork
        // Go does not like fork
    case 3: // read
        tmp := make([]byte, args[2])
        n, _ := syscall.Read(int(args[0]), tmp)
        u.MemWrite(args[1], tmp[:n])
        ret = uint64(n)
    case 4: // write
        mem, _ := u.MemRead(args[1], args[2])
        n, _ := syscall.Write(int(args[0]), mem)
        ret = uint64(n)
    case 5: // open
        path, _ := u.MemReadStr(args[0])
        fd, _ := syscall.Open(path, int(args[1]), uint32(args[2]))
        ret = uint64(fd)
    case 6: // close
        syscall.Close(int(args[0]))
    case 19: // lseek
        off, _ := syscall.Seek(int(args[0]), int64(args[1]), int(args[2]))
        ret = uint64(off)
    case 91: // munmap
    case 192: // mmap
        addr, _ := u.Mmap(args[0], args[1])
        ret = uint64(addr)
    default:
        panic(fmt.Sprintf("unhandled syscall %d", eax))
    }
    u.RegWrite(uc.UC_X86_REG_EAX, ret)
}

func Interrupt(u models.Usercorn, intno uint32) {
    if intno == 0x80 {
        Syscall(u)
    }
}
<|endoftext|>


<commit_before>package main

import (
//	"errors"
	"fmt"

	"os"

	"github.com/abiosoft/ishell"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

type ServiceSession struct {
        Sess *session.Session
        Svc *s3.S3
}

func main () {
	profile := ""
	var sess *session.Session
	switch len(os.Args) {
		case 3:
			if os.Args[1] == "-p" {
				profile = os.Args[2]
				sess = session.Must(session.NewSessionWithOptions(session.Options{
					SharedConfigState: session.SharedConfigEnable,
					Profile: profile,
				}))
			}
		case 1:
				sess = session.Must(session.NewSessionWithOptions(session.Options{
				SharedConfigState: session.SharedConfigEnable,
				}))

		default:
			fmt.Printf("Incorrect number of command line arguments: %v\n", len(os.Args) -1)
				os.Exit(1)
	}

	pwd := "/"
	var list map [string]string
//	sess := session.Must(session.NewSessionWithOptions(session.Options{
//		SharedConfigState: session.SharedConfigEnable,
//		}))
	svc := s3.New(sess)

	shell := ishell.New()

	service := ServiceSession {sess, svc}

	//display info
	shell.Println("S3 Shell")

	shell.AddCmd(&ishell.Cmd{
		Name: "get",
		Help: "download an object",
		Func: func(c *ishell.Context){
			get (c, &pwd, &service)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "cr",
		Help: "change region",
		Func: func(c *ishell.Context){
		cr(c, &service)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "ls",
		Help: "list objects",
		Func: func(c *ishell.Context){
			list = ls (c, &pwd, &service)
			for r,v := range list {
				if len(v) > 0 {
					c.Print(v + "\t")
				}
				c.Println(r)
			}
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "desc",
		Help: "describe object's metadata",
		Func: func (c *ishell.Context) {
			obj := ""
			if len(c.Args) > 0 {
				obj = c.Args[0]
			}
			if len(obj) == 0 {
				c.Println("Please specify object name.")
				return
			}

			describe (c, svc, &pwd, obj)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "pwd",
		Help: "print current directory",
		Func: func(c *ishell.Context){
			printdir (c, &pwd)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "cd",
		Help: "change directory",
		Func: func(c *ishell.Context){
			cd(c, &pwd, &service)
		},
	})

	if len(os.Args) > 1 && os.Args[1] == "exit" {
		shell.Process(os.Args[2:]...)
	} else {
		shell.Run()
		shell.Close()
	}

}
<commit_msg>Made "ls" output sorted. Performance took a hit though.<commit_after>package main

import (
//	"errors"
	"fmt"

	"os"
	"sort"

	"github.com/abiosoft/ishell"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

type ServiceSession struct {
        Sess *session.Session
        Svc *s3.S3
}

func main () {
	profile := ""
	var sess *session.Session
	switch len(os.Args) {
		case 3:
			if os.Args[1] == "-p" {
				profile = os.Args[2]
				sess = session.Must(session.NewSessionWithOptions(session.Options{
					SharedConfigState: session.SharedConfigEnable,
					Profile: profile,
				}))
			}
		case 1:
				sess = session.Must(session.NewSessionWithOptions(session.Options{
				SharedConfigState: session.SharedConfigEnable,
				}))

		default:
			fmt.Printf("Incorrect number of command line arguments: %v\n", len(os.Args) -1)
				os.Exit(1)
	}

	pwd := "/"
	var list map [string]string
//	sess := session.Must(session.NewSessionWithOptions(session.Options{
//		SharedConfigState: session.SharedConfigEnable,
//		}))
	svc := s3.New(sess)

	shell := ishell.New()

	service := ServiceSession {sess, svc}

	//display info
	shell.Println("S3 Shell")

	shell.AddCmd(&ishell.Cmd{
		Name: "get",
		Help: "download an object",
		Func: func(c *ishell.Context){
			get (c, &pwd, &service)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "cr",
		Help: "change region",
		Func: func(c *ishell.Context){
		cr(c, &service)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "ls",
		Help: "list objects",
		Func: func(c *ishell.Context){
			list = ls (c, &pwd, &service)
			keys := make([]string, len(list))
			for r:= range list {
				keys = append(keys, r)
			}
			sort.Strings(keys)
			for r := range keys {
				if len(list[keys[r]]) > 0 {
					c.Print(list[keys[r]] + "\t")
				}
				c.Println(keys[r])
			}
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "desc",
		Help: "describe object's metadata",
		Func: func (c *ishell.Context) {
			obj := ""
			if len(c.Args) > 0 {
				obj = c.Args[0]
			}
			if len(obj) == 0 {
				c.Println("Please specify object name.")
				return
			}

			describe (c, svc, &pwd, obj)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "pwd",
		Help: "print current directory",
		Func: func(c *ishell.Context){
			printdir (c, &pwd)
		},
	})

	shell.AddCmd(&ishell.Cmd{
		Name: "cd",
		Help: "change directory",
		Func: func(c *ishell.Context){
			cd(c, &pwd, &service)
		},
	})

	if len(os.Args) > 1 && os.Args[1] == "exit" {
		shell.Process(os.Args[2:]...)
	} else {
		shell.Run()
		shell.Close()
	}

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"net/http"
)

// Fetch the url given in parameter and unmarshall the JSON to the given out struct
func fetchURL(url string, out interface{}) (err error) {
	c := new(http.Client)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return
	}
	// Add the API version in Headers
	req.Header.Add("Accept", "application/vnd.github.v3+json")
	resp, err := c.Do(req)
	defer resp.Body.Close()
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(out)
	return
}
<commit_msg>Forgot that one ._.<commit_after>package main

import (
	"encoding/json"
	"net/http"
)

// Fetch the url given in parameter and unmarshall the JSON to the given out struct
func fetchURL(url string, out interface{}) (err error) {
	c := new(http.Client)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return
	}
	// Add the API version in Headers
	req.Header.Add("Accept", "application/vnd.github.v3+json")
	resp, err := c.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(out)
	return
}
<|endoftext|>


<commit_before>/* Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

package siesta

// FetchRequest is used to fetch a chunk of one or more logs for some topic-partitions.
type FetchRequest struct {
	MaxWait     int32
	MinBytes    int32
	RequestInfo map[string][]*PartitionFetchInfo
}

// Write writes the FetchRequest to the given Encoder.
func (fr *FetchRequest) Write(encoder Encoder) {
	//Normal client consumers should always specify ReplicaId as -1 as they have no node id
	encoder.WriteInt32(-1)
	encoder.WriteInt32(fr.MaxWait)
	encoder.WriteInt32(fr.MinBytes)
	encoder.WriteInt32(int32(len(fr.RequestInfo)))

	for topic, partitionFetchInfos := range fr.RequestInfo {
		encoder.WriteString(topic)
		encoder.WriteInt32(int32(len(partitionFetchInfos)))
		for _, info := range partitionFetchInfos {
			encoder.WriteInt32(info.Partition)
			encoder.WriteInt64(info.Offset)
			encoder.WriteInt32(info.FetchSize)
		}
	}
}

// Key returns the Kafka API key for FetchRequest.
func (fr *FetchRequest) Key() int16 {
	return 1
}

// Version returns the Kafka request version for backwards compatibility.
func (fr *FetchRequest) Version() int16 {
	return 0
}

// AddFetch is a convenience method to add a PartitionFetchInfo.
func (fr *FetchRequest) AddFetch(topic string, partition int32, offset int64, fetchSize int32) {
	if fr.RequestInfo == nil {
		fr.RequestInfo = make(map[string][]*PartitionFetchInfo)
	}

	fr.RequestInfo[topic] = append(fr.RequestInfo[topic], &PartitionFetchInfo{Partition: partition, Offset: offset, FetchSize: fetchSize})
}

// FetchResponse contains FetchResponseData for all requested topics and partitions.
type FetchResponse struct {
	Data map[string]map[int32]*FetchResponsePartitionData
}

func (fr *FetchResponse) Read(decoder Decoder) *DecodingError {
	fr.Data = make(map[string]map[int32]*FetchResponsePartitionData)

	blocksLength, err := decoder.GetInt32()
	if err != nil {
		return NewDecodingError(err, reasonInvalidBlocksLength)
	}

	for i := int32(0); i < blocksLength; i++ {
		topic, err := decoder.GetString()
		if err != nil {
			return NewDecodingError(err, reasonInvalidBlockTopic)
		}
		fr.Data[topic] = make(map[int32]*FetchResponsePartitionData)

		fetchResponseDataLength, err := decoder.GetInt32()
		if err != nil {
			return NewDecodingError(err, reasonInvalidFetchResponseDataLength)
		}
		for j := int32(0); j < fetchResponseDataLength; j++ {
			partition, err := decoder.GetInt32()
			if err != nil {
				return NewDecodingError(err, reasonInvalidFetchResponseDataPartition)
			}

			fetchResponseData := new(FetchResponsePartitionData)
			decodingErr := fetchResponseData.Read(decoder)
			if decodingErr != nil {
				return decodingErr
			}

			fr.Data[topic][partition] = fetchResponseData
		}
	}

	return nil
}

// GetMessages traverses this FetchResponse and collects all messages.
// Returns an error if FetchResponse contains one.
// Messages should be ordered by offset.
func (fr *FetchResponse) GetMessages() ([]*MessageAndMetadata, error) {
	var messages []*MessageAndMetadata

	collector := func(topic string, partition int32, offset int64, key []byte, value []byte) {
		messages = append(messages, &MessageAndMetadata{
			Topic:     topic,
			Partition: partition,
			Offset:    offset,
			Key:       key,
			Value:     value,
		})
	}

	err := fr.CollectMessages(collector)
	return messages, err
}

// Error returns the error message for a given topic and pertion of this FetchResponse
func (fr *FetchResponse) Error(topic string, partition int32) error {
	t, ok := fr.Data[topic]
	if !ok {
		return nil
	}
	p, ok := t[partition]
	if !ok {
		return nil
	}
	return p.Error
}

// CollectMessages traverses this FetchResponse and applies a collector function to each message
// giving the possibility to avoid response -> siesta.Message -> other.Message conversion if necessary.
func (fr *FetchResponse) CollectMessages(collector func(topic string, partition int32, offset int64, key []byte, value []byte)) error {
	for topic, partitionAndData := range fr.Data {
		for partition, data := range partitionAndData {
			if data.Error != ErrNoError {
				return data.Error
			}
			for _, messageAndOffset := range data.Messages {
				if messageAndOffset.Message.Nested != nil {
					for _, nested := range messageAndOffset.Message.Nested {
						collector(topic, partition, nested.Offset, nested.Message.Key, nested.Message.Value)
					}
				} else {
					collector(topic, partition, messageAndOffset.Offset, messageAndOffset.Message.Key, messageAndOffset.Message.Value)
				}
			}
		}
	}

	return nil
}

// PartitionFetchInfo contains information about what partition to fetch, what offset to fetch from and the maximum bytes to include in the message set for this partition.
type PartitionFetchInfo struct {
	Partition int32
	Offset    int64
	FetchSize int32
}

// FetchResponsePartitionData contains fetched messages for a single partition, the offset at the end of the log for this partition and an error code.
type FetchResponsePartitionData struct {
	Error               error
	HighwaterMarkOffset int64
	Messages            []*MessageAndOffset
}

func (frd *FetchResponsePartitionData) Read(decoder Decoder) *DecodingError {
	errCode, err := decoder.GetInt16()
	if err != nil {
		return NewDecodingError(err, reasonInvalidFetchResponseDataErrorCode)
	}
	frd.Error = BrokerErrors[errCode]

	highwaterMarkOffset, err := decoder.GetInt64()
	if err != nil {
		return NewDecodingError(err, reasonInvalidFetchResponseDataHighwaterMarkOffset)
	}
	frd.HighwaterMarkOffset = highwaterMarkOffset

	if _, err = decoder.GetInt32(); err != nil {
		return NewDecodingError(err, reasonInvalidMessageSetLength)
	}

	messages, decodingErr := ReadMessageSet(decoder)
	if decodingErr != nil {
		return decodingErr
	}
	frd.Messages = messages

	return nil
}

const (
	reasonInvalidBlocksLength                         = "Invalid length for Blocks field"
	reasonInvalidBlockTopic                           = "Invalid topic in block"
	reasonInvalidFetchResponseDataLength              = "Invalid length for FetchResponseData field"
	reasonInvalidFetchResponseDataPartition           = "Invalid partition in FetchResponseData"
	reasonInvalidFetchResponseDataErrorCode           = "Invalid error code in FetchResponseData"
	reasonInvalidFetchResponseDataHighwaterMarkOffset = "Invalid highwater mark offset in FetchResponseData"
	reasonInvalidMessageSetLength                     = "Invalid MessageSet length"
)
<commit_msg>collector function could return an error<commit_after>/* Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

package siesta

// FetchRequest is used to fetch a chunk of one or more logs for some topic-partitions.
type FetchRequest struct {
	MaxWait     int32
	MinBytes    int32
	RequestInfo map[string][]*PartitionFetchInfo
}

// Write writes the FetchRequest to the given Encoder.
func (fr *FetchRequest) Write(encoder Encoder) {
	//Normal client consumers should always specify ReplicaId as -1 as they have no node id
	encoder.WriteInt32(-1)
	encoder.WriteInt32(fr.MaxWait)
	encoder.WriteInt32(fr.MinBytes)
	encoder.WriteInt32(int32(len(fr.RequestInfo)))

	for topic, partitionFetchInfos := range fr.RequestInfo {
		encoder.WriteString(topic)
		encoder.WriteInt32(int32(len(partitionFetchInfos)))
		for _, info := range partitionFetchInfos {
			encoder.WriteInt32(info.Partition)
			encoder.WriteInt64(info.Offset)
			encoder.WriteInt32(info.FetchSize)
		}
	}
}

// Key returns the Kafka API key for FetchRequest.
func (fr *FetchRequest) Key() int16 {
	return 1
}

// Version returns the Kafka request version for backwards compatibility.
func (fr *FetchRequest) Version() int16 {
	return 0
}

// AddFetch is a convenience method to add a PartitionFetchInfo.
func (fr *FetchRequest) AddFetch(topic string, partition int32, offset int64, fetchSize int32) {
	if fr.RequestInfo == nil {
		fr.RequestInfo = make(map[string][]*PartitionFetchInfo)
	}

	fr.RequestInfo[topic] = append(fr.RequestInfo[topic], &PartitionFetchInfo{Partition: partition, Offset: offset, FetchSize: fetchSize})
}

// FetchResponse contains FetchResponseData for all requested topics and partitions.
type FetchResponse struct {
	Data map[string]map[int32]*FetchResponsePartitionData
}

func (fr *FetchResponse) Read(decoder Decoder) *DecodingError {
	fr.Data = make(map[string]map[int32]*FetchResponsePartitionData)

	blocksLength, err := decoder.GetInt32()
	if err != nil {
		return NewDecodingError(err, reasonInvalidBlocksLength)
	}

	for i := int32(0); i < blocksLength; i++ {
		topic, err := decoder.GetString()
		if err != nil {
			return NewDecodingError(err, reasonInvalidBlockTopic)
		}
		fr.Data[topic] = make(map[int32]*FetchResponsePartitionData)

		fetchResponseDataLength, err := decoder.GetInt32()
		if err != nil {
			return NewDecodingError(err, reasonInvalidFetchResponseDataLength)
		}
		for j := int32(0); j < fetchResponseDataLength; j++ {
			partition, err := decoder.GetInt32()
			if err != nil {
				return NewDecodingError(err, reasonInvalidFetchResponseDataPartition)
			}

			fetchResponseData := new(FetchResponsePartitionData)
			decodingErr := fetchResponseData.Read(decoder)
			if decodingErr != nil {
				return decodingErr
			}

			fr.Data[topic][partition] = fetchResponseData
		}
	}

	return nil
}

// GetMessages traverses this FetchResponse and collects all messages.
// Returns an error if FetchResponse contains one.
// Messages should be ordered by offset.
func (fr *FetchResponse) GetMessages() ([]*MessageAndMetadata, error) {
	var messages []*MessageAndMetadata

	collector := func(topic string, partition int32, offset int64, key []byte, value []byte) error {
		messages = append(messages, &MessageAndMetadata{
			Topic:     topic,
			Partition: partition,
			Offset:    offset,
			Key:       key,
			Value:     value,
		})
		return nil
	}

	err := fr.CollectMessages(collector)
	return messages, err
}

// Error returns the error message for a given topic and pertion of this FetchResponse
func (fr *FetchResponse) Error(topic string, partition int32) error {
	t, ok := fr.Data[topic]
	if !ok {
		return nil
	}
	p, ok := t[partition]
	if !ok {
		return nil
	}
	return p.Error
}

// CollectMessages traverses this FetchResponse and applies a collector function to each message
// giving the possibility to avoid response -> siesta.Message -> other.Message conversion if necessary.
func (fr *FetchResponse) CollectMessages(collector func(topic string, partition int32, offset int64, key []byte, value []byte) error) error {
	for topic, partitionAndData := range fr.Data {
		for partition, data := range partitionAndData {
			if data.Error != ErrNoError {
				return data.Error
			}
			for _, messageAndOffset := range data.Messages {
				if messageAndOffset.Message.Nested != nil {
					for _, nested := range messageAndOffset.Message.Nested {
						err := collector(topic, partition, nested.Offset, nested.Message.Key, nested.Message.Value)
						if err != nil {
							return err
						}
					}
				} else {
					err := collector(topic, partition, messageAndOffset.Offset, messageAndOffset.Message.Key, messageAndOffset.Message.Value)
					if err != nil {
						return err
					}
				}
			}
		}
	}

	return nil
}

// PartitionFetchInfo contains information about what partition to fetch, what offset to fetch from and the maximum bytes to include in the message set for this partition.
type PartitionFetchInfo struct {
	Partition int32
	Offset    int64
	FetchSize int32
}

// FetchResponsePartitionData contains fetched messages for a single partition, the offset at the end of the log for this partition and an error code.
type FetchResponsePartitionData struct {
	Error               error
	HighwaterMarkOffset int64
	Messages            []*MessageAndOffset
}

func (frd *FetchResponsePartitionData) Read(decoder Decoder) *DecodingError {
	errCode, err := decoder.GetInt16()
	if err != nil {
		return NewDecodingError(err, reasonInvalidFetchResponseDataErrorCode)
	}
	frd.Error = BrokerErrors[errCode]

	highwaterMarkOffset, err := decoder.GetInt64()
	if err != nil {
		return NewDecodingError(err, reasonInvalidFetchResponseDataHighwaterMarkOffset)
	}
	frd.HighwaterMarkOffset = highwaterMarkOffset

	if _, err = decoder.GetInt32(); err != nil {
		return NewDecodingError(err, reasonInvalidMessageSetLength)
	}

	messages, decodingErr := ReadMessageSet(decoder)
	if decodingErr != nil {
		return decodingErr
	}
	frd.Messages = messages

	return nil
}

const (
	reasonInvalidBlocksLength                         = "Invalid length for Blocks field"
	reasonInvalidBlockTopic                           = "Invalid topic in block"
	reasonInvalidFetchResponseDataLength              = "Invalid length for FetchResponseData field"
	reasonInvalidFetchResponseDataPartition           = "Invalid partition in FetchResponseData"
	reasonInvalidFetchResponseDataErrorCode           = "Invalid error code in FetchResponseData"
	reasonInvalidFetchResponseDataHighwaterMarkOffset = "Invalid highwater mark offset in FetchResponseData"
	reasonInvalidMessageSetLength                     = "Invalid MessageSet length"
)
<|endoftext|>


<commit_before>package lfs

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"strconv"

	"github.com/pkg/errors"
)

// runCatFileBatch uses 'git cat-file --batch' to get the object contents of a
// git object, given its sha1. The contents will be decoded into a Git LFS
// pointer. Git Blob SHA1s are read from the sha1Ch channel and fed to STDIN.
// Results are parsed from STDOUT, and any elegible LFS pointers are sent to
// pointerCh. Any errors are sent to errCh. An error is returned if the 'git
// cat-file' command fails to start.
func runCatFileBatch(pointerCh chan *WrappedPointer, sha1Ch <-chan string, errCh chan error) error {
	cmd, err := startCommand("git", "cat-file", "--batch")
	if err != nil {
		return err
	}

	go catFileBatchOutput(pointerCh, cmd, errCh)
	go catFileBatchInput(cmd, sha1Ch, errCh)
	return nil
}

func catFileBatchOutput(pointerCh chan *WrappedPointer, cmd *wrappedCmd, errCh chan error) {
	for {
		l, err := cmd.Stdout.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				errCh <- errors.Wrap(err, "git cat-file --batch:")
			}
			break
		}

		// Line is formatted:
		// <sha1> <type> <size>
		fields := bytes.Fields(l)
		s, _ := strconv.Atoi(string(fields[2]))

		nbuf := make([]byte, s)
		_, err = io.ReadFull(cmd.Stdout, nbuf)
		if err != nil {
			break // Legit errors
		}

		p, err := DecodePointer(bytes.NewBuffer(nbuf))
		if err == nil {
			pointerCh <- &WrappedPointer{
				Sha1:    string(fields[0]),
				Size:    p.Size,
				Pointer: p,
			}
		}

		_, err = cmd.Stdout.ReadBytes('\n') // Extra \n inserted by cat-file
		if err != nil {
			if err != io.EOF {
				errCh <- errors.Wrap(err, "git cat-file --batch:")
			}
			break
		}
	}

	stderr, _ := ioutil.ReadAll(cmd.Stderr)
	err := cmd.Wait()
	if err != nil {
		errCh <- fmt.Errorf("Error in git cat-file --batch: %v %v", err, string(stderr))
	}

	close(pointerCh)
	close(errCh)
}

func catFileBatchInput(cmd *wrappedCmd, sha1Ch <-chan string, errCh chan error) {
	for r := range sha1Ch {
		cmd.Stdin.Write([]byte(r + "\n"))
	}
	cmd.Stdin.Close()
}
<commit_msg>git catfilebatch: pr feedback<commit_after>package lfs

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"strconv"

	"github.com/pkg/errors"
)

// runCatFileBatch uses 'git cat-file --batch' to get the object contents of a
// git object, given its sha1. The contents will be decoded into a Git LFS
// pointer. Git Blob SHA1s are read from the sha1Ch channel and fed to STDIN.
// Results are parsed from STDOUT, and any elegible LFS pointers are sent to
// pointerCh. Any errors are sent to errCh. An error is returned if the 'git
// cat-file' command fails to start.
func runCatFileBatch(pointerCh chan *WrappedPointer, sha1Ch <-chan string, errCh chan error) error {
	cmd, err := startCommand("git", "cat-file", "--batch")
	if err != nil {
		return err
	}

	go catFileBatchOutput(pointerCh, cmd, errCh)
	go catFileBatchInput(cmd, sha1Ch, errCh)
	return nil
}

func catFileBatchOutput(pointerCh chan *WrappedPointer, cmd *wrappedCmd, errCh chan error) {
	for {
		l, err := cmd.Stdout.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				errCh <- errors.Wrap(err, "git cat-file --batch:")
			}
			break
		}

		// Line is formatted:
		// <sha1> <type> <size>
		fields := bytes.Fields(l)
		if len(fields) < 3 {
			errCh <- errors.Wrap(fmt.Errorf("Invalid: %s", string(l)), "git cat-file --batch:")
			break
		}

		s, _ := strconv.Atoi(string(fields[2]))
		p, err := DecodePointer(io.LimitReader(cmd.Stdout, int64(s)))
		if err == nil {
			pointerCh <- &WrappedPointer{
				Sha1:    string(fields[0]),
				Size:    p.Size,
				Pointer: p,
			}
		}

		_, err = cmd.Stdout.ReadBytes('\n') // Extra \n inserted by cat-file
		if err != nil && err != io.EOF {
			errCh <- errors.Wrap(err, "git cat-file --batch:")
		}
	}

	stderr, _ := ioutil.ReadAll(cmd.Stderr)
	err := cmd.Wait()
	if err != nil {
		errCh <- fmt.Errorf("Error in git cat-file --batch: %v %v", err, string(stderr))
	}

	close(pointerCh)
	close(errCh)
}

func catFileBatchInput(cmd *wrappedCmd, sha1Ch <-chan string, errCh chan error) {
	for r := range sha1Ch {
		cmd.Stdin.Write([]byte(r + "\n"))
	}
	cmd.Stdin.Close()
}
<|endoftext|>


<commit_before>package imguploader

import (
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/util"
)

type S3Uploader struct {
	region    string
	bucket    string
	acl       string
	secretKey string
	accessKey string
	log       log.Logger
}

func NewS3Uploader(region, bucket, acl, accessKey, secretKey string) *S3Uploader {
	return &S3Uploader{
		region:    region,
		bucket:    bucket,
		acl:       acl,
		accessKey: accessKey,
		secretKey: secretKey,
		log:       log.New("s3uploader"),
	}
}

func (u *S3Uploader) Upload(imageDiskPath string) (string, error) {
	sess, err := session.NewSession()
	if err != nil {
		return "", err
	}
	creds := credentials.NewChainCredentials(
		[]credentials.Provider{
			&credentials.StaticProvider{Value: credentials.Value{
				AccessKeyID:     u.accessKey,
				SecretAccessKey: u.secretKey,
			}},
			&credentials.EnvProvider{},
			&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
		})
	cfg := &aws.Config{
		Region:      aws.String(u.region),
		Credentials: creds,
	}

	key := util.GetRandomString(20) + ".png"
	log.Debug("Uploading image to s3", "bucket = ", u.bucket, ", key = ", key)

	file, err := os.Open(imageDiskPath)
	if err != nil {
		return "", err
	}

	sess, err = session.NewSession(cfg)
	if err != nil {
		return "", err
	}
	svc := s3.New(sess, cfg)
	params := &s3.PutObjectInput{
		Bucket:      aws.String(u.bucket),
		Key:         aws.String(key),
		ACL:         aws.String(u.acl),
		Body:        file,
		ContentType: aws.String("image/png"),
	}
	_, err = svc.PutObject(params)
	if err != nil {
		return "", err
	}

	if u.region == "us-east-1" {
		return "https://" + u.bucket + ".s3.amazonaws.com/" + key, nil
	} else {
		return "https://" + u.bucket + ".s3-" + u.region + ".amazonaws.com/" + key, nil
	}
}
<commit_msg>get s3 url via aws-sdk-go, fix #9189<commit_after>package imguploader

import (
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/endpoints"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/grafana/grafana/pkg/log"
	"github.com/grafana/grafana/pkg/util"
)

type S3Uploader struct {
	region    string
	bucket    string
	acl       string
	secretKey string
	accessKey string
	log       log.Logger
}

func NewS3Uploader(region, bucket, acl, accessKey, secretKey string) *S3Uploader {
	return &S3Uploader{
		region:    region,
		bucket:    bucket,
		acl:       acl,
		accessKey: accessKey,
		secretKey: secretKey,
		log:       log.New("s3uploader"),
	}
}

func (u *S3Uploader) Upload(imageDiskPath string) (string, error) {
	sess, err := session.NewSession()
	if err != nil {
		return "", err
	}
	creds := credentials.NewChainCredentials(
		[]credentials.Provider{
			&credentials.StaticProvider{Value: credentials.Value{
				AccessKeyID:     u.accessKey,
				SecretAccessKey: u.secretKey,
			}},
			&credentials.EnvProvider{},
			&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
		})
	cfg := &aws.Config{
		Region:      aws.String(u.region),
		Credentials: creds,
	}

	s3_endpoint, _ := endpoints.DefaultResolver().EndpointFor("s3", u.region)
	key := util.GetRandomString(20) + ".png"
	image_url := s3_endpoint.URL + "/" + u.bucket + "/" + key
	log.Debug("Uploading image to s3", "url = ", image_url)

	file, err := os.Open(imageDiskPath)
	if err != nil {
		return "", err
	}

	sess, err = session.NewSession(cfg)
	if err != nil {
		return "", err
	}
	svc := s3.New(sess, cfg)
	params := &s3.PutObjectInput{
		Bucket:      aws.String(u.bucket),
		Key:         aws.String(key),
		ACL:         aws.String(u.acl),
		Body:        file,
		ContentType: aws.String("image/png"),
	}
	_, err = svc.PutObject(params)
	if err != nil {
		return "", err
	}
	return image_url, nil
}
<|endoftext|>