<commit_before>package gorm

import (
	"fmt"
	"regexp"
)

type search struct {
	db               *DB
	whereConditions  []map[string]interface{}
	orConditions     []map[string]interface{}
	notConditions    []map[string]interface{}
	havingConditions []map[string]interface{}
	joinConditions   []map[string]interface{}
	initAttrs        []interface{}
	assignAttrs      []interface{}
	selects          map[string]interface{}
	omits            []string
	orders           []interface{}
	preload          []searchPreload
	offset           interface{}
	limit            interface{}
	group            string
	tableName        string
	raw              bool
	Unscoped         bool
	ignoreOrderQuery bool
}

type searchPreload struct {
	schema     string
	conditions []interface{}
}

func (s *search) clone() *search {
	clone := *s
	return &clone
}

func (s *search) Where(query interface{}, values ...interface{}) *search {
	s.whereConditions = append(s.whereConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Not(query interface{}, values ...interface{}) *search {
	s.notConditions = append(s.notConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Or(query interface{}, values ...interface{}) *search {
	s.orConditions = append(s.orConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Attrs(attrs ...interface{}) *search {
	s.initAttrs = append(s.initAttrs, toSearchableMap(attrs...))
	return s
}

func (s *search) Assign(attrs ...interface{}) *search {
	s.assignAttrs = append(s.assignAttrs, toSearchableMap(attrs...))
	return s
}

func (s *search) Order(value interface{}, reorder ...bool) *search {
	if len(reorder) > 0 && reorder[0] {
		s.orders = []interface{}{}
	}

	if value != nil && value != "" {
		s.orders = append(s.orders, value)
	}
	return s
}

var distinctSQLRegexp = regexp.MustCompile(`(?i)distinct[^a-z]+[a-z]+`)

func (s *search) Select(query interface{}, args ...interface{}) *search {
	if distinctSQLRegexp.MatchString(fmt.Sprint(query)) {
		s.ignoreOrderQuery = true
	}

	s.selects = map[string]interface{}{"query": query, "args": args}
	return s
}

func (s *search) Omit(columns ...string) *search {
	s.omits = columns
	return s
}

func (s *search) Limit(limit interface{}) *search {
	s.limit = limit
	return s
}

func (s *search) Offset(offset interface{}) *search {
	s.offset = offset
	return s
}

func (s *search) Group(query string) *search {
	s.group = s.getInterfaceAsSQL(query)
	return s
}

func (s *search) Having(query interface{}, values ...interface{}) *search {
	if val, ok := query.(*expr); ok {
		s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": val.expr, "args": val.args})
	} else {
		s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": query, "args": values})
	}
	return s
}

func (s *search) Joins(query string, values ...interface{}) *search {
	s.joinConditions = append(s.joinConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Preload(schema string, values ...interface{}) *search {
	var preloads []searchPreload
	for _, preload := range s.preload {
		if preload.schema != schema {
			preloads = append(preloads, preload)
		}
	}
	preloads = append(preloads, searchPreload{schema, values})
	s.preload = preloads
	return s
}

func (s *search) Raw(b bool) *search {
	s.raw = b
	return s
}

func (s *search) unscoped() *search {
	s.Unscoped = true
	return s
}

func (s *search) Table(name string) *search {
	s.tableName = name
	return s
}

func (s *search) getInterfaceAsSQL(value interface{}) (str string) {
	switch value.(type) {
	case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		str = fmt.Sprintf("%v", value)
	default:
		s.db.AddError(ErrInvalidSQL)
	}

	if str == "-1" {
		return ""
	}
	return
}
<commit_msg>Do not ignore order on distinct query (#1570)<commit_after>package gorm

import (
	"fmt"
)

type search struct {
	db               *DB
	whereConditions  []map[string]interface{}
	orConditions     []map[string]interface{}
	notConditions    []map[string]interface{}
	havingConditions []map[string]interface{}
	joinConditions   []map[string]interface{}
	initAttrs        []interface{}
	assignAttrs      []interface{}
	selects          map[string]interface{}
	omits            []string
	orders           []interface{}
	preload          []searchPreload
	offset           interface{}
	limit            interface{}
	group            string
	tableName        string
	raw              bool
	Unscoped         bool
	ignoreOrderQuery bool
}

type searchPreload struct {
	schema     string
	conditions []interface{}
}

func (s *search) clone() *search {
	clone := *s
	return &clone
}

func (s *search) Where(query interface{}, values ...interface{}) *search {
	s.whereConditions = append(s.whereConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Not(query interface{}, values ...interface{}) *search {
	s.notConditions = append(s.notConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Or(query interface{}, values ...interface{}) *search {
	s.orConditions = append(s.orConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Attrs(attrs ...interface{}) *search {
	s.initAttrs = append(s.initAttrs, toSearchableMap(attrs...))
	return s
}

func (s *search) Assign(attrs ...interface{}) *search {
	s.assignAttrs = append(s.assignAttrs, toSearchableMap(attrs...))
	return s
}

func (s *search) Order(value interface{}, reorder ...bool) *search {
	if len(reorder) > 0 && reorder[0] {
		s.orders = []interface{}{}
	}

	if value != nil && value != "" {
		s.orders = append(s.orders, value)
	}
	return s
}

func (s *search) Select(query interface{}, args ...interface{}) *search {
	s.selects = map[string]interface{}{"query": query, "args": args}
	return s
}

func (s *search) Omit(columns ...string) *search {
	s.omits = columns
	return s
}

func (s *search) Limit(limit interface{}) *search {
	s.limit = limit
	return s
}

func (s *search) Offset(offset interface{}) *search {
	s.offset = offset
	return s
}

func (s *search) Group(query string) *search {
	s.group = s.getInterfaceAsSQL(query)
	return s
}

func (s *search) Having(query interface{}, values ...interface{}) *search {
	if val, ok := query.(*expr); ok {
		s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": val.expr, "args": val.args})
	} else {
		s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": query, "args": values})
	}
	return s
}

func (s *search) Joins(query string, values ...interface{}) *search {
	s.joinConditions = append(s.joinConditions, map[string]interface{}{"query": query, "args": values})
	return s
}

func (s *search) Preload(schema string, values ...interface{}) *search {
	var preloads []searchPreload
	for _, preload := range s.preload {
		if preload.schema != schema {
			preloads = append(preloads, preload)
		}
	}
	preloads = append(preloads, searchPreload{schema, values})
	s.preload = preloads
	return s
}

func (s *search) Raw(b bool) *search {
	s.raw = b
	return s
}

func (s *search) unscoped() *search {
	s.Unscoped = true
	return s
}

func (s *search) Table(name string) *search {
	s.tableName = name
	return s
}

func (s *search) getInterfaceAsSQL(value interface{}) (str string) {
	switch value.(type) {
	case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
		str = fmt.Sprintf("%v", value)
	default:
		s.db.AddError(ErrInvalidSQL)
	}

	if str == "-1" {
		return ""
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Reverse proxy tests.

package httputil

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
	"time"
)

func TestReverseProxy(t *testing.T) {
	const backendResponse = "I am the backend"
	const backendStatus = 404
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if len(r.TransferEncoding) > 0 {
			t.Errorf("backend got unexpected TransferEncoding: %v", r.TransferEncoding)
		}
		if r.Header.Get("X-Forwarded-For") == "" {
			t.Errorf("didn't get X-Forwarded-For header")
		}
		if c := r.Header.Get("Connection"); c != "" {
			t.Errorf("handler got Connection header value %q", c)
		}
		if c := r.Header.Get("Upgrade"); c != "" {
			t.Errorf("handler got Keep-Alive header value %q", c)
		}
		if g, e := r.Host, "some-name"; g != e {
			t.Errorf("backend got Host header %q, want %q", g, e)
		}
		w.Header().Set("X-Foo", "bar")
		http.SetCookie(w, &http.Cookie{Name: "flavor", Value: "chocolateChip"})
		w.WriteHeader(backendStatus)
		w.Write([]byte(backendResponse))
	}))
	defer backend.Close()
	backendURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatal(err)
	}
	proxyHandler := NewSingleHostReverseProxy(backendURL)
	frontend := httptest.NewServer(proxyHandler)
	defer frontend.Close()

	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
	getReq.Host = "some-name"
	getReq.Header.Set("Connection", "close")
	getReq.Header.Set("Upgrade", "foo")
	getReq.Close = true
	res, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if g, e := res.StatusCode, backendStatus; g != e {
		t.Errorf("got res.StatusCode %d; expected %d", g, e)
	}
	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
		t.Errorf("got X-Foo %q; expected %q", g, e)
	}
	if g, e := len(res.Header["Set-Cookie"]), 1; g != e {
		t.Fatalf("got %d SetCookies, want %d", g, e)
	}
	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
		t.Errorf("unexpected cookie %q", cookie.Name)
	}
	bodyBytes, _ := ioutil.ReadAll(res.Body)
	if g, e := string(bodyBytes), backendResponse; g != e {
		t.Errorf("got body %q; expected %q", g, e)
	}
}

func TestXForwardedFor(t *testing.T) {
	const prevForwardedFor = "client ip"
	const backendResponse = "I am the backend"
	const backendStatus = 404
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("X-Forwarded-For") == "" {
			t.Errorf("didn't get X-Forwarded-For header")
		}
		if !strings.Contains(r.Header.Get("X-Forwarded-For"), prevForwardedFor) {
			t.Errorf("X-Forwarded-For didn't contain prior data")
		}
		w.WriteHeader(backendStatus)
		w.Write([]byte(backendResponse))
	}))
	defer backend.Close()
	backendURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatal(err)
	}
	proxyHandler := NewSingleHostReverseProxy(backendURL)
	frontend := httptest.NewServer(proxyHandler)
	defer frontend.Close()

	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
	getReq.Host = "some-name"
	getReq.Header.Set("Connection", "close")
	getReq.Header.Set("X-Forwarded-For", prevForwardedFor)
	getReq.Close = true
	res, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if g, e := res.StatusCode, backendStatus; g != e {
		t.Errorf("got res.StatusCode %d; expected %d", g, e)
	}
	bodyBytes, _ := ioutil.ReadAll(res.Body)
	if g, e := string(bodyBytes), backendResponse; g != e {
		t.Errorf("got body %q; expected %q", g, e)
	}
}

var proxyQueryTests = []struct {
	baseSuffix string // suffix to add to backend URL
	reqSuffix  string // suffix to add to frontend's request URL
	want       string // what backend should see for final request URL (without ?)
}{
	{"", "", ""},
	{"?sta=tic", "?us=er", "sta=tic&us=er"},
	{"", "?us=er", "us=er"},
	{"?sta=tic", "", "sta=tic"},
}

func TestReverseProxyQuery(t *testing.T) {
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Got-Query", r.URL.RawQuery)
		w.Write([]byte("hi"))
	}))
	defer backend.Close()

	for i, tt := range proxyQueryTests {
		backendURL, err := url.Parse(backend.URL + tt.baseSuffix)
		if err != nil {
			t.Fatal(err)
		}
		frontend := httptest.NewServer(NewSingleHostReverseProxy(backendURL))
		req, _ := http.NewRequest("GET", frontend.URL+tt.reqSuffix, nil)
		req.Close = true
		res, err := http.DefaultClient.Do(req)
		if err != nil {
			t.Fatalf("%d. Get: %v", i, err)
		}
		if g, e := res.Header.Get("X-Got-Query"), tt.want; g != e {
			t.Errorf("%d. got query %q; expected %q", i, g, e)
		}
		res.Body.Close()
		frontend.Close()
	}
}

func TestReverseProxyFlushInterval(t *testing.T) {
	const expected = "hi"
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(expected))
	}))
	defer backend.Close()

	backendURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatal(err)
	}

	proxyHandler := NewSingleHostReverseProxy(backendURL)
	proxyHandler.FlushInterval = time.Microsecond

	done := make(chan bool)
	onExitFlushLoop = func() { done <- true }
	defer func() { onExitFlushLoop = nil }()

	frontend := httptest.NewServer(proxyHandler)
	defer frontend.Close()

	req, _ := http.NewRequest("GET", frontend.URL, nil)
	req.Close = true
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	defer res.Body.Close()
	if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected {
		t.Errorf("got body %q; expected %q", bodyBytes, expected)
	}

	select {
	case <-done:
		// OK
	case <-time.After(5 * time.Second):
		t.Error("maxLatencyWriter flushLoop() never exited")
	}
}
<commit_msg>net/http/httputil: fix string in test failure message<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Reverse proxy tests.

package httputil

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
	"time"
)

func TestReverseProxy(t *testing.T) {
	const backendResponse = "I am the backend"
	const backendStatus = 404
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if len(r.TransferEncoding) > 0 {
			t.Errorf("backend got unexpected TransferEncoding: %v", r.TransferEncoding)
		}
		if r.Header.Get("X-Forwarded-For") == "" {
			t.Errorf("didn't get X-Forwarded-For header")
		}
		if c := r.Header.Get("Connection"); c != "" {
			t.Errorf("handler got Connection header value %q", c)
		}
		if c := r.Header.Get("Upgrade"); c != "" {
			t.Errorf("handler got Upgrade header value %q", c)
		}
		if g, e := r.Host, "some-name"; g != e {
			t.Errorf("backend got Host header %q, want %q", g, e)
		}
		w.Header().Set("X-Foo", "bar")
		http.SetCookie(w, &http.Cookie{Name: "flavor", Value: "chocolateChip"})
		w.WriteHeader(backendStatus)
		w.Write([]byte(backendResponse))
	}))
	defer backend.Close()
	backendURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatal(err)
	}
	proxyHandler := NewSingleHostReverseProxy(backendURL)
	frontend := httptest.NewServer(proxyHandler)
	defer frontend.Close()

	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
	getReq.Host = "some-name"
	getReq.Header.Set("Connection", "close")
	getReq.Header.Set("Upgrade", "foo")
	getReq.Close = true
	res, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if g, e := res.StatusCode, backendStatus; g != e {
		t.Errorf("got res.StatusCode %d; expected %d", g, e)
	}
	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
		t.Errorf("got X-Foo %q; expected %q", g, e)
	}
	if g, e := len(res.Header["Set-Cookie"]), 1; g != e {
		t.Fatalf("got %d SetCookies, want %d", g, e)
	}
	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
		t.Errorf("unexpected cookie %q", cookie.Name)
	}
	bodyBytes, _ := ioutil.ReadAll(res.Body)
	if g, e := string(bodyBytes), backendResponse; g != e {
		t.Errorf("got body %q; expected %q", g, e)
	}
}

func TestXForwardedFor(t *testing.T) {
	const prevForwardedFor = "client ip"
	const backendResponse = "I am the backend"
	const backendStatus = 404
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("X-Forwarded-For") == "" {
			t.Errorf("didn't get X-Forwarded-For header")
		}
		if !strings.Contains(r.Header.Get("X-Forwarded-For"), prevForwardedFor) {
			t.Errorf("X-Forwarded-For didn't contain prior data")
		}
		w.WriteHeader(backendStatus)
		w.Write([]byte(backendResponse))
	}))
	defer backend.Close()
	backendURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatal(err)
	}
	proxyHandler := NewSingleHostReverseProxy(backendURL)
	frontend := httptest.NewServer(proxyHandler)
	defer frontend.Close()

	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
	getReq.Host = "some-name"
	getReq.Header.Set("Connection", "close")
	getReq.Header.Set("X-Forwarded-For", prevForwardedFor)
	getReq.Close = true
	res, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if g, e := res.StatusCode, backendStatus; g != e {
		t.Errorf("got res.StatusCode %d; expected %d", g, e)
	}
	bodyBytes, _ := ioutil.ReadAll(res.Body)
	if g, e := string(bodyBytes), backendResponse; g != e {
		t.Errorf("got body %q; expected %q", g, e)
	}
}

var proxyQueryTests = []struct {
	baseSuffix string // suffix to add to backend URL
	reqSuffix  string // suffix to add to frontend's request URL
	want       string // what backend should see for final request URL (without ?)
}{
	{"", "", ""},
	{"?sta=tic", "?us=er", "sta=tic&us=er"},
	{"", "?us=er", "us=er"},
	{"?sta=tic", "", "sta=tic"},
}

func TestReverseProxyQuery(t *testing.T) {
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Got-Query", r.URL.RawQuery)
		w.Write([]byte("hi"))
	}))
	defer backend.Close()

	for i, tt := range proxyQueryTests {
		backendURL, err := url.Parse(backend.URL + tt.baseSuffix)
		if err != nil {
			t.Fatal(err)
		}
		frontend := httptest.NewServer(NewSingleHostReverseProxy(backendURL))
		req, _ := http.NewRequest("GET", frontend.URL+tt.reqSuffix, nil)
		req.Close = true
		res, err := http.DefaultClient.Do(req)
		if err != nil {
			t.Fatalf("%d. Get: %v", i, err)
		}
		if g, e := res.Header.Get("X-Got-Query"), tt.want; g != e {
			t.Errorf("%d. got query %q; expected %q", i, g, e)
		}
		res.Body.Close()
		frontend.Close()
	}
}

func TestReverseProxyFlushInterval(t *testing.T) {
	const expected = "hi"
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(expected))
	}))
	defer backend.Close()

	backendURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatal(err)
	}

	proxyHandler := NewSingleHostReverseProxy(backendURL)
	proxyHandler.FlushInterval = time.Microsecond

	done := make(chan bool)
	onExitFlushLoop = func() { done <- true }
	defer func() { onExitFlushLoop = nil }()

	frontend := httptest.NewServer(proxyHandler)
	defer frontend.Close()

	req, _ := http.NewRequest("GET", frontend.URL, nil)
	req.Close = true
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	defer res.Body.Close()
	if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected {
		t.Errorf("got body %q; expected %q", bodyBytes, expected)
	}

	select {
	case <-done:
		// OK
	case <-time.After(5 * time.Second):
		t.Error("maxLatencyWriter flushLoop() never exited")
	}
}
<|endoftext|>


<commit_before>package seconn

import (
	"encoding/binary"
	"errors"
	"io"
	"net"

	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"

	"code.google.com/p/go.crypto/curve25519"
)

// The size of the internal encrypted write buffer
var WriteBufferSize = 128

type Conn struct {
	net.Conn
	privKey *[32]byte
	pubKey  *[32]byte
	peerKey *[32]byte
	shared  *[32]byte
	stream  cipher.Stream

	writeBuf []byte
}

// Generate new public and private keys. Automatically called by Negotiate
func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) {
	publicKey = new([32]byte)
	privateKey = new([32]byte)
	_, err = io.ReadFull(rand, privateKey[:])
	if err != nil {
		publicKey = nil
		privateKey = nil
		return
	}

	curve25519.ScalarBaseMult(publicKey, privateKey)
	return
}

// Create a new connection. Negotiate must be called before the
// connection can be used.
func NewConn(c net.Conn) (*Conn, error) {
	pub, priv, err := GenerateKey(rand.Reader)
	if err != nil {
		return nil, err
	}

	conn := &Conn{
		Conn:     c,
		privKey:  priv,
		pubKey:   pub,
		writeBuf: make([]byte, 128),
	}

	return conn, nil
}

// Create a new connection and negotiate as the client
func NewClient(u net.Conn) (*Conn, error) {
	c, err := NewConn(u)
	if err != nil {
		return nil, err
	}

	c.Negotiate(false)

	return c, nil
}

// Create a new connection and negotiate as the client
func NewServer(u net.Conn) (*Conn, error) {
	c, err := NewConn(u)
	if err != nil {
		return nil, err
	}

	c.Negotiate(true)

	return c, nil
}

// Exchange keys and setup the encryption
func (c *Conn) Negotiate(server bool) error {
	err := binary.Write(c.Conn, binary.BigEndian, uint32(len(c.pubKey)))
	if err != nil {
		return err
	}

	n, err := c.Conn.Write((*c.pubKey)[:])
	if err != nil {
		return err
	}

	if n != len(c.pubKey) {
		return io.ErrShortWrite
	}

	other := uint32(0)

	err = binary.Read(c.Conn, binary.BigEndian, &other)
	if err != nil {
		return err
	}

	c.peerKey = new([32]byte)

	n, err = c.Conn.Read((*c.peerKey)[:])
	if err != nil {
		return err
	}

	if n != len(c.peerKey) {
		return io.ErrShortBuffer
	}

	c.shared = new([32]byte)

	curve25519.ScalarMult(c.shared, c.privKey, c.peerKey)

	block, err := aes.NewCipher((*c.shared)[:])
	if err != nil {
		return err
	}

	var iv []byte

	if server {
		err = binary.Read(c.Conn, binary.BigEndian, &other)
		if err != nil {
			return err
		}

		iv = make([]byte, other)

		n, err := io.ReadFull(c.Conn, iv)
		if err != nil {
			return err
		}

		if n != int(other) {
			return io.ErrShortBuffer
		}
	} else {
		iv = make([]byte, aes.BlockSize)
		n, err := io.ReadFull(rand.Reader, iv)
		if err != nil {
			return err
		}

		if n != aes.BlockSize {
			return io.ErrShortBuffer
		}

		err = binary.Write(c.Conn, binary.BigEndian, uint32(len(iv)))
		if err != nil {
			return err
		}

		n, err = c.Conn.Write(iv)
		if err != nil {
			return err
		}

		if n != len(iv) {
			return io.ErrShortWrite
		}
	}

	stream := cipher.NewOFB(block, iv)
	if stream == nil {
		return errors.New("unable to create stream cipher")
	}

	c.stream = stream

	return nil
}

// Read data, automatically decrypting it as read
func (c *Conn) Read(buf []byte) (int, error) {
	n, err := c.Conn.Read(buf)
	if err != nil {
		return 0, err
	}

	c.stream.XORKeyStream(buf[:n], buf[:n])
	return n, err
}

// Write data, automatically encrypting it
func (c *Conn) Write(buf []byte) (int, error) {
	left := len(buf)
	cur := 0

	for {
		if left <= len(c.writeBuf) {
			c.stream.XORKeyStream(c.writeBuf, buf[cur:])

			n, err := c.Conn.Write(c.writeBuf[:left])
			if err != nil {
				return 0, err
			}

			if n != left {
				return 0, io.ErrShortWrite
			}

			break
		} else {
			c.stream.XORKeyStream(c.writeBuf, buf[cur:cur+len(c.writeBuf)])

			n, err := c.Conn.Write(c.writeBuf)
			if err != nil {
				return 0, err
			}

			if n != len(c.writeBuf) {
				return 0, io.ErrShortWrite
			}

			cur += n
			left -= n
		}
	}

	return len(buf), nil
}

// Read a message as a []byte
func (c *Conn) GetMessage() ([]byte, error) {
	l := uint32(0)

	err := binary.Read(c, binary.BigEndian, &l)
	if err != nil {
		return nil, err
	}

	buf := make([]byte, l)

	n, err := io.ReadFull(c, buf)
	if err != nil {
		return nil, err
	}

	if n != len(buf) {
		return nil, io.ErrShortBuffer
	}

	return buf, nil
}

// Write msg to the other side
func (c *Conn) SendMessage(msg []byte) error {
	err := binary.Write(c, binary.BigEndian, uint32(len(msg)))
	if err != nil {
		return err
	}

	n, err := c.Write(msg)
	if err != nil {
		return err
	}

	if n != len(msg) {
		return io.ErrShortWrite
	}

	return nil
}
<commit_msg>Need 2 streams because, well, thats how streams work<commit_after>package seconn

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"

	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"

	"code.google.com/p/go.crypto/curve25519"
)

// The size of the internal encrypted write buffer
var WriteBufferSize = 128

type Conn struct {
	net.Conn
	privKey *[32]byte
	pubKey  *[32]byte
	peerKey *[32]byte
	shared  *[32]byte
	readS   cipher.Stream
	writeS  cipher.Stream

	writeBuf []byte
}

// Generate new public and private keys. Automatically called by Negotiate
func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) {
	publicKey = new([32]byte)
	privateKey = new([32]byte)
	_, err = io.ReadFull(rand, privateKey[:])
	if err != nil {
		publicKey = nil
		privateKey = nil
		return
	}

	curve25519.ScalarBaseMult(publicKey, privateKey)
	return
}

// Create a new connection. Negotiate must be called before the
// connection can be used.
func NewConn(c net.Conn) (*Conn, error) {
	pub, priv, err := GenerateKey(rand.Reader)
	if err != nil {
		return nil, err
	}

	conn := &Conn{
		Conn:     c,
		privKey:  priv,
		pubKey:   pub,
		writeBuf: make([]byte, 128),
	}

	return conn, nil
}

// Create a new connection and negotiate as the client
func NewClient(u net.Conn) (*Conn, error) {
	c, err := NewConn(u)
	if err != nil {
		return nil, err
	}

	c.Negotiate(false)

	return c, nil
}

// Create a new connection and negotiate as the client
func NewServer(u net.Conn) (*Conn, error) {
	c, err := NewConn(u)
	if err != nil {
		return nil, err
	}

	c.Negotiate(true)

	return c, nil
}

// Exchange keys and setup the encryption
func (c *Conn) Negotiate(server bool) error {
	err := binary.Write(c.Conn, binary.BigEndian, uint32(len(c.pubKey)))
	if err != nil {
		return err
	}

	n, err := c.Conn.Write((*c.pubKey)[:])
	if err != nil {
		return err
	}

	if n != len(c.pubKey) {
		return io.ErrShortWrite
	}

	other := uint32(0)

	err = binary.Read(c.Conn, binary.BigEndian, &other)
	if err != nil {
		return err
	}

	c.peerKey = new([32]byte)

	n, err = c.Conn.Read((*c.peerKey)[:])
	if err != nil {
		return err
	}

	if n != len(c.peerKey) {
		return io.ErrShortBuffer
	}

	c.shared = new([32]byte)

	curve25519.ScalarMult(c.shared, c.privKey, c.peerKey)

	block, err := aes.NewCipher((*c.shared)[:])
	if err != nil {
		return err
	}

	var iv []byte

	if server {
		err = binary.Read(c.Conn, binary.BigEndian, &other)
		if err != nil {
			return err
		}

		iv = make([]byte, other)

		n, err := io.ReadFull(c.Conn, iv)
		if err != nil {
			return err
		}

		if n != int(other) {
			return io.ErrShortBuffer
		}
	} else {
		iv = make([]byte, aes.BlockSize)
		n, err := io.ReadFull(rand.Reader, iv)
		if err != nil {
			return err
		}

		if n != aes.BlockSize {
			return io.ErrShortBuffer
		}

		err = binary.Write(c.Conn, binary.BigEndian, uint32(len(iv)))
		if err != nil {
			return err
		}

		n, err = c.Conn.Write(iv)
		if err != nil {
			return err
		}

		if n != len(iv) {
			return io.ErrShortWrite
		}
	}

	c.readS = cipher.NewOFB(block, iv)
	if c.readS == nil {
		return errors.New("unable to create stream cipher")
	}

	c.writeS = cipher.NewOFB(block, iv)
	if c.writeS == nil {
		return errors.New("unable to create stream cipher")
	}

	return nil
}

// Read data, automatically decrypting it as read
func (c *Conn) Read(buf []byte) (int, error) {
	n, err := c.Conn.Read(buf)
	if err != nil {
		return 0, err
	}

	c.readS.XORKeyStream(buf[:n], buf[:n])

	return n, err
}

// Write data, automatically encrypting it
func (c *Conn) Write(buf []byte) (int, error) {
	left := len(buf)
	cur := 0

	fmt.Printf("writing: %#v\n", buf)

	for {
		if left <= len(c.writeBuf) {
			c.writeS.XORKeyStream(c.writeBuf, buf[cur:])

			n, err := c.Conn.Write(c.writeBuf[:left])
			if err != nil {
				return 0, err
			}

			if n != left {
				return 0, io.ErrShortWrite
			}

			break
		} else {
			c.writeS.XORKeyStream(c.writeBuf, buf[cur:cur+len(c.writeBuf)])

			n, err := c.Conn.Write(c.writeBuf)
			if err != nil {
				return 0, err
			}

			if n != len(c.writeBuf) {
				return 0, io.ErrShortWrite
			}

			cur += n
			left -= n
		}
	}

	return len(buf), nil
}

// Read a message as a []byte
func (c *Conn) GetMessage() ([]byte, error) {
	l := uint32(0)

	err := binary.Read(c, binary.BigEndian, &l)
	if err != nil {
		return nil, err
	}

	buf := make([]byte, l)

	n, err := io.ReadFull(c, buf)
	if err != nil {
		return nil, err
	}

	if n != len(buf) {
		return nil, io.ErrShortBuffer
	}

	return buf, nil
}

// Write msg to the other side
func (c *Conn) SendMessage(msg []byte) error {
	err := binary.Write(c, binary.BigEndian, uint32(len(msg)))
	if err != nil {
		return err
	}

	n, err := c.Write(msg)
	if err != nil {
		return err
	}

	if n != len(msg) {
		return io.ErrShortWrite
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sensor provides sensor events from various movement sensors.
package sensor

import (
	"errors"
	"time"
)

// Type represents a sensor type.
type Type int

var sensorNames = map[Type]string{
	Accelerometer: "Accelerometer",
	Gyroscope:     "Gyrsocope",
	Magnetometer:  "Magnetometer",
}

// String returns the string representation of the sensor type.
func (t Type) String() string {
	if n, ok := sensorNames[t]; ok {
		return n
	}
	return "Unknown sensor"
}

const (
	Accelerometer = Type(0)
	Gyroscope     = Type(1)
	Magnetometer  = Type(2)
)

// Event represents a sensor event.
type Event struct {
	// Sensor is the type of the sensor the event is coming from.
	Sensor Type

	// Timestamp is a device specific event time in nanoseconds.
	// Timestamps are not Unix times, they represent a time that is
	// only valid for the device's default sensor.
	Timestamp int64

	// Data is the event data.
	//
	// If the event source is Accelerometer,
	//  - Data[0]: acceleration force in x axis in m/s^2
	//  - Data[1]: acceleration force in y axis in m/s^2
	//  - Data[2]: acceleration force in z axis in m/s^2
	//
	// If the event source is Gyroscope,
	//  - Data[0]: rate of rotation around the x axis in rad/s
	//  - Data[1]: rate of rotation around the y axis in rad/s
	//  - Data[2]: rate of rotation around the z axis in rad/s
	//
	// If the event source is Magnetometer,
	//  - Data[0]: force of gravity along the x axis in m/s^2
	//  - Data[1]: force of gravity along the y axis in m/s^2
	//  - Data[2]: force of gravity along the z axis in m/s^2
	//
	Data []float64
}

type sender interface {
	Send(event interface{})
}

var m *manager

func Enable(s sender, t Type, delay time.Duration) error {
	if t < 0 || int(t) >= len(sensorNames) {
		return errors.New("sensor: unknown sensor type")
	}
	return m.enable(s, t, delay)
}

// Disable disables to feed the manager with the specified sensor.
func Disable(t Type) error {
	if t < 0 || int(t) >= len(sensorNames) {
		return errors.New("sensor: unknown sensor type")
	}
	return m.disable(t)
}

func init() {
	m = new(manager)
	m.initialize()
}
<commit_msg>Add TODOs.<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sensor provides sensor events from various movement sensors.
package sensor

import (
	"errors"
	"time"
)

// Type represents a sensor type.
type Type int

var sensorNames = map[Type]string{
	Accelerometer: "Accelerometer",
	Gyroscope:     "Gyrsocope",
	Magnetometer:  "Magnetometer",
}

// String returns the string representation of the sensor type.
func (t Type) String() string {
	if n, ok := sensorNames[t]; ok {
		return n
	}
	return "Unknown sensor"
}

const (
	Accelerometer = Type(0)
	Gyroscope     = Type(1)
	Magnetometer  = Type(2)
)

// Event represents a sensor event.
type Event struct {
	// Sensor is the type of the sensor the event is coming from.
	Sensor Type

	// Timestamp is a device specific event time in nanoseconds.
	// Timestamps are not Unix times, they represent a time that is
	// only valid for the device's default sensor.
	Timestamp int64

	// Data is the event data.
	//
	// If the event source is Accelerometer,
	//  - Data[0]: acceleration force in x axis in m/s^2
	//  - Data[1]: acceleration force in y axis in m/s^2
	//  - Data[2]: acceleration force in z axis in m/s^2
	//
	// If the event source is Gyroscope,
	//  - Data[0]: rate of rotation around the x axis in rad/s
	//  - Data[1]: rate of rotation around the y axis in rad/s
	//  - Data[2]: rate of rotation around the z axis in rad/s
	//
	// If the event source is Magnetometer,
	//  - Data[0]: force of gravity along the x axis in m/s^2
	//  - Data[1]: force of gravity along the y axis in m/s^2
	//  - Data[2]: force of gravity along the z axis in m/s^2
	//
	Data []float64
}

// TODO(jbd): Remove sender and couple the package with x/mobile/app?
type sender interface {
	Send(event interface{})
}

// m is the underlying platform-specific sensor manager.
var m *manager

// Enable enables the specified sensor type with the given delay rate.
// Sensor events will be sent to the s that implements Send(event interface{}).
func Enable(s sender, t Type, delay time.Duration) error {
	if t < 0 || int(t) >= len(sensorNames) {
		return errors.New("sensor: unknown sensor type")
	}
	return m.enable(s, t, delay)
}

// Disable disables to feed the manager with the specified sensor.
func Disable(t Type) error {
	if t < 0 || int(t) >= len(sensorNames) {
		return errors.New("sensor: unknown sensor type")
	}
	return m.disable(t)
}

func init() {
	m = new(manager)
	m.initialize()
}
<|endoftext|>


<commit_before>package store

import (
	"net"
	"net/rpc"
)

type Server struct {
	*rpc.Server
	ln       net.Listener
	filePath string
	store    *Store
}

func NewServer(addr string, filePath string) (*Server, error) {
	store, err := NewStore(filePath)
	if err != nil {
		return nil, err
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}
	server := &Server{
		Server:   rpc.NewServer(),
		ln:       ln,
		filePath: filePath,
		store:    store,
	}
	server.Register(store)
	go server.start()
	return server, nil
}

func (s *Server) start() {
	for {
		conn, err := s.ln.Accept()
		if err != nil {
			break
		}
		go s.ServeConn(conn)
	}
}

func (s *Server) Close() {
	s.ln.Close()
}
<commit_msg>Server fixes<commit_after>package store

import (
	"net"
	"net/rpc"
	"sync"
)

type Server struct {
	*rpc.Server
	ln        net.Listener
	filePath  string
	store     *Store
	stop      chan struct{}
	closeOnce sync.Once
}

func NewServer(addr string, filePath string) (*Server, error) {
	store, err := NewStore(filePath)
	if err != nil {
		return nil, err
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}
	server := &Server{
		Server:   rpc.NewServer(),
		ln:       ln,
		filePath: filePath,
		store:    store,
		stop:     make(chan struct{}),
	}
	server.Register(store)
	go server.accept()
	return server, nil
}

func (s *Server) accept() {
	for {
		conn, err := s.ln.Accept()
		if err != nil {
			break
		}
		go s.ServeConn(conn)
	}
	s.Close()
}

func (s *Server) Close() {
	s.ln.Close()
	s.closeOnce.Do(func() {
		close(s.stop)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"log"
	"net"
	"os"
	"sync"
	"time"

	"github.com/armon/go-socks5"
)

type server struct {
	socksAddr string
	cfg       config
	wg        sync.WaitGroup
	socks5    *socks5.Server
	errChan   chan error
	signal    chan os.Signal
	done      chan struct{}
}

func newServer(cfg config) *server {
	return &server{
		cfg:     cfg,
		errChan: make(chan error, 1),
		signal:  make(chan os.Signal),
		done:    make(chan struct{}),
	}
}

func (s *server) proxyClientConn(conn, rConn net.Conn, ch chan struct{}) {
	defer s.wg.Done()
	defer close(ch)

	var wg sync.WaitGroup
	connCopy := func(dst, src net.Conn) {
		defer wg.Done()
		nr, err := io.Copy(dst, src)
		log.Printf("[DEBUG] %d bytes has been copied", nr)
		if err != nil {
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				log.Println("[ERR] Failed to copy connection:", err)
			}
			return
		}
	}

	wg.Add(2)
	go connCopy(rConn, conn)
	go connCopy(conn, rConn)
	wg.Wait()
}

func (s *server) clientConn(conn net.Conn) {
	defer s.wg.Done()
	defer func() {
		if err := conn.Close(); err != nil {
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				// TODO: log this event
			}
		}
	}()

	rConn, err := net.Dial(s.cfg.Method, s.socksAddr)
	if err != nil {
		log.Println("[ERR] Failed to dial", s.socksAddr, err)
		return
	}
	defer func() {
		if err := rConn.Close(); err != nil {
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				// TODO: log this event
			}
		}
	}()

	ch := make(chan struct{})
	s.wg.Add(1)
	go s.proxyClientConn(conn, rConn, ch)
	select {
	case <-s.done:
		log.Print("[DEBUG] Closing client connection by force")
	case <-ch:
	}
}

func (s *server) connSocks5(conn net.Conn) {
	defer s.wg.Done()

	ch := make(chan struct{})
	s.wg.Add(1)
	go func() {
		defer s.wg.Done()
		select {
		case <-s.done:
			if err := conn.Close(); err != nil {
				if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
					// TODO: log this event
				}
			}
		case <-ch:
		}
	}()

	defer close(ch)
	if err := s.socks5.ServeConn(conn); err != nil {
		// TODO: log this error.
	}
}

func (s *server) serve(l net.Listener) {
	defer s.wg.Done()
	for {
		conn, err := l.Accept()
		if err != nil {
			// Shutdown the server immediately.
			s.shutdown()
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				s.errChan <- err
				return
			}
			s.errChan <- nil
			return
		}

		s.wg.Add(1)
		if s.cfg.Role == roleClient {
			go s.clientConn(conn)
			continue
		}
		go s.connSocks5(conn)
	}
}

func (s *server) shutdown() {
	select {
	case <-s.done:
		return
	default:
	}
	close(s.done)
}

func (s *server) run() error {
	var err error
	var host, port string
	switch {
	case s.cfg.Role == roleClient:
		host, port = s.cfg.ClientHost, s.cfg.ClientPort
	case s.cfg.Role == roleServer:
		host, port = s.cfg.ServerHost, s.cfg.ServerPort
		// Create a SOCKS5 server
		conf := &socks5.Config{}
		s.socks5, err = socks5.New(conf)
		if err != nil {
			return err
		}
	}

	addr := net.JoinHostPort(host, port)
	s.socksAddr = net.JoinHostPort(s.cfg.ServerHost, s.cfg.ServerPort)
	// Create a TCP/UDP server
	l, lerr := net.Listen(s.cfg.Method, addr)
	if lerr != nil {
		return lerr
	}

	s.wg.Add(1)
	go s.serve(l)

	log.Println("[INF] gsocks5: Proxy server runs on", addr)

	select {
	// Wait for SIGINT or SIGTERM
	case <-s.signal:
	// Wait for a listener error
	case <-s.done:
	}

	// Signal all running goroutines to stop.
	log.Println("[INF] gsocks5: Stopping proxy", addr)
	s.shutdown()

	if err = l.Close(); err != nil {
		log.Println("[ERR] gsocks5: Failed to close listener", err)
	}

	ch := make(chan struct{})
	go func() {
		defer close(ch)
		s.wg.Wait()
	}()

	select {
	case <-ch:
	case <-time.After(time.Duration(s.cfg.GracefulPeriod) * time.Second):
		log.Println("[WARN] Some goroutines will be stopped immediately")
	}

	err = <-s.errChan
	return err
}
<commit_msg>server: improve logging<commit_after>package main

import (
	"io"
	"log"
	"net"
	"os"
	"sync"
	"time"

	"github.com/armon/go-socks5"
)

type server struct {
	socksAddr string
	cfg       config
	wg        sync.WaitGroup
	socks5    *socks5.Server
	errChan   chan error
	signal    chan os.Signal
	done      chan struct{}
}

func newServer(cfg config) *server {
	return &server{
		cfg:     cfg,
		errChan: make(chan error, 1),
		signal:  make(chan os.Signal),
		done:    make(chan struct{}),
	}
}

func (s *server) proxyClientConn(conn, rConn net.Conn, ch chan struct{}) {
	defer s.wg.Done()
	defer close(ch)
	var wg sync.WaitGroup
	connCopy := func(dst, src net.Conn) {
		defer wg.Done()
		_, err := io.Copy(dst, src)
		if err != nil {
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "readfrom") {
				log.Println("[ERR] gsocks5: Failed to copy connection from",
					src.RemoteAddr(), "to", conn.RemoteAddr(), ":", err)
			}
			return
		}
	}
	wg.Add(2)
	go connCopy(rConn, conn)
	go connCopy(conn, rConn)
	wg.Wait()
}

func (s *server) clientConn(conn net.Conn) {
	defer s.wg.Done()
	defer func() {
		if err := conn.Close(); err != nil {
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				log.Println("[ERR] gsocks5: Error while closing socket", conn.RemoteAddr())
			}
		}
	}()

	rConn, err := net.Dial(s.cfg.Method, s.socksAddr)
	if err != nil {
		log.Println("[ERR] gsocks5: Failed to dial", s.socksAddr, err)
		return
	}
	defer func() {
		if err := rConn.Close(); err != nil {
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				log.Println("[ERR] gsocks5: Error while closing socket", rConn.RemoteAddr())
			}
		}
	}()

	ch := make(chan struct{})
	s.wg.Add(1)
	go s.proxyClientConn(conn, rConn, ch)
	select {
	case <-s.done:
	case <-ch:
	}
}

func (s *server) connSocks5(conn net.Conn) {
	defer s.wg.Done()

	ch := make(chan struct{})
	s.wg.Add(1)
	go func() {
		defer s.wg.Done()
		select {
		case <-s.done:
			if err := conn.Close(); err != nil {
				if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
					log.Println("[ERR] gsocks5: Error while closing socket", conn.RemoteAddr())
				}
			}
		case <-ch:
		}
	}()

	defer close(ch)
	if err := s.socks5.ServeConn(conn); err != nil {
		log.Println("[ERR] gsocks5: Failed to proxy to ", conn.RemoteAddr())
	}
}

func (s *server) serve(l net.Listener) {
	defer s.wg.Done()
	for {
		conn, err := l.Accept()
		if err != nil {
			// Shutdown the server immediately.
			s.shutdown()
			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
				s.errChan <- err
				return
			}
			s.errChan <- nil
			return
		}

		s.wg.Add(1)
		if s.cfg.Role == roleClient {
			go s.clientConn(conn)
			continue
		}
		go s.connSocks5(conn)
	}
}

func (s *server) shutdown() {
	select {
	case <-s.done:
		return
	default:
	}
	close(s.done)
}

func (s *server) run() error {
	var err error
	var host, port string
	switch {
	case s.cfg.Role == roleClient:
		host, port = s.cfg.ClientHost, s.cfg.ClientPort
	case s.cfg.Role == roleServer:
		host, port = s.cfg.ServerHost, s.cfg.ServerPort
		// Create a SOCKS5 server
		conf := &socks5.Config{}
		s.socks5, err = socks5.New(conf)
		if err != nil {
			return err
		}
	}

	addr := net.JoinHostPort(host, port)
	s.socksAddr = net.JoinHostPort(s.cfg.ServerHost, s.cfg.ServerPort)
	// Create a TCP/UDP server
	l, lerr := net.Listen(s.cfg.Method, addr)
	if lerr != nil {
		return lerr
	}

	s.wg.Add(1)
	go s.serve(l)

	log.Println("[INF] gsocks5: Proxy server runs on", addr)

	select {
	// Wait for SIGINT or SIGTERM
	case <-s.signal:
	// Wait for a listener error
	case <-s.done:
	}

	// Signal all running goroutines to stop.
	log.Println("[INF] gsocks5: Stopping proxy", addr)
	s.shutdown()

	if err = l.Close(); err != nil {
		log.Println("[ERR] gsocks5: Failed to close listener", err)
	}

	ch := make(chan struct{})
	go func() {
		defer close(ch)
		s.wg.Wait()
	}()

	select {
	case <-ch:
	case <-time.After(time.Duration(s.cfg.GracefulPeriod) * time.Second):
		log.Println("[WARN] Some goroutines will be stopped immediately")
	}

	err = <-s.errChan
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"log"
	"net/http"
	"regexp"
	"strconv"

	"golang.org/x/crypto/blowfish"
)

var (
	assets = http.FileServer(http.Dir("assets"))

	pathOld = regexp.MustCompile(`^/([0-9]{1,10})(/.*)?$`)
	pathNew = regexp.MustCompile(`^/([0-9a-f]{16})(/.*)?$`)

	cipher *blowfish.Cipher
)

func servePaste(w http.ResponseWriter, id uint64, p string) {
	paste, title, author, notes, err := getPaste(id)
	if err != nil {
		http.NotFound(w, nil)
		return
	}

	switch p {
	case "", "/":
		renderPaste(w, paste, title, author, notes)
	case "/raw":
		w.Write(paste)
	case "/json":
		json.NewEncoder(w).Encode(map[string]interface{}{
			"paste":  string(paste),
			"title":  string(title),
			"author": string(author),
			"notes":  string(notes),
		})
	default:
		http.NotFound(w, nil)
	}
}

func handle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Strict-Transport-Security", "max-age=31536000")
	w.Header().Set("Content-Security-Policy", "default-src 'self'")

	if m := pathNew.FindStringSubmatch(r.URL.Path); m != nil {
		src, err := hex.DecodeString(m[1])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		dst := make([]byte, 8)
		cipher.Decrypt(dst, src)

		id := binary.BigEndian.Uint64(dst)
		servePaste(w, id, m[2])
	} else if m := pathOld.FindStringSubmatch(r.URL.Path); m != nil {
		id, err := strconv.ParseUint(m[1], 10, 64)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if id >= 256 {
			id = (id * 0x7FFFFFFF) % 0x100000000
		}

		if id >= 1000 {
			http.Error(w, "Forbidden", http.StatusForbidden)
			return
		}

		servePaste(w, id, m[2])
	} else if r.URL.Path == "/create" {
		err := r.ParseForm()
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		paste := r.Form.Get("paste")
		if len(paste) == 0 {
			http.Error(w, "No (or Invalid) Paste", http.StatusBadRequest)
			return
		}

		title := r.Form.Get("title")
		author := r.Form.Get("author")
		notes := r.Form.Get("notes")

		id, err := postPaste(&paste, &title, &author, &notes)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		src := make([]byte, 8)
		binary.BigEndian.PutUint64(src, uint64(id))

		dst := make([]byte, 8)
		cipher.Encrypt(dst, src)

		http.Redirect(w, r, hex.EncodeToString(dst), http.StatusSeeOther)
	} else {
		assets.ServeHTTP(w, r)
	}
}

func main() {
	var err error
	cipher, err = blowfish.NewCipher(key)
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", handle)

	go http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://" + r.Host + r.RequestURI, http.StatusMovedPermanently)
	}))

	log.Fatal(http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil))
}
<commit_msg>Allow unsafe-inline styles in CSP<commit_after>package main

import (
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"log"
	"net/http"
	"regexp"
	"strconv"

	"golang.org/x/crypto/blowfish"
)

var (
	assets = http.FileServer(http.Dir("assets"))

	pathOld = regexp.MustCompile(`^/([0-9]{1,10})(/.*)?$`)
	pathNew = regexp.MustCompile(`^/([0-9a-f]{16})(/.*)?$`)

	cipher *blowfish.Cipher
)

func servePaste(w http.ResponseWriter, id uint64, p string) {
	paste, title, author, notes, err := getPaste(id)
	if err != nil {
		http.NotFound(w, nil)
		return
	}

	switch p {
	case "", "/":
		renderPaste(w, paste, title, author, notes)
	case "/raw":
		w.Write(paste)
	case "/json":
		json.NewEncoder(w).Encode(map[string]interface{}{
			"paste":  string(paste),
			"title":  string(title),
			"author": string(author),
			"notes":  string(notes),
		})
	default:
		http.NotFound(w, nil)
	}
}

func handle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Strict-Transport-Security", "max-age=31536000")
	w.Header().Set("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'")

	if m := pathNew.FindStringSubmatch(r.URL.Path); m != nil {
		src, err := hex.DecodeString(m[1])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		dst := make([]byte, 8)
		cipher.Decrypt(dst, src)

		id := binary.BigEndian.Uint64(dst)
		servePaste(w, id, m[2])
	} else if m := pathOld.FindStringSubmatch(r.URL.Path); m != nil {
		id, err := strconv.ParseUint(m[1], 10, 64)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if id >= 256 {
			id = (id * 0x7FFFFFFF) % 0x100000000
		}

		if id >= 1000 {
			http.Error(w, "Forbidden", http.StatusForbidden)
			return
		}

		servePaste(w, id, m[2])
	} else if r.URL.Path == "/create" {
		err := r.ParseForm()
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		paste := r.Form.Get("paste")
		if len(paste) == 0 {
			http.Error(w, "No (or Invalid) Paste", http.StatusBadRequest)
			return
		}

		title := r.Form.Get("title")
		author := r.Form.Get("author")
		notes := r.Form.Get("notes")

		id, err := postPaste(&paste, &title, &author, &notes)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		src := make([]byte, 8)
		binary.BigEndian.PutUint64(src, uint64(id))

		dst := make([]byte, 8)
		cipher.Encrypt(dst, src)

		http.Redirect(w, r, hex.EncodeToString(dst), http.StatusSeeOther)
	} else {
		assets.ServeHTTP(w, r)
	}
}

func main() {
	var err error
	cipher, err = blowfish.NewCipher(key)
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", handle)

	go http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://" + r.Host + r.RequestURI, http.StatusMovedPermanently)
	}))

	log.Fatal(http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil))
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"crypto/sha1"
	"fmt"
	authlib "github.com/clawio/service.auth/lib"
	"github.com/clawio/service.localstore.data/lib"
	pb "github.com/clawio/service.localstore.data/proto/propagator"
	"github.com/clawio/service.localstorexattr.data/xattr"
	log "github.com/sirupsen/logrus"
	"github.com/zenazn/goji/web/mutil"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"hash"
	"hash/adler32"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strings"
	"syscall"
	"time"
)

const (
	dirPerm          = 0755
	xattrKeyID       = "user.id"
	xattrKeyChecksum = "user.checksum"
)

type newServerParams struct {
	dataDir      string
	tmpDir       string
	checksum     string
	prop         string
	sharedSecret string
}

func newServer(p *newServerParams) (*server, error) {

	s := &server{}
	s.p = p

	return s, nil
}

type server struct {
	p *newServerParams
}

func (s *server) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {

	traceID := getTraceID(r)
	reqLogger := log.WithField("trace", traceID)
	ctx = newGRPCTraceContext(ctx, traceID)
	ctx = NewLogContext(ctx, reqLogger)

	reqLogger.Info("request started")

	// Time request
	reqStart := time.Now()

	// Sniff the status and content size for logging
	lw := mutil.WrapWriter(w)

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		reqLogger.WithFields(log.Fields{
			"method":      r.Method,
			"type":        "access",
			"status_code": lw.Status(),
			"duration":    reqDur.Seconds(),
			"size":        lw.BytesWritten(),
		}).Infof("%s %s %03d", r.Method, r.URL.String(), lw.Status())

		reqLogger.Info("request finished")

	}()

	if strings.ToUpper(r.Method) == "PUT" {
		reqLogger.WithField("op", "upload").Info()
		s.authHandler(ctx, lw, r, s.upload)
	} else if strings.ToUpper(r.Method) == "GET" {
		reqLogger.WithField("op", "download").Info()
		s.authHandler(ctx, lw, r, s.download)
	} else {
		w.WriteHeader(http.StatusNotFound)
		return
	}
}

func (s *server) upload(ctx context.Context, w http.ResponseWriter, r *http.Request) {

	log := MustFromLogContext(ctx)
	p := lib.MustFromContext(ctx)

	pp := s.getPhysicalPath(p)

	log.Infof("physical path is %s", pp)

	tmpFn, tmpFile, err := s.tmpFile()
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("created tmp file %s", tmpFn)

	var mw io.Writer
	var hasher hash.Hash
	var isChecksumed bool
	var computedChecksum string

	switch s.p.checksum {
	case "md5":
		hasher = md5.New()
		isChecksumed = true
		mw = io.MultiWriter(tmpFile, hasher)
	case "sha1":
		hasher = sha1.New()
		isChecksumed = true
		mw = io.MultiWriter(tmpFile, hasher)
	case "adler32":
		hasher = adler32.New()
		isChecksumed = true
		mw = io.MultiWriter(tmpFile, hasher)
	default:
		mw = io.MultiWriter(tmpFile)
	}

	// TODO(labkode) Sometimes ContentLength = -1 because it is a binary
	// upload with TransferEncoding: chunked.
	// Instead using Copy we shoudl use a LimitedReader with a max file upload
	// configuration value.
	_, err = io.Copy(mw, r.Body)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	chk := s.getChecksumInfo(r)

	if isChecksumed {
		log.Infof("file sent with checksum %s", chk.String())

		// checksums are given in hexadecimal format.
		computedChecksum = fmt.Sprintf("%x", string(hasher.Sum(nil)))

		if chk.Type == s.p.checksum && chk.Type != "" {

			isCorrupted := computedChecksum != chk.Sum

			if isCorrupted {
				log.Errorf("corrupted file. expected %s and got %s",
					s.p.checksum+":"+computedChecksum, chk.Sum)
				http.Error(w, "", http.StatusPreconditionFailed)
				return
			}
		}
	}

	log.Infof("copied r.Body into tmp file %s", tmpFn)

	err = tmpFile.Close()
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("closed tmp file %s", tmpFn)

	// TODO(labkode) Add xattr here
	resourceID := uuid.New()
	err = xattr.SetXAttr(tmpFn, xattrKeyID, []byte(resourceID), xattr.XAttrCreate)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	if isChecksumed {
		err = xattr.SetXAttr(tmpFn, xattrKeyChecksum, []byte(chk.String()), xattr.XAttrCreate)
		if err != nil {
			log.Error(err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}

	}
	if err = os.Rename(tmpFn, pp); err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("renamed tmp file %s to %s", tmpFn, pp)

	con, err := grpc.Dial(s.p.prop, grpc.WithInsecure())
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
	defer con.Close()

	log.Infof("created connection to %s", s.p.prop)

	client := pb.NewPropClient(con)

	in := &pb.PutReq{}
	in.Path = p
	in.AccessToken = authlib.MustFromTokenContext(ctx)
	in.Checksum = chk.String()

	_, err = client.Put(ctx, in)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("saved path %s into %s", p, s.p.prop)

	w.WriteHeader(http.StatusCreated)
}

func (s *server) download(ctx context.Context, w http.ResponseWriter, r *http.Request) {

	log := MustFromLogContext(ctx)
	p := lib.MustFromContext(ctx)

	pp := s.getPhysicalPath(p)

	log.Info("physical path is %s", pp)

	fd, err := os.Open(pp)
	if err == syscall.ENOENT {
		log.Error(err.Error())
		http.Error(w, "", http.StatusNotFound)
		return
	}

	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("opened %s", pp)

	info, err := fd.Stat()
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("stated %s got size %d", pp, info.Size())

	if info.IsDir() {
		log.Errorf("%s is a directory", pp)
		http.Error(w, "", http.StatusBadRequest)
		return
	}

	defer fd.Close()

	_, err = io.Copy(w, fd)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("copied %s to res.body", pp)

}

func (s *server) authHandler(ctx context.Context, w http.ResponseWriter, r *http.Request,
	next func(ctx context.Context, w http.ResponseWriter, r *http.Request)) {

	log := MustFromLogContext(ctx)

	idt, err := s.getIdentityFromReq(r)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusUnauthorized)
		return
	}

	p := getPathFromReq(r) // already sanitized

	if !isUnderHome(p, idt) {
		// TODO use here share service
		log.Warnf("%s cannot access %s", *idt, p)
		http.Error(w, "", http.StatusForbidden)
		return
	}

	if p == getHome(idt) {
		http.Error(w, "", http.StatusMethodNotAllowed)
		return
	}

	log.Infof("path is %s", p)

	ctx = authlib.NewContext(ctx, idt)
	ctx = lib.NewContext(ctx, p)
	ctx = authlib.NewTokenContext(ctx, s.getTokenFromReq(r))
	next(ctx, w, r)
}

func (s *server) tmpFile() (string, *os.File, error) {

	file, err := ioutil.TempFile(s.p.tmpDir, serviceID)
	if err != nil {
		return "", nil, err
	}

	fn := path.Join(path.Clean(file.Name()))

	return fn, file, nil
}

func (s *server) getPhysicalPath(p string) string {
	return path.Join(s.p.dataDir, path.Clean(p))
}

func (s *server) getTokenFromReq(r *http.Request) string {

	var token string

	// Look for an Authorization header
	if ah := r.Header.Get("Authorization"); ah != "" {
		// Should be a bearer token
		if len(ah) > 6 && strings.ToUpper(ah[0:6]) == "BEARER" {
			token = ah[7:]
		}
	}

	if token == "" {
		// Look for "auth_token" parameter
		r.ParseMultipartForm(10e6)
		if tokStr := r.Form.Get("access_token"); tokStr != "" {
			token = tokStr
		}

	}

	return token
}

func (s *server) getIdentityFromReq(r *http.Request) (*authlib.Identity, error) {
	return authlib.ParseToken(s.getTokenFromReq(r), s.p.sharedSecret)
}
func getIDFromPath(path string) ([]byte, error) {

	id, err := xattr.GetXAttr(path, xattrKeyID)
	if err != nil {
		if err == syscall.ENODATA {
			id = []byte(uuid.New())
			return id, nil
		}
		return []byte(""), err
	}

	if len(id) == 0 { // xattr is empty but is set
		id = []byte(uuid.New())
	}

	return id, nil
}
<commit_msg>Added file id and checksum in xattr<commit_after>package main

import (
	"crypto/md5"
	"crypto/sha1"
	"fmt"
	authlib "github.com/clawio/service.auth/lib"
	"github.com/clawio/service.localstore.data/lib"
	//pb "github.com/clawio/service.localstore.data/proto/propagator"
	"github.com/clawio/service.localstorexattr.data/xattr"
	log "github.com/sirupsen/logrus"
	"github.com/zenazn/goji/web/mutil"
	"golang.org/x/net/context"
	//"google.golang.org/grpc"
	"hash"
	"hash/adler32"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strings"
	"syscall"
	"time"
	"code.google.com/p/go-uuid/uuid"
)

const (
	dirPerm          = 0755
	xattrKeyID       = "user.id"
	xattrKeyChecksum = "user.checksum"
)

type newServerParams struct {
	dataDir      string
	tmpDir       string
	checksum     string
	prop         string
	sharedSecret string
}

func newServer(p *newServerParams) (*server, error) {

	s := &server{}
	s.p = p

	return s, nil
}

type server struct {
	p *newServerParams
}

func (s *server) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {

	traceID := getTraceID(r)
	reqLogger := log.WithField("trace", traceID)
	ctx = newGRPCTraceContext(ctx, traceID)
	ctx = NewLogContext(ctx, reqLogger)

	reqLogger.Info("request started")

	// Time request
	reqStart := time.Now()

	// Sniff the status and content size for logging
	lw := mutil.WrapWriter(w)

	defer func() {
		// Compute request duration
		reqDur := time.Since(reqStart)

		// Log access info
		reqLogger.WithFields(log.Fields{
			"method":      r.Method,
			"type":        "access",
			"status_code": lw.Status(),
			"duration":    reqDur.Seconds(),
			"size":        lw.BytesWritten(),
		}).Infof("%s %s %03d", r.Method, r.URL.String(), lw.Status())

		reqLogger.Info("request finished")

	}()

	if strings.ToUpper(r.Method) == "PUT" {
		reqLogger.WithField("op", "upload").Info()
		s.authHandler(ctx, lw, r, s.upload)
	} else if strings.ToUpper(r.Method) == "GET" {
		reqLogger.WithField("op", "download").Info()
		s.authHandler(ctx, lw, r, s.download)
	} else {
		w.WriteHeader(http.StatusNotFound)
		return
	}
}

func (s *server) upload(ctx context.Context, w http.ResponseWriter, r *http.Request) {

	log := MustFromLogContext(ctx)
	p := lib.MustFromContext(ctx)

	pp := s.getPhysicalPath(p)

	log.Infof("physical path is %s", pp)

	tmpFn, tmpFile, err := s.tmpFile()
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("created tmp file %s", tmpFn)

	var mw io.Writer
	var hasher hash.Hash
	var isChecksumed bool
	var computedChecksum string

	switch s.p.checksum {
	case "md5":
		hasher = md5.New()
		isChecksumed = true
		mw = io.MultiWriter(tmpFile, hasher)
	case "sha1":
		hasher = sha1.New()
		isChecksumed = true
		mw = io.MultiWriter(tmpFile, hasher)
	case "adler32":
		hasher = adler32.New()
		isChecksumed = true
		mw = io.MultiWriter(tmpFile, hasher)
	default:
		mw = io.MultiWriter(tmpFile)
	}

	// TODO(labkode) Sometimes ContentLength = -1 because it is a binary
	// upload with TransferEncoding: chunked.
	// Instead using Copy we shoudl use a LimitedReader with a max file upload
	// configuration value.
	_, err = io.Copy(mw, r.Body)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	chk := s.getChecksumInfo(r)

	if isChecksumed {
		log.Infof("file sent with checksum %s", chk.String())

		// checksums are given in hexadecimal format.
		computedChecksum = fmt.Sprintf("%x", string(hasher.Sum(nil)))

		if chk.Type == s.p.checksum && chk.Type != "" {

			isCorrupted := computedChecksum != chk.Sum

			if isCorrupted {
				log.Errorf("corrupted file. expected %s and got %s",
					s.p.checksum+":"+computedChecksum, chk.Sum)
				http.Error(w, "", http.StatusPreconditionFailed)
				return
			}
		}
	}

	log.Infof("copied r.Body into tmp file %s", tmpFn)

	err = tmpFile.Close()
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("closed tmp file %s", tmpFn)

	resourceID, err := getIDFromPath(pp)
  	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	err = xattr.SetXAttr(tmpFn, xattrKeyID, []byte(resourceID), xattr.XAttrCreate)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

    log.Infof("resource id %s set for path %s in xattr %s", resourceID, pp, xattrKeyID)

	if isChecksumed {
		err = xattr.SetXAttr(tmpFn, xattrKeyChecksum, []byte(s.p.checksum + ":" + computedChecksum), xattr.XAttrCreate)
		if err != nil {
			log.Error(err)
			http.Error(w, "", http.StatusInternalServerError)
			return
		}
	}

    log.Infof("checksum %s set for path %s in xattr %s", computedChecksum, pp, xattrKeyChecksum)

	if err = os.Rename(tmpFn, pp); err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("renamed tmp file %s to %s", tmpFn, pp)

    // TODO(labkode) Connect to prop service
	/*
	con, err := grpc.Dial(s.p.prop, grpc.WithInsecure())
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}
	defer con.Close()

    log.Infof("created connection to %s", s.p.prop)

	client := pb.NewPropClient(con)

	in := &pb.PutReq{}
	in.Path = p
	in.AccessToken = authlib.MustFromTokenContext(ctx)
	in.Checksum = chk.String()

	_, err = client.Put(ctx, in)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("saved path %s into %s", p, s.p.prop)

    */
	w.WriteHeader(http.StatusCreated)
}

func (s *server) download(ctx context.Context, w http.ResponseWriter, r *http.Request) {

	log := MustFromLogContext(ctx)
	p := lib.MustFromContext(ctx)

	pp := s.getPhysicalPath(p)

	log.Infof("physical path is %s", pp)

	fd, err := os.Open(pp)
	if err == syscall.ENOENT {
		log.Error(err.Error())
		http.Error(w, "", http.StatusNotFound)
		return
	}

	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("opened %s", pp)

	info, err := fd.Stat()
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("stated %s got size %d", pp, info.Size())

	if info.IsDir() {
		log.Errorf("%s is a directory", pp)
		http.Error(w, "", http.StatusBadRequest)
		return
	}

	defer fd.Close()

	_, err = io.Copy(w, fd)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusInternalServerError)
		return
	}

	log.Infof("copied %s to res.body", pp)

}

func (s *server) authHandler(ctx context.Context, w http.ResponseWriter, r *http.Request,
	next func(ctx context.Context, w http.ResponseWriter, r *http.Request)) {

	log := MustFromLogContext(ctx)

	idt, err := s.getIdentityFromReq(r)
	if err != nil {
		log.Error(err)
		http.Error(w, "", http.StatusUnauthorized)
		return
	}

	p := getPathFromReq(r) // already sanitized

	if !isUnderHome(p, idt) {
		// TODO use here share service
		log.Warnf("%s cannot access %s", *idt, p)
		http.Error(w, "", http.StatusForbidden)
		return
	}

	if p == getHome(idt) {
		http.Error(w, "", http.StatusMethodNotAllowed)
		return
	}

	log.Infof("path is %s", p)

	ctx = authlib.NewContext(ctx, idt)
	ctx = lib.NewContext(ctx, p)
	ctx = authlib.NewTokenContext(ctx, s.getTokenFromReq(r))
	next(ctx, w, r)
}

func (s *server) tmpFile() (string, *os.File, error) {

	file, err := ioutil.TempFile(s.p.tmpDir, serviceID)
	if err != nil {
		return "", nil, err
	}

	fn := path.Join(path.Clean(file.Name()))

	return fn, file, nil
}

func (s *server) getPhysicalPath(p string) string {
	return path.Join(s.p.dataDir, path.Clean(p))
}

func (s *server) getTokenFromReq(r *http.Request) string {

	var token string

	// Look for an Authorization header
	if ah := r.Header.Get("Authorization"); ah != "" {
		// Should be a bearer token
		if len(ah) > 6 && strings.ToUpper(ah[0:6]) == "BEARER" {
			token = ah[7:]
		}
	}

	if token == "" {
		// Look for "auth_token" parameter
		r.ParseMultipartForm(10e6)
		if tokStr := r.Form.Get("access_token"); tokStr != "" {
			token = tokStr
		}

	}

	return token
}

func (s *server) getIdentityFromReq(r *http.Request) (*authlib.Identity, error) {
	return authlib.ParseToken(s.getTokenFromReq(r), s.p.sharedSecret)
}
func getIDFromPath(path string) ([]byte, error) {

	id, err := xattr.GetXAttr(path, xattrKeyID)
	if err != nil {
		if err == syscall.ENODATA  || err == syscall.ENOENT{
			id = []byte(uuid.New())
			return id, nil
		}
		return []byte(""), err
	}

	if len(id) == 0 { // xattr is empty but is set
		id = []byte(uuid.New())
	}

	return id, nil
}
<|endoftext|>


<commit_before>package xweb

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"runtime"
	runtimePprof "runtime/pprof"
	"strconv"
	"strings"

	"github.com/go-xweb/log"
)

// ServerConfig is configuration for server objects.
type ServerConfig struct {
	Addr                   string
	Port                   int
	RecoverPanic           bool
	Profiler               bool
	EnableGzip             bool
	StaticExtensionsToGzip []string
	Url                    string
	UrlPrefix              string
	UrlSuffix              string
	StaticHtmlDir          string
}

var ServerNumber uint = 0

// Server represents a xweb server.
type Server struct {
	Config  *ServerConfig
	Apps    map[string]*App
	AppName map[string]string //[SWH|+]
	Name    string            //[SWH|+]
	RootApp *App
	Logger  *log.Logger
	Env     map[string]interface{}
	//save the listener so it can be closed
	l net.Listener
}

func NewServer(args ...string) *Server {
	name := ""
	if len(args) == 1 {
		name = args[0]
	} else {
		name = fmt.Sprintf("Server%d", ServerNumber)
		ServerNumber++
	}
	s := &Server{
		Config:  Config,
		Env:     map[string]interface{}{},
		Apps:    map[string]*App{},
		AppName: map[string]string{},
		Name:    name,
	}
	Servers[s.Name] = s //[SWH|+]

	s.SetLogger(log.New(os.Stdout, "", log.Ldefault()))

	app := NewApp("/", "root") //[SWH|+] ,"root"
	s.AddApp(app)
	return s
}

func (s *Server) AddApp(a *App) {
	a.BasePath = strings.TrimRight(a.BasePath, "/") + "/"
	s.Apps[a.BasePath] = a

	//[SWH|+]
	if a.Name != "" {
		s.AppName[a.Name] = a.BasePath
	}

	a.Server = s
	a.Logger = s.Logger
	if a.BasePath == "/" {
		s.RootApp = a
	}
}

func (s *Server) AddAction(cs ...interface{}) {
	s.RootApp.AddAction(cs...)
}

func (s *Server) AutoAction(c ...interface{}) {
	s.RootApp.AutoAction(c...)
}

func (s *Server) AddRouter(url string, c interface{}) {
	s.RootApp.AddRouter(url, c)
}

func (s *Server) AddTmplVar(name string, varOrFun interface{}) {
	s.RootApp.AddTmplVar(name, varOrFun)
}

func (s *Server) AddTmplVars(t *T) {
	s.RootApp.AddTmplVars(t)
}

func (s *Server) AddFilter(filter Filter) {
	s.RootApp.AddFilter(filter)
}

func (s *Server) AddConfig(name string, value interface{}) {
	s.RootApp.Config[name] = value
}

func (s *Server) error(w http.ResponseWriter, status int, content string) error {
	return s.RootApp.error(w, status, content)
}

func (s *Server) initServer() {
	if s.Config == nil {
		s.Config = &ServerConfig{}
		s.Config.Profiler = true
	}

	for _, app := range s.Apps {
		app.initApp()
	}
}

// ServeHTTP is the interface method for Go's http server package
func (s *Server) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	s.Process(c, req)
}

// Process invokes the routing system for server s
// non-root app's route will override root app's if there is same path
func (s *Server) Process(w http.ResponseWriter, req *http.Request) {
	var result bool = true
	_, _ = XHook.Call("BeforeProcess", &result, s, w, req) //[SWH|+]call hook
	if !result {
		return
	}
	if s.Config.UrlSuffix != "" && strings.HasSuffix(req.URL.Path, s.Config.UrlSuffix) {
		req.URL.Path = strings.TrimSuffix(req.URL.Path, s.Config.UrlSuffix)
	}
	if s.Config.UrlPrefix != "" && strings.HasPrefix(req.URL.Path, "/"+s.Config.UrlPrefix) {
		req.URL.Path = strings.TrimPrefix(req.URL.Path, "/"+s.Config.UrlPrefix)
	}
	if req.URL.Path[0] != '/' {
		req.URL.Path = "/" + req.URL.Path
	}
	for _, app := range s.Apps {
		if app != s.RootApp && strings.HasPrefix(req.URL.Path, app.BasePath) {
			app.routeHandler(req, w)
			return
		}
	}
	s.RootApp.routeHandler(req, w)
	_, _ = XHook.Call("AfterProcess", &result, s, w, req) //[SWH|+]call hook
}

// Run starts the web application and serves HTTP requests for s
func (s *Server) Run(addr string) {
	addrs := strings.Split(addr, ":")
	s.Config.Addr = addrs[0]
	s.Config.Port, _ = strconv.Atoi(addrs[1])

	s.initServer()

	mux := http.NewServeMux()
	if s.Config.Profiler {
		mux.Handle("/debug/pprof", http.HandlerFunc(pprof.Index))
		mux.Handle("/debug/pprof/heap", pprof.Handler("heap"))
		mux.Handle("/debug/pprof/block", pprof.Handler("block"))
		mux.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
		mux.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))

		mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
		mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
		mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))

		mux.Handle("/debug/pprof/startcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StartCPUProfile()
		}))
		mux.Handle("/debug/pprof/stopcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StopCPUProfile()
		}))
		mux.Handle("/debug/pprof/memprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			runtime.GC()
			runtimePprof.WriteHeapProfile(rw)
		}))
		mux.Handle("/debug/pprof/gc", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			PrintGCSummary(rw)
		}))

	}
	//[SWH|+]call hook
	if c, err := XHook.Call("MuxHandle", mux); err == nil {
		if ret := XHook.Value(c, 0); ret != nil {
			mux = ret.(*http.ServeMux)
		}
	}
	mux.Handle("/", s)

	s.Logger.Infof("http server is listening %s", addr)

	l, err := net.Listen("tcp", addr)
	if err != nil {
		s.Logger.Error("ListenAndServe:", err)
	}
	s.l = l
	err = http.Serve(s.l, mux)
	s.l.Close()
}

// RunFcgi starts the web application and serves FastCGI requests for s.
func (s *Server) RunFcgi(addr string) {
	s.initServer()
	s.Logger.Infof("fcgi server is listening %s", addr)
	s.listenAndServeFcgi(addr)
}

// RunScgi starts the web application and serves SCGI requests for s.
func (s *Server) RunScgi(addr string) {
	s.initServer()
	s.Logger.Infof("scgi server is listening %s", addr)
	s.listenAndServeScgi(addr)
}

// RunTLS starts the web application and serves HTTPS requests for s.
func (s *Server) RunTLS(addr string, config *tls.Config) error {
	s.initServer()
	mux := http.NewServeMux()
	mux.Handle("/", s)
	l, err := tls.Listen("tcp", addr, config)
	if err != nil {
		s.Logger.Errorf("Listen: %v", err)
		return err
	}

	s.l = l

	s.Logger.Infof("https server is listening %s", addr)

	return http.Serve(s.l, mux)
}

// Close stops server s.
func (s *Server) Close() {
	if s.l != nil {
		s.l.Close()
	}
}

// SetLogger sets the logger for server s
func (s *Server) SetLogger(logger *log.Logger) {
	s.Logger = logger
	s.Logger.SetPrefix("[" + s.Name + "] ")
}

func (s *Server) SetTemplateDir(path string) {
	s.RootApp.SetTemplateDir(path)
}

func (s *Server) SetStaticDir(path string) {
	s.RootApp.SetStaticDir(path)
}

func (s *Server) App(name string) *App {
	path, ok := s.AppName[name]
	if ok {
		return s.Apps[path]
	}
	return nil
}
<commit_msg>add config<commit_after>package xweb

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"runtime"
	runtimePprof "runtime/pprof"
	"strconv"
	"strings"

	"github.com/go-xweb/log"
)

// ServerConfig is configuration for server objects.
type ServerConfig struct {
	Addr                   string
	Port                   int
	RecoverPanic           bool
	Profiler               bool
	EnableGzip             bool
	StaticExtensionsToGzip []string
	Url                    string
	UrlPrefix              string
	UrlSuffix              string
	StaticHtmlDir          string
}

var ServerNumber uint = 0

// Server represents a xweb server.
type Server struct {
	Config  *ServerConfig
	Apps    map[string]*App
	AppName map[string]string //[SWH|+]
	Name    string            //[SWH|+]
	RootApp *App
	Logger  *log.Logger
	Env     map[string]interface{}
	//save the listener so it can be closed
	l net.Listener
}

func NewServer(args ...string) *Server {
	name := ""
	if len(args) == 1 {
		name = args[0]
	} else {
		name = fmt.Sprintf("Server%d", ServerNumber)
		ServerNumber++
	}
	s := &Server{
		Config:  Config,
		Env:     map[string]interface{}{},
		Apps:    map[string]*App{},
		AppName: map[string]string{},
		Name:    name,
	}
	Servers[s.Name] = s //[SWH|+]

	s.SetLogger(log.New(os.Stdout, "", log.Ldefault()))

	app := NewApp("/", "root") //[SWH|+] ,"root"
	s.AddApp(app)
	return s
}

func (s *Server) AddApp(a *App) {
	a.BasePath = strings.TrimRight(a.BasePath, "/") + "/"
	s.Apps[a.BasePath] = a

	//[SWH|+]
	if a.Name != "" {
		s.AppName[a.Name] = a.BasePath
	}

	a.Server = s
	a.Logger = s.Logger
	if a.BasePath == "/" {
		s.RootApp = a
	}
}

func (s *Server) AddAction(cs ...interface{}) {
	s.RootApp.AddAction(cs...)
}

func (s *Server) AutoAction(c ...interface{}) {
	s.RootApp.AutoAction(c...)
}

func (s *Server) AddRouter(url string, c interface{}) {
	s.RootApp.AddRouter(url, c)
}

func (s *Server) AddTmplVar(name string, varOrFun interface{}) {
	s.RootApp.AddTmplVar(name, varOrFun)
}

func (s *Server) AddTmplVars(t *T) {
	s.RootApp.AddTmplVars(t)
}

func (s *Server) AddFilter(filter Filter) {
	s.RootApp.AddFilter(filter)
}

func (s *Server) AddConfig(name string, value interface{}) {
	s.RootApp.SetConfig(name, value)
}

func (s *Server) SetConfig(name string, value interface{}) {
	s.RootApp.SetConfig(name, value)
}

func (s *Server) GetConfig(name string) interface{} {
	return s.RootApp.GetConfig(name)
}

func (s *Server) error(w http.ResponseWriter, status int, content string) error {
	return s.RootApp.error(w, status, content)
}

func (s *Server) initServer() {
	if s.Config == nil {
		s.Config = &ServerConfig{}
		s.Config.Profiler = true
	}

	for _, app := range s.Apps {
		app.initApp()
	}
}

// ServeHTTP is the interface method for Go's http server package
func (s *Server) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	s.Process(c, req)
}

// Process invokes the routing system for server s
// non-root app's route will override root app's if there is same path
func (s *Server) Process(w http.ResponseWriter, req *http.Request) {
	var result bool = true
	_, _ = XHook.Call("BeforeProcess", &result, s, w, req) //[SWH|+]call hook
	if !result {
		return
	}
	if s.Config.UrlSuffix != "" && strings.HasSuffix(req.URL.Path, s.Config.UrlSuffix) {
		req.URL.Path = strings.TrimSuffix(req.URL.Path, s.Config.UrlSuffix)
	}
	if s.Config.UrlPrefix != "" && strings.HasPrefix(req.URL.Path, "/"+s.Config.UrlPrefix) {
		req.URL.Path = strings.TrimPrefix(req.URL.Path, "/"+s.Config.UrlPrefix)
	}
	if req.URL.Path[0] != '/' {
		req.URL.Path = "/" + req.URL.Path
	}
	for _, app := range s.Apps {
		if app != s.RootApp && strings.HasPrefix(req.URL.Path, app.BasePath) {
			app.routeHandler(req, w)
			return
		}
	}
	s.RootApp.routeHandler(req, w)
	_, _ = XHook.Call("AfterProcess", &result, s, w, req) //[SWH|+]call hook
}

// Run starts the web application and serves HTTP requests for s
func (s *Server) Run(addr string) {
	addrs := strings.Split(addr, ":")
	s.Config.Addr = addrs[0]
	s.Config.Port, _ = strconv.Atoi(addrs[1])

	s.initServer()

	mux := http.NewServeMux()
	if s.Config.Profiler {
		mux.Handle("/debug/pprof", http.HandlerFunc(pprof.Index))
		mux.Handle("/debug/pprof/heap", pprof.Handler("heap"))
		mux.Handle("/debug/pprof/block", pprof.Handler("block"))
		mux.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
		mux.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))

		mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
		mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
		mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))

		mux.Handle("/debug/pprof/startcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StartCPUProfile()
		}))
		mux.Handle("/debug/pprof/stopcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StopCPUProfile()
		}))
		mux.Handle("/debug/pprof/memprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			runtime.GC()
			runtimePprof.WriteHeapProfile(rw)
		}))
		mux.Handle("/debug/pprof/gc", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			PrintGCSummary(rw)
		}))

	}
	//[SWH|+]call hook
	if c, err := XHook.Call("MuxHandle", mux); err == nil {
		if ret := XHook.Value(c, 0); ret != nil {
			mux = ret.(*http.ServeMux)
		}
	}
	mux.Handle("/", s)

	s.Logger.Infof("http server is listening %s", addr)

	l, err := net.Listen("tcp", addr)
	if err != nil {
		s.Logger.Error("ListenAndServe:", err)
	}
	s.l = l
	err = http.Serve(s.l, mux)
	s.l.Close()
}

// RunFcgi starts the web application and serves FastCGI requests for s.
func (s *Server) RunFcgi(addr string) {
	s.initServer()
	s.Logger.Infof("fcgi server is listening %s", addr)
	s.listenAndServeFcgi(addr)
}

// RunScgi starts the web application and serves SCGI requests for s.
func (s *Server) RunScgi(addr string) {
	s.initServer()
	s.Logger.Infof("scgi server is listening %s", addr)
	s.listenAndServeScgi(addr)
}

// RunTLS starts the web application and serves HTTPS requests for s.
func (s *Server) RunTLS(addr string, config *tls.Config) error {
	s.initServer()
	mux := http.NewServeMux()
	mux.Handle("/", s)
	l, err := tls.Listen("tcp", addr, config)
	if err != nil {
		s.Logger.Errorf("Listen: %v", err)
		return err
	}

	s.l = l

	s.Logger.Infof("https server is listening %s", addr)

	return http.Serve(s.l, mux)
}

// Close stops server s.
func (s *Server) Close() {
	if s.l != nil {
		s.l.Close()
	}
}

// SetLogger sets the logger for server s
func (s *Server) SetLogger(logger *log.Logger) {
	s.Logger = logger
	s.Logger.SetPrefix("[" + s.Name + "] ")
}

func (s *Server) SetTemplateDir(path string) {
	s.RootApp.SetTemplateDir(path)
}

func (s *Server) SetStaticDir(path string) {
	s.RootApp.SetStaticDir(path)
}

func (s *Server) App(name string) *App {
	path, ok := s.AppName[name]
	if ok {
		return s.Apps[path]
	}
	return nil
}
<|endoftext|>


<commit_before>package datahub

import (
	"bufio"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"os"
)

type handler struct {
	datadir string
	log     *log.Logger
}

func (d *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	// NOT VALIDATING THE HTTP METHODS :-)
	switch req.URL.Path {
	case "/datahub/upload":
		{
			uploadFileNames := []string{
				"trainingset.csv",
				"testset.challenge.csv",
				"testset.prediction.csv",
				"testset.result.csv",
			}

			success := false
			for _, filename := range uploadFileNames {
				res := d.receiveUpload(req, filename)
				if res {
					success = res
				}
			}
			if !success {
				d.failrequest(
					w,
					"no dataset received, expected one of these: %q",
					uploadFileNames,
				)
				return
			}
			w.WriteHeader(http.StatusOK)
		}
	case "/datahub/score":
		{
			d.scoreCheck(w, req)
			w.WriteHeader(http.StatusOK)
		}
	default:
		{
			d.log.Printf("error: path %q not found", req.URL.Path)
			w.WriteHeader(http.StatusNotFound)
		}
	}
}

func NewHandler() http.Handler {
	const datadir string = "./.repo"
	log := log.New(os.Stdout, "datahub.server", log.Lshortfile|log.Lmicroseconds)
	err := os.MkdirAll(datadir, 0755)
	if err != nil {
		log.Fatalf("error %q creating data dir %q", err, datadir)
	}
	return &handler{
		datadir: datadir,
		log:     log,
	}
}

func (d *handler) failrequest(
	w http.ResponseWriter,
	fmt string,
	args ...interface{},
) {
	d.log.Printf(fmt, args...)
	w.WriteHeader(http.StatusInternalServerError)
}

func (d *handler) receiveUpload(
	req *http.Request,
	filename string,
) bool {
	uploadedfile, _, err := req.FormFile(filename)
	if err != nil {
		d.log.Printf("%q parsing form", err)
		return false
	}
	defer uploadedfile.Close()

	filepath := d.datadir + "/" + filename
	d.log.Printf("creating file %q", filepath)
	file, err := os.Create(filepath)
	if err != nil {
		d.log.Printf("error: %q opening file %q", err, filepath)
		return false
	}
	d.log.Printf("created file with success, copying contents")
	_, err = io.Copy(file, uploadedfile)
	if err != nil {
		d.log.Printf("error: %q copying file", err)
		return false
	}
	d.log.Printf("finished copying from form %q with success", filename)
	return true
}

func (d *handler) scoreCheck(w http.ResponseWriter, req *http.Request) float32 {
	const datadir string = "./.repo"
	predictionfile, err := os.Open(datadir + "/testset.prediction")
	if err != nil {
		d.log.Printf("error: %q reading file", err)
	}
	defer predictionfile.Close()

	resultfile, err := os.Open(datadir + "/testset.result")
	if err != nil {
		d.log.Printf("error: %q reading file", err)
	}
	defer resultfile.Close()

	scanpredictionfile := bufio.NewScanner(predictionfile)
	scanresultfile := bufio.NewScanner(resultfile)

	totallines := 0
	ok := 0
	for scanresultfile.Scan() {
		totallines = totallines + 1
		if scanpredictionfile.Scan() {
			if scanresultfile.Text() == scanpredictionfile.Text() {
				ok++
			}
		}
	}
	score := float32(int((ok*100/totallines)*100)) / 100
	response := make(map[string]interface{})
	response["score"] = score

	w.Header().Set("Content-type", "application/json")
	json.NewEncoder(w).Encode(response)
	return score
}
<commit_msg>Fix file extension<commit_after>package datahub

import (
	"bufio"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"os"
)

type handler struct {
	datadir string
	log     *log.Logger
}

func (d *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	// NOT VALIDATING THE HTTP METHODS :-)
	switch req.URL.Path {
	case "/datahub/upload":
		{
			uploadFileNames := []string{
				"trainingset.csv",
				"testset.challenge.csv",
				"testset.prediction.csv",
				"testset.result.csv",
			}

			success := false
			for _, filename := range uploadFileNames {
				res := d.receiveUpload(req, filename)
				if res {
					success = res
				}
			}
			if !success {
				d.failrequest(
					w,
					"no dataset received, expected one of these: %q",
					uploadFileNames,
				)
				return
			}
			w.WriteHeader(http.StatusOK)
		}
	case "/datahub/score":
		{
			d.scoreCheck(w, req)
			w.WriteHeader(http.StatusOK)
		}
	default:
		{
			d.log.Printf("error: path %q not found", req.URL.Path)
			w.WriteHeader(http.StatusNotFound)
		}
	}
}

func NewHandler() http.Handler {
	const datadir string = "./.repo"
	log := log.New(os.Stdout, "datahub.server", log.Lshortfile|log.Lmicroseconds)
	err := os.MkdirAll(datadir, 0755)
	if err != nil {
		log.Fatalf("error %q creating data dir %q", err, datadir)
	}
	return &handler{
		datadir: datadir,
		log:     log,
	}
}

func (d *handler) failrequest(
	w http.ResponseWriter,
	fmt string,
	args ...interface{},
) {
	d.log.Printf(fmt, args...)
	w.WriteHeader(http.StatusInternalServerError)
}

func (d *handler) receiveUpload(
	req *http.Request,
	filename string,
) bool {
	uploadedfile, _, err := req.FormFile(filename)
	if err != nil {
		d.log.Printf("%q parsing form", err)
		return false
	}
	defer uploadedfile.Close()

	filepath := d.datadir + "/" + filename
	d.log.Printf("creating file %q", filepath)
	file, err := os.Create(filepath)
	if err != nil {
		d.log.Printf("error: %q opening file %q", err, filepath)
		return false
	}
	d.log.Printf("created file with success, copying contents")
	_, err = io.Copy(file, uploadedfile)
	if err != nil {
		d.log.Printf("error: %q copying file", err)
		return false
	}
	d.log.Printf("finished copying from form %q with success", filename)
	return true
}

func (d *handler) scoreCheck(w http.ResponseWriter, req *http.Request) float32 {
	const datadir string = "./.repo"
	predictionfile, err := os.Open(datadir + "/testset.prediction.csv")
	if err != nil {
		d.log.Printf("error: %q reading file", err)
	}
	defer predictionfile.Close()

	resultfile, err := os.Open(datadir + "/testset.result.csv")
	if err != nil {
		d.log.Printf("error: %q reading file", err)
	}
	defer resultfile.Close()

	scanpredictionfile := bufio.NewScanner(predictionfile)
	scanresultfile := bufio.NewScanner(resultfile)

	totallines := 0
	ok := 0
	for scanresultfile.Scan() {
		totallines = totallines + 1
		if scanpredictionfile.Scan() {
			if scanresultfile.Text() == scanpredictionfile.Text() {
				ok++
			}
		}
	}
	score := float32(int((ok*100/totallines)*100)) / 100
	response := make(map[string]interface{})
	response["score"] = score

	w.Header().Set("Content-type", "application/json")
	json.NewEncoder(w).Encode(response)
	return score
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io/ioutil"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/julienschmidt/httprouter"
	nlogrus "github.com/meatballhat/negroni-logrus"
	"time"
	"sync"
	"fmt"
	"net/http"
	"strconv"
)

var (
	data   = make(map[string]interface{})
	dataMutex sync.RWMutex
	dirty  = false
	logger *logrus.Logger
)

func main() {
	logr := nlogrus.NewMiddleware()
	logger = logr.Logger

	parseJsonFile()

	port := ":" + os.Getenv("PORT")
	if port == ":" {
		port = ":3000"
	}

	router := httprouter.New()

	router.Handle("GET", "/db", handleDb)

	// set up our routes
	for key, value := range data {
		// Shadow these variables. If this isn't done, then the closures below will see
		// `value` and `key` as whatever they were in the last(?) iteration of the above for loop
		value := value
		key := key

		router.GET(fmt.Sprintf("/%s", key), func (w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
			genericJsonResponse(w, r, value)
		})

		for _, method := range []string{"GET", "PATCH", "PUT", "DELETE"} {
			method := method
			router.Handle(method, fmt.Sprintf("/%s/:id", key), func (w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
				rows, ok := value.([]interface{})
				if !ok {
					logger.Error("unknown type")
					w.WriteHeader(http.StatusInternalServerError)
					return
				}

				idParam, _ := strconv.ParseFloat(ps.ByName("id"), 64)
				for i, row := range rows {
					rowMap, _ := row.(map[string]interface{})

					// Found the item
					if id, ok := rowMap["id"]; ok && id.(float64) == idParam {

						// The method type determines how we respond
						switch (method) {
							case "GET":
								genericJsonResponse(w, r, row)
								return
							case "PATCH":
								updatedData, err := readRequestData(r)
								if err != nil {
									w.WriteHeader(http.StatusBadRequest)
									return
								}

								dataMutex.Lock()
								for key, value := range updatedData {
									rowMap[key] = value
								}

								dirty = true
								dataMutex.Unlock()

								return
							case "PUT":
								updatedData, err := readRequestData(r)
								if err != nil {
									w.WriteHeader(http.StatusBadRequest)
									return
								}

								dataMutex.Lock()
								for key, _ := range rowMap {
									rowMap[key] = nil
								}

								for key, value := range updatedData {
									rowMap[key] = value
								}

								dirty = true
								dataMutex.Unlock()

								w.WriteHeader(http.StatusOK)
								return
							case "DELETE":
								dataMutex.Lock()
								data[key] = append(rows[:i], rows[i+1:]...)
								dirty = true
								dataMutex.Unlock()
								return
						}
					}
				}

				if method == "PUT" {
					newData, err := readRequestData(r)
					if err != nil {
						w.WriteHeader(http.StatusBadRequest)
						return
					}

					dataMutex.Lock()
					dirty = true
					data[key] = append(rows, newData)
					dataMutex.Unlock()

					w.WriteHeader(http.StatusCreated)
				}
				w.WriteHeader(http.StatusNotFound)
			})
		}
	}

	go flushJson()

	n := negroni.Classic()
	n.Use(logr)
	n.UseHandler(router)
	n.Run(port)
}

// Parses the JSON file provided in the command arguments
func parseJsonFile() {
	if len(os.Args) != 2 {
		logger.Fatalln("Invalid number of arguments")
	}

	filename := os.Args[1]
	file, err := os.Open(filename)
	if err != nil {
		logger.Fatalln(err)
	}

	defer file.Close()

	jsonData, err := ioutil.ReadAll(file)
	if err != nil {
		logger.Fatalln(err)
	}

	err = json.Unmarshal(jsonData, &data)
	if err != nil {
		logger.Fatalln(err)
	}
}

func flushJson() {
	filename := os.Args[1]

	for {
		// Flush every 30 seconds
		<-time.After(30 * time.Second)

		if dirty {
			dataMutex.RLock()
			dirty = false

			jsonData, err := json.Marshal(data)
			dataMutex.RUnlock()
			if err != nil {
				logger.Error(err)
				continue
			}

			ioutil.WriteFile(filename, jsonData, 0755)
		}
	}
}
<commit_msg>Fix stale data<commit_after>package main

import (
	"encoding/json"
	"io/ioutil"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/julienschmidt/httprouter"
	nlogrus "github.com/meatballhat/negroni-logrus"
	"time"
	"sync"
	"fmt"
	"net/http"
	"strconv"
)

var (
	data   = make(map[string]interface{})
	dataMutex sync.RWMutex
	dirty  = false
	logger *logrus.Logger
)

func main() {
	logr := nlogrus.NewMiddleware()
	logger = logr.Logger

	parseJsonFile()

	port := ":" + os.Getenv("PORT")
	if port == ":" {
		port = ":3000"
	}

	router := httprouter.New()

	router.Handle("GET", "/db", handleDb)

	// set up our routes
	for key, value := range data {
		// Shadow these variables. If this isn't done, then the closures below will see
		// `value` and `key` as whatever they were in the last(?) iteration of the above for loop
		value := value
		key := key

		router.GET(fmt.Sprintf("/%s", key), func (w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
			genericJsonResponse(w, r, value)
		})

		for _, method := range []string{"GET", "PATCH", "PUT", "DELETE"} {
			method := method
			router.Handle(method, fmt.Sprintf("/%s/:id", key), func (w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
				rows, ok := value.([]interface{})
				if !ok {
					logger.Error("unknown type")
					w.WriteHeader(http.StatusInternalServerError)
					return
				}

				idParam, _ := strconv.ParseFloat(ps.ByName("id"), 64)
				for i, row := range rows {
					rowMap, _ := row.(map[string]interface{})

					// Found the item
					if id, ok := rowMap["id"]; ok && id.(float64) == idParam {

						// The method type determines how we respond
						switch (method) {
							case "GET":
								genericJsonResponse(w, r, row)
								return
							case "PATCH":
								updatedData, err := readRequestData(r)
								if err != nil {
									w.WriteHeader(http.StatusBadRequest)
									return
								}

								dataMutex.Lock()
								for key, value := range updatedData {
									rowMap[key] = value
								}

								dirty = true

								// since value is a shadow copy, we need to update it as it's now stale
								value = data[key]

								dataMutex.Unlock()

								return
							case "PUT":
								updatedData, err := readRequestData(r)
								if err != nil {
									w.WriteHeader(http.StatusBadRequest)
									return
								}

								dataMutex.Lock()
								for key, _ := range rowMap {
									rowMap[key] = nil
								}

								for key, value := range updatedData {
									rowMap[key] = value
								}

								dirty = true

								// since value is a shadow copy, we need to update it as it's now stale
								value = data[key]

								dataMutex.Unlock()

								w.WriteHeader(http.StatusOK)

								return
							case "DELETE":
								dataMutex.Lock()
								data[key] = append(rows[:i], rows[i+1:]...)
								dirty = true

								// since value is a shadow copy, we need to update it as it's now stale
								value = data[key]

								dataMutex.Unlock()

								w.WriteHeader(http.StatusOK)
								return
						}
					}
				}

				if method == "PUT" {
					newData, err := readRequestData(r)
					if err != nil {
						w.WriteHeader(http.StatusBadRequest)
						return
					}

					dataMutex.Lock()
					dirty = true
					data[key] = append(rows, newData)
					dataMutex.Unlock()

					w.WriteHeader(http.StatusCreated)
				}
				w.WriteHeader(http.StatusNotFound)
			})
		}
	}

	go flushJson()

	n := negroni.Classic()
	n.Use(logr)
	n.UseHandler(router)
	n.Run(port)
}

// Parses the JSON file provided in the command arguments
func parseJsonFile() {
	if len(os.Args) != 2 {
		logger.Fatalln("Invalid number of arguments")
	}

	filename := os.Args[1]
	file, err := os.Open(filename)
	if err != nil {
		logger.Fatalln(err)
	}

	defer file.Close()

	jsonData, err := ioutil.ReadAll(file)
	if err != nil {
		logger.Fatalln(err)
	}

	err = json.Unmarshal(jsonData, &data)
	if err != nil {
		logger.Fatalln(err)
	}
}

func flushJson() {
	filename := os.Args[1]

	for {
		// Flush every 30 seconds
		<-time.After(30 * time.Second)

		if dirty {
			dataMutex.RLock()
			dirty = false

			jsonData, err := json.Marshal(data)
			dataMutex.RUnlock()
			if err != nil {
				logger.Error(err)
				continue
			}

			ioutil.WriteFile(filename, jsonData, 0755)
		}
	}
}
<|endoftext|>