<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime/pprof"
	"strings"
	"syscall"

	"github.com/cenkalti/log"
	"github.com/cenkalti/rain/client"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/internal/resume/torrentresume"
	"github.com/cenkalti/rain/torrent"
	"github.com/mitchellh/go-homedir"
)

var (
	configPath = flag.String("config", "", "config path")
	dest       = flag.String("dest", ".", "where to download")
	port       = flag.Int("port", 0, "listen port")
	debug      = flag.Bool("debug", false, "enable debug log")
	version    = flag.Bool("version", false, "version")
	seed       = flag.Bool("seed", false, "continue seeding after dowload finishes")
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
)

func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal("could not create CPU profile: ", err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal("could not start CPU profile: ", err)
		}
		defer pprof.StopCPUProfile()
	}
	if *version {
		fmt.Println(torrent.Version)
		return
	}
	args := flag.Args()
	if len(args) == 0 {
		_, _ = fmt.Fprintln(os.Stderr, "Give a torrent file as first argument!")
		os.Exit(1)
	}
	if *debug {
		logger.SetLogLevel(log.DEBUG)
	}
	cfg := client.NewConfig()
	if *configPath != "" {
		cp, err := homedir.Expand(*configPath)
		if err != nil {
			log.Fatal(err)
		}
		err = cfg.LoadFile(cp)
		if err != nil {
			log.Fatal(err)
		}
	}
	res, err := torrentresume.New("rain.resume")
	if err != nil {
		log.Fatal(err)
	}
	var t *torrent.Torrent
	if strings.HasPrefix(args[0], "magnet:") {
		t, err = torrent.NewMagnet(args[0], *dest, *port, res)
	} else {
		f, err2 := os.Open(args[0])
		if err2 != nil {
			log.Fatal(err2)
		}
		t, err = torrent.New(f, *dest, *port, res)
		f.Close()
	}
	if err != nil {
		log.Fatal(err)
	}

	sigC := make(chan os.Signal, 1)
	signal.Notify(sigC, syscall.SIGINT, syscall.SIGTERM)
LOOP:
	for {
		select {
		case <-sigC:
			break LOOP
		case <-t.NotifyComplete():
			if !*seed {
				break LOOP
			}
		case err = <-t.NotifyError():
			log.Error(err)
			os.Exit(1)
		}
	}
	err = t.Close()
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>fix tests<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime/pprof"
	"strings"
	"syscall"

	"github.com/cenkalti/log"
	"github.com/cenkalti/rain/client"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/internal/resume/torrentresume"
	"github.com/cenkalti/rain/torrent"
	"github.com/mitchellh/go-homedir"
)

var (
	configPath = flag.String("config", "", "config path")
	dest       = flag.String("dest", ".", "where to download")
	port       = flag.Int("port", 0, "listen port")
	debug      = flag.Bool("debug", false, "enable debug log")
	version    = flag.Bool("version", false, "version")
	seed       = flag.Bool("seed", false, "continue seeding after dowload finishes")
	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
)

func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal("could not create CPU profile: ", err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal("could not start CPU profile: ", err)
		}
		defer pprof.StopCPUProfile()
	}
	if *version {
		fmt.Println(torrent.Version)
		return
	}
	args := flag.Args()
	if len(args) == 0 {
		_, _ = fmt.Fprintln(os.Stderr, "Give a torrent file as first argument!")
		os.Exit(1)
	}
	if *debug {
		logger.SetLogLevel(log.DEBUG)
	}
	cfg := client.NewConfig()
	if *configPath != "" {
		cp, err := homedir.Expand(*configPath)
		if err != nil {
			log.Fatal(err)
		}
		err = cfg.LoadFile(cp)
		if err != nil {
			log.Fatal(err)
		}
	}
	res, err := torrentresume.New("rain.resume")
	if err != nil {
		log.Fatal(err)
	}
	var t *torrent.Torrent
	if strings.HasPrefix(args[0], "magnet:") {
		t, err = torrent.NewMagnet(args[0], *dest, *port, res)
	} else {
		f, err2 := os.Open(args[0])
		if err2 != nil {
			log.Fatal(err2)
		}
		t, err = torrent.New(f, *dest, *port, res)
		_ = f.Close()
	}
	if err != nil {
		log.Fatal(err)
	}

	sigC := make(chan os.Signal, 1)
	signal.Notify(sigC, syscall.SIGINT, syscall.SIGTERM)
LOOP:
	for {
		select {
		case <-sigC:
			break LOOP
		case <-t.NotifyComplete():
			if !*seed {
				break LOOP
			}
		case err = <-t.NotifyError():
			log.Error(err)
			os.Exit(1)
		}
	}
	err = t.Close()
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package siri

import (
	"bytes"
	"text/template"
	"time"
)

type SIRINotifyStopMonitoring struct {
	Address                   string
	RequestMessageRef         string
	ProducerRef               string
	ResponseMessageIdentifier string
	SubscriberRef             string
	SubscriptionIdentifier    string

	ResponseTimestamp time.Time
	Status            bool
	ErrorType         string
	ErrorNumber       int
	ErrorText         string

	MonitoredStopVisits []*SIRIMonitoredStopVisit
}

const stopMonitoringNotifyTemplate = `<sw:NotifyStopMonitoring xmlns:sw="http://wsdl.siri.org.uk"> xmlns:siri="http://www.siri.org.uk/siri">
		<siri:ResponseTimestamp>{{ .ResponseTimestamp.Format "2006-01-02T15:04:05.000Z07:00" }}</siri:ResponseTimestamp>
		<siri:ProducerRef>{{ .ProducerRef }}</siri:ProducerRef>{{ if .Address }}
		<siri:Address>{{ .Address }}</siri:Address>{{ end }}
		<siri:ResponseMessageIdentifier>{{ .ResponseMessageIdentifier }}</siri:ResponseMessageIdentifier>
		<siri:RequestMessageRef>{{ .RequestMessageRef }}</siri:RequestMessageRef>
	</ServiceDeliveryInfo>
	<Notification xmlns:ns2="http://www.ifopt.org.uk/acsb" xmlns:siri="http://www.ifopt.org.uk/ifopt" xmlns:ns4="http://datex2.eu/schema/2_0RC1/2_0" xmlns:siri="http://www.siri.org.uk/siri" xmlns:ns6="http://wsdl.siri.org.uk/siri">
		<siri:StopMonitoringDelivery version="2.0:FR-IDF-2.4">
			<siri:ResponseTimestamp>{{ .ResponseTimestamp.Format "2006-01-02T15:04:05.000Z07:00" }}</siri:ResponseTimestamp>
			<siri:RequestMessageRef>{{ .RequestMessageRef }}</siri:RequestMessageRef>
			<siri:SubscriberRef>{{.SubscriberRef}}</siri:SubscriberRef>
			<siri:SubscriptionRef>{{.SubscriptionIdentifier}}</siri:SubscriptionRef>
			<siri:Status>{{ .Status }}</siri:Status>{{ if not .Status }}
			<siri:ErrorCondition>{{ if eq .ErrorType "OtherError" }}
				<siri:OtherError number="{{.ErrorNumber}}">{{ else }}
				<siri:{{.ErrorType}}>{{ end }}
					<siri:ErrorText>{{.ErrorText}}</siri:ErrorText>
				</siri:{{.ErrorType}}>
			</siri:ErrorCondition>{{ else }}{{ range .MonitoredStopVisits }}
			{{ .BuildMonitoredStopVisitXML }}{{ end }}{{ end }}
		</siri:StopMonitoringDelivery>
	</Notification>
	<NotificationExtension />
</sw:NotifyStopMonitoring>`

func (notify *SIRINotifyStopMonitoring) BuildXML() (string, error) {
	var buffer bytes.Buffer
	var notifyDelivery = template.Must(template.New("stopMonitoringNotify").Parse(stopMonitoringNotifyTemplate))
	if err := notifyDelivery.Execute(&buffer, notify); err != nil {
		return "", err
	}
	return buffer.String(), nil
}
<commit_msg>SM notify xml fix<commit_after>package siri

import (
	"bytes"
	"text/template"
	"time"
)

type SIRINotifyStopMonitoring struct {
	Address                   string
	RequestMessageRef         string
	ProducerRef               string
	ResponseMessageIdentifier string
	SubscriberRef             string
	SubscriptionIdentifier    string

	ResponseTimestamp time.Time
	Status            bool
	ErrorType         string
	ErrorNumber       int
	ErrorText         string

	MonitoredStopVisits []*SIRIMonitoredStopVisit
}

const stopMonitoringNotifyTemplate = `<sw:NotifyStopMonitoring xmlns:sw="http://wsdl.siri.org.uk" xmlns:siri="http://www.siri.org.uk/siri">
	<ServiceDeliveryInfo>
		<siri:ResponseTimestamp>{{ .ResponseTimestamp.Format "2006-01-02T15:04:05.000Z07:00" }}</siri:ResponseTimestamp>
		<siri:ProducerRef>{{ .ProducerRef }}</siri:ProducerRef>{{ if .Address }}
		<siri:Address>{{ .Address }}</siri:Address>{{ end }}
		<siri:ResponseMessageIdentifier>{{ .ResponseMessageIdentifier }}</siri:ResponseMessageIdentifier>
		<siri:RequestMessageRef>{{ .RequestMessageRef }}</siri:RequestMessageRef>
	</ServiceDeliveryInfo>
	<Notification>
		<siri:StopMonitoringDelivery version="2.0:FR-IDF-2.4">
			<siri:ResponseTimestamp>{{ .ResponseTimestamp.Format "2006-01-02T15:04:05.000Z07:00" }}</siri:ResponseTimestamp>
			<siri:RequestMessageRef>{{ .RequestMessageRef }}</siri:RequestMessageRef>
			<siri:SubscriberRef>{{.SubscriberRef}}</siri:SubscriberRef>
			<siri:SubscriptionRef>{{.SubscriptionIdentifier}}</siri:SubscriptionRef>
			<siri:Status>{{ .Status }}</siri:Status>{{ if not .Status }}
			<siri:ErrorCondition>{{ if eq .ErrorType "OtherError" }}
				<siri:OtherError number="{{.ErrorNumber}}">{{ else }}
				<siri:{{.ErrorType}}>{{ end }}
					<siri:ErrorText>{{.ErrorText}}</siri:ErrorText>
				</siri:{{.ErrorType}}>
			</siri:ErrorCondition>{{ else }}{{ range .MonitoredStopVisits }}
			{{ .BuildMonitoredStopVisitXML }}{{ end }}{{ end }}
		</siri:StopMonitoringDelivery>
	</Notification>
	<NotificationExtension />
</sw:NotifyStopMonitoring>`

func (notify *SIRINotifyStopMonitoring) BuildXML() (string, error) {
	var buffer bytes.Buffer
	var notifyDelivery = template.Must(template.New("stopMonitoringNotify").Parse(stopMonitoringNotifyTemplate))
	if err := notifyDelivery.Execute(&buffer, notify); err != nil {
		return "", err
	}
	return buffer.String(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"image"
	_ "image/jpeg"
	"log"
	"mime"
	"os"
	"path/filepath"

	"github.com/agorf/goexif/exif"
	_ "github.com/mattn/go-sqlite3"
)

type Photo struct {
	Aperture      sql.NullFloat64
	Camera        sql.NullString
	ExposureComp  sql.NullInt64
	ExposureTime  sql.NullFloat64
	Flash         sql.NullString
	FocalLength   sql.NullFloat64
	FocalLength35 sql.NullInt64
	Folder        string
	Height        int
	ISO           sql.NullInt64
	Lat           sql.NullFloat64
	Lens          sql.NullString
	Lng           sql.NullFloat64
	Path          string
	Size          int64
	Taken         sql.NullString
	Width         int
}

var (
	db                                                             *sql.DB
	selectSetStmt, selectPhotoStmt, insertSetStmt, insertPhotoStmt *sql.Stmt
)

func decodePhotoExif(photo *Photo, x *exif.Exif) {
	taken, err := x.DateTime()
	if err == nil {
		photo.Taken.String = taken.UTC().Format("2006-01-02 15:04:05")
		photo.Taken.Valid = true
	}

	lat, lng, err := x.LatLong()
	if err == nil {
		photo.Lat.Float64 = lat
		photo.Lat.Valid = true
		photo.Lng.Float64 = lng
		photo.Lng.Valid = true
	}

	orientTag, err := x.Get(exif.Orientation)
	if err == nil {
		switch orientTag.String() {
		case "5", "6", "7", "8": // rotated
			photo.Width, photo.Height = photo.Height, photo.Width // swap
		}
	}

	camMakeTag, err := x.Get(exif.Make)
	if err == nil {
		photo.Camera.String, _ = camMakeTag.StringVal()
		photo.Camera.Valid = true
	}

	camModelTag, err := x.Get(exif.Model)
	if err == nil {
		cameraModel, _ := camModelTag.StringVal()

		if photo.Camera.Valid {
			photo.Camera.String = fmt.Sprintf("%s %s", photo.Camera.String, cameraModel)
		} else {
			photo.Camera.String = cameraModel
			photo.Camera.Valid = true
		}
	}

	lensMakeTag, err := x.Get(exif.LensMake)
	if err == nil {
		photo.Lens.String, _ = lensMakeTag.StringVal()
		photo.Lens.Valid = true
	}

	lensModelTag, err := x.Get(exif.LensModel)
	if err == nil {
		lensModel, _ := lensModelTag.StringVal()

		if photo.Lens.Valid {
			photo.Lens.String = fmt.Sprintf("%s %s", photo.Lens.String, lensModel)
		} else {
			photo.Lens.String = lensModel
			photo.Lens.Valid = true
		}
	}

	focalLenTag, err := x.Get(exif.FocalLength)
	if err == nil {
		numer, denom, _ := focalLenTag.Rat2(0)
		photo.FocalLength.Float64 = float64(numer) / float64(denom)
		photo.FocalLength.Valid = true
	}

	focalLen35Tag, err := x.Get(exif.FocalLengthIn35mmFilm)
	if err == nil {
		photo.FocalLength35.Int64, _ = focalLen35Tag.Int64(0)
		photo.FocalLength35.Valid = true
	}

	apertureTag, err := x.Get(exif.FNumber)
	if err == nil {
		numer, denom, _ := apertureTag.Rat2(0)
		photo.Aperture.Float64 = float64(numer) / float64(denom)
		photo.Aperture.Valid = true
	}

	expTimeTag, err := x.Get(exif.ExposureTime)
	if err == nil {
		numer, denom, _ := expTimeTag.Rat2(0)
		photo.ExposureTime.Float64 = float64(numer) / float64(denom)
		photo.ExposureTime.Valid = true
	}

	isoTag, err := x.Get(exif.ISOSpeedRatings)
	if err == nil {
		photo.ISO.Int64, _ = isoTag.Int64(0)
		photo.ISO.Valid = true
	}

	expBiasTag, err := x.Get(exif.ExposureBiasValue)
	if err == nil {
		photo.ExposureComp.Int64, _ = expBiasTag.Int64(0)
		photo.ExposureComp.Valid = true
	}

	flash, err := x.Flash()
	if err == nil {
		photo.Flash.String = flash
		photo.Flash.Valid = true
	}
}

func decodePhoto(path string) (*Photo, error) {
	var photo Photo

	photo.Path = path
	photo.Folder = filepath.Base(filepath.Dir(path))

	f, err := os.Open(path)
	if err != nil {
		return &photo, err
	}
	defer f.Close()

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

	img, _, err := image.DecodeConfig(f)
	if err != nil {
		return &photo, err
	}
	photo.Width, photo.Height = img.Width, img.Height

	f.Seek(0, 0) // rewind

	x, err := exif.Decode(f)
	if err == nil { // EXIF data exists
		decodePhotoExif(&photo, x)
	}

	return &photo, nil
}

func storePhoto(photo *Photo) error {
	var setId, photoId int64

	row := selectSetStmt.QueryRow(photo.Folder)
	if err := row.Scan(&setId); err == sql.ErrNoRows { // set does not exist
		result, err := insertSetStmt.Exec(photo.Folder) // create it
		if err != nil {
			return err
		}

		setId, err = result.LastInsertId()
		if err != nil {
			return err
		}
	}

	row = selectPhotoStmt.QueryRow(photo.Path)
	if err := row.Scan(&photoId); err == sql.ErrNoRows { // photo does not exist
		result, err := insertPhotoStmt.Exec(photo.Aperture, photo.Camera,
			photo.ExposureComp, photo.ExposureTime, photo.Flash, photo.FocalLength,
			photo.FocalLength35, photo.Height, photo.ISO, photo.Lat, photo.Lens,
			photo.Lng, photo.Path, setId, photo.Size, photo.Taken, photo.Width) // create it
		if err != nil {
			return err
		}

		photoId, err = result.LastInsertId()
		if err != nil {
			return err
		}

		fmt.Fprintf(os.Stderr, "photos id=%d path=%s\n", photoId, photo.Path)
	}

	return nil
}

func walk(path string, info os.FileInfo, err error) error {
	if err != nil { // error walking "path"
		return nil // skip
	}

	if info.IsDir() {
		return nil // skip
	}

	if mime.TypeByExtension(filepath.Ext(path)) != "image/jpeg" { // not JPEG
		return nil // skip
	}

	photo, err := decodePhoto(path)
	if err == nil {
		storePhoto(photo)
	}

	return nil // next
}

func updatePhotoSiblings() error {
	var prevId, prevSetId int

	tx, err := db.Begin()
	if err != nil {
		return err
	}

	updatePrevPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET prev_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updatePrevPhotoStmt.Close()

	updateNextPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET next_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateNextPhotoStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id FROM photos ORDER BY set_id, taken_at
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId int
		rows.Scan(&id, &setId)

		if setId == prevSetId && prevId > 0 {
			updatePrevPhotoStmt.Exec(prevId, id)
			fmt.Fprintf(os.Stderr, "photos id=%d prev_photo_id=%d\n", id, prevId)
			updateNextPhotoStmt.Exec(id, prevId)
			fmt.Fprintf(os.Stderr, "photos id=%d next_photo_id=%d\n", prevId, id)
		}

		prevId = id
		prevSetId = setId
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func updateSets() error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	photosCountStmt, err := tx.Prepare(`
	SELECT COUNT(*) FROM photos WHERE set_id = ?
	`)
	if err != nil {
		return err
	}
	defer photosCountStmt.Close()

	updateSetStmt, err := tx.Prepare(`
	UPDATE sets
	SET photos_count = ?, taken_at = ?, thumb_photo_id = ?
	WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateSetStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id, MIN(taken_at) FROM photos GROUP BY set_id
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId, photosCount int
		var taken sql.NullString

		rows.Scan(&id, &setId, &taken)

		row := photosCountStmt.QueryRow(setId)
		row.Scan(&photosCount)

		updateSetStmt.Exec(photosCount, taken, id, setId)
		fmt.Fprintf(os.Stderr, "sets id=%d photos_count=%d taken=\"%s\" thumb_photo_id=%d\n", setId, photosCount, taken, id)
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func main() {
	var err error

	if len(os.Args) == 1 {
		fmt.Fprintf(os.Stderr, "usage: %v path [path...]\n", os.Args[0])
		return
	}

	db, err = sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	selectSetStmt, err = db.Prepare("SELECT id FROM sets WHERE name = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectSetStmt.Close()

	selectPhotoStmt, err = db.Prepare("SELECT id FROM photos WHERE path = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectPhotoStmt.Close()

	insertSetStmt, err = db.Prepare("INSERT INTO sets (name) VALUES (?)")
	if err != nil {
		log.Fatal(err)
	}
	defer insertSetStmt.Close()

	insertPhotoStmt, err = db.Prepare(`
	INSERT INTO photos (
	aperture, camera, exposure_comp, exposure_time, flash, focal_length,
	focal_length_35, height, iso, lat, lens, lng, path, set_id, size, taken_at,
	width
	)
	VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer insertPhotoStmt.Close()

	for i := 1; i < len(os.Args); i++ {
		filepath.Walk(os.Args[i], walk)
	}

	updatePhotoSiblings()
	updateSets()
}
<commit_msg>Use "%q" in format to wrap string with double quotes<commit_after>package main

import (
	"database/sql"
	"fmt"
	"image"
	_ "image/jpeg"
	"log"
	"mime"
	"os"
	"path/filepath"

	"github.com/agorf/goexif/exif"
	_ "github.com/mattn/go-sqlite3"
)

type Photo struct {
	Aperture      sql.NullFloat64
	Camera        sql.NullString
	ExposureComp  sql.NullInt64
	ExposureTime  sql.NullFloat64
	Flash         sql.NullString
	FocalLength   sql.NullFloat64
	FocalLength35 sql.NullInt64
	Folder        string
	Height        int
	ISO           sql.NullInt64
	Lat           sql.NullFloat64
	Lens          sql.NullString
	Lng           sql.NullFloat64
	Path          string
	Size          int64
	Taken         sql.NullString
	Width         int
}

var (
	db                                                             *sql.DB
	selectSetStmt, selectPhotoStmt, insertSetStmt, insertPhotoStmt *sql.Stmt
)

func decodePhotoExif(photo *Photo, x *exif.Exif) {
	taken, err := x.DateTime()
	if err == nil {
		photo.Taken.String = taken.UTC().Format("2006-01-02 15:04:05")
		photo.Taken.Valid = true
	}

	lat, lng, err := x.LatLong()
	if err == nil {
		photo.Lat.Float64 = lat
		photo.Lat.Valid = true
		photo.Lng.Float64 = lng
		photo.Lng.Valid = true
	}

	orientTag, err := x.Get(exif.Orientation)
	if err == nil {
		switch orientTag.String() {
		case "5", "6", "7", "8": // rotated
			photo.Width, photo.Height = photo.Height, photo.Width // swap
		}
	}

	camMakeTag, err := x.Get(exif.Make)
	if err == nil {
		photo.Camera.String, _ = camMakeTag.StringVal()
		photo.Camera.Valid = true
	}

	camModelTag, err := x.Get(exif.Model)
	if err == nil {
		cameraModel, _ := camModelTag.StringVal()

		if photo.Camera.Valid {
			photo.Camera.String = fmt.Sprintf("%s %s", photo.Camera.String, cameraModel)
		} else {
			photo.Camera.String = cameraModel
			photo.Camera.Valid = true
		}
	}

	lensMakeTag, err := x.Get(exif.LensMake)
	if err == nil {
		photo.Lens.String, _ = lensMakeTag.StringVal()
		photo.Lens.Valid = true
	}

	lensModelTag, err := x.Get(exif.LensModel)
	if err == nil {
		lensModel, _ := lensModelTag.StringVal()

		if photo.Lens.Valid {
			photo.Lens.String = fmt.Sprintf("%s %s", photo.Lens.String, lensModel)
		} else {
			photo.Lens.String = lensModel
			photo.Lens.Valid = true
		}
	}

	focalLenTag, err := x.Get(exif.FocalLength)
	if err == nil {
		numer, denom, _ := focalLenTag.Rat2(0)
		photo.FocalLength.Float64 = float64(numer) / float64(denom)
		photo.FocalLength.Valid = true
	}

	focalLen35Tag, err := x.Get(exif.FocalLengthIn35mmFilm)
	if err == nil {
		photo.FocalLength35.Int64, _ = focalLen35Tag.Int64(0)
		photo.FocalLength35.Valid = true
	}

	apertureTag, err := x.Get(exif.FNumber)
	if err == nil {
		numer, denom, _ := apertureTag.Rat2(0)
		photo.Aperture.Float64 = float64(numer) / float64(denom)
		photo.Aperture.Valid = true
	}

	expTimeTag, err := x.Get(exif.ExposureTime)
	if err == nil {
		numer, denom, _ := expTimeTag.Rat2(0)
		photo.ExposureTime.Float64 = float64(numer) / float64(denom)
		photo.ExposureTime.Valid = true
	}

	isoTag, err := x.Get(exif.ISOSpeedRatings)
	if err == nil {
		photo.ISO.Int64, _ = isoTag.Int64(0)
		photo.ISO.Valid = true
	}

	expBiasTag, err := x.Get(exif.ExposureBiasValue)
	if err == nil {
		photo.ExposureComp.Int64, _ = expBiasTag.Int64(0)
		photo.ExposureComp.Valid = true
	}

	flash, err := x.Flash()
	if err == nil {
		photo.Flash.String = flash
		photo.Flash.Valid = true
	}
}

func decodePhoto(path string) (*Photo, error) {
	var photo Photo

	photo.Path = path
	photo.Folder = filepath.Base(filepath.Dir(path))

	f, err := os.Open(path)
	if err != nil {
		return &photo, err
	}
	defer f.Close()

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

	img, _, err := image.DecodeConfig(f)
	if err != nil {
		return &photo, err
	}
	photo.Width, photo.Height = img.Width, img.Height

	f.Seek(0, 0) // rewind

	x, err := exif.Decode(f)
	if err == nil { // EXIF data exists
		decodePhotoExif(&photo, x)
	}

	return &photo, nil
}

func storePhoto(photo *Photo) error {
	var setId, photoId int64

	row := selectSetStmt.QueryRow(photo.Folder)
	if err := row.Scan(&setId); err == sql.ErrNoRows { // set does not exist
		result, err := insertSetStmt.Exec(photo.Folder) // create it
		if err != nil {
			return err
		}

		setId, err = result.LastInsertId()
		if err != nil {
			return err
		}
	}

	row = selectPhotoStmt.QueryRow(photo.Path)
	if err := row.Scan(&photoId); err == sql.ErrNoRows { // photo does not exist
		result, err := insertPhotoStmt.Exec(photo.Aperture, photo.Camera,
			photo.ExposureComp, photo.ExposureTime, photo.Flash, photo.FocalLength,
			photo.FocalLength35, photo.Height, photo.ISO, photo.Lat, photo.Lens,
			photo.Lng, photo.Path, setId, photo.Size, photo.Taken, photo.Width) // create it
		if err != nil {
			return err
		}

		photoId, err = result.LastInsertId()
		if err != nil {
			return err
		}

		fmt.Fprintf(os.Stderr, "photos id=%d path=%s\n", photoId, photo.Path)
	}

	return nil
}

func walk(path string, info os.FileInfo, err error) error {
	if err != nil { // error walking "path"
		return nil // skip
	}

	if info.IsDir() {
		return nil // skip
	}

	if mime.TypeByExtension(filepath.Ext(path)) != "image/jpeg" { // not JPEG
		return nil // skip
	}

	photo, err := decodePhoto(path)
	if err == nil {
		storePhoto(photo)
	}

	return nil // next
}

func updatePhotoSiblings() error {
	var prevId, prevSetId int

	tx, err := db.Begin()
	if err != nil {
		return err
	}

	updatePrevPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET prev_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updatePrevPhotoStmt.Close()

	updateNextPhotoStmt, err := tx.Prepare(`
	UPDATE photos SET next_photo_id = ? WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateNextPhotoStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id FROM photos ORDER BY set_id, taken_at
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId int
		rows.Scan(&id, &setId)

		if setId == prevSetId && prevId > 0 {
			updatePrevPhotoStmt.Exec(prevId, id)
			fmt.Fprintf(os.Stderr, "photos id=%d prev_photo_id=%d\n", id, prevId)
			updateNextPhotoStmt.Exec(id, prevId)
			fmt.Fprintf(os.Stderr, "photos id=%d next_photo_id=%d\n", prevId, id)
		}

		prevId = id
		prevSetId = setId
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func updateSets() error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	photosCountStmt, err := tx.Prepare(`
	SELECT COUNT(*) FROM photos WHERE set_id = ?
	`)
	if err != nil {
		return err
	}
	defer photosCountStmt.Close()

	updateSetStmt, err := tx.Prepare(`
	UPDATE sets
	SET photos_count = ?, taken_at = ?, thumb_photo_id = ?
	WHERE id = ?
	`)
	if err != nil {
		return err
	}
	defer updateSetStmt.Close()

	rows, err := tx.Query(`
	SELECT id, set_id, MIN(taken_at) FROM photos GROUP BY set_id
	`)
	if err != nil {
		return err
	}
	defer rows.Close()

	for rows.Next() {
		var id, setId, photosCount int
		var taken sql.NullString

		rows.Scan(&id, &setId, &taken)

		row := photosCountStmt.QueryRow(setId)
		row.Scan(&photosCount)

		updateSetStmt.Exec(photosCount, taken, id, setId)
		fmt.Fprintf(os.Stderr, "sets id=%d photos_count=%d taken=%q thumb_photo_id=%d\n", setId, photosCount, taken.String, id)
	}

	if err := rows.Err(); err != nil {
		return err
	}

	if err := tx.Commit(); err != nil {
		return err
	}

	return nil
}

func main() {
	var err error

	if len(os.Args) == 1 {
		fmt.Fprintf(os.Stderr, "usage: %v path [path...]\n", os.Args[0])
		return
	}

	db, err = sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	selectSetStmt, err = db.Prepare("SELECT id FROM sets WHERE name = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectSetStmt.Close()

	selectPhotoStmt, err = db.Prepare("SELECT id FROM photos WHERE path = ?")
	if err != nil {
		log.Fatal(err)
	}
	defer selectPhotoStmt.Close()

	insertSetStmt, err = db.Prepare("INSERT INTO sets (name) VALUES (?)")
	if err != nil {
		log.Fatal(err)
	}
	defer insertSetStmt.Close()

	insertPhotoStmt, err = db.Prepare(`
	INSERT INTO photos (
	aperture, camera, exposure_comp, exposure_time, flash, focal_length,
	focal_length_35, height, iso, lat, lens, lng, path, set_id, size, taken_at,
	width
	)
	VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer insertPhotoStmt.Close()

	for i := 1; i < len(os.Args); i++ {
		filepath.Walk(os.Args[i], walk)
	}

	updatePhotoSiblings()
	updateSets()
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"github.com/docker/docker/pkg/archive"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

var VERSION = "0.1.0"

func usage() {
	fmt.Printf("Usage: %s https://example.org/download.tar.bz2\n", os.Args[0])
	os.Exit(1)
}

func version() {
	fmt.Println(VERSION)
	os.Exit(0)
}

func tls_config() *tls.Config {
	pool := x509.NewCertPool()
	cert, err := ioutil.ReadFile("./.cert")
	if err != nil {
		fmt.Printf("Failed to load certificate -- %s\n", err)
		os.Exit(1)
	}
	pool.AppendCertsFromPEM(cert)
	return &tls.Config{RootCAs: pool}
}

func download(url string) io.Reader {
	transport := &http.Transport{TLSClientConfig: tls_config()}
	client := &http.Client{Transport: transport}
	response, err := client.Get(url)
	if err != nil {
		fmt.Printf("Failed to download %s -- %s\n", url, err)
		os.Exit(1)
	}
	fmt.Printf("Downloaded %s\n", url)
	return response.Body
}

func main() {
	if len(os.Args) < 2 {
		usage()
	}
	if os.Args[1] == "-v" {
		version()
	}
	err := archive.Untar(download(os.Args[1]), "/", nil)
	if err != nil {
		fmt.Printf("Failed to extract -- %s\n", err)
	}
	fmt.Println("Successfully extracted archive")
}
<commit_msg>bump version<commit_after>package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"github.com/docker/docker/pkg/archive"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

var VERSION = "0.2.0"

func usage() {
	fmt.Printf("Usage: %s https://example.org/download.tar.bz2\n", os.Args[0])
	os.Exit(1)
}

func version() {
	fmt.Println(VERSION)
	os.Exit(0)
}

func tls_config() *tls.Config {
	pool := x509.NewCertPool()
	cert, err := ioutil.ReadFile("./.cert")
	if err != nil {
		fmt.Printf("Failed to load certificate -- %s\n", err)
		os.Exit(1)
	}
	pool.AppendCertsFromPEM(cert)
	return &tls.Config{RootCAs: pool}
}

func download(url string) io.Reader {
	transport := &http.Transport{TLSClientConfig: tls_config()}
	client := &http.Client{Transport: transport}
	response, err := client.Get(url)
	if err != nil {
		fmt.Printf("Failed to download %s -- %s\n", url, err)
		os.Exit(1)
	}
	fmt.Printf("Downloaded %s\n", url)
	return response.Body
}

func main() {
	if len(os.Args) < 2 {
		usage()
	}
	if os.Args[1] == "-v" {
		version()
	}
	err := archive.Untar(download(os.Args[1]), "/", nil)
	if err != nil {
		fmt.Printf("Failed to extract -- %s\n", err)
	}
	fmt.Println("Successfully extracted archive")
}
<|endoftext|>


<commit_before>// +build !confonly

package http

import (
	"bufio"
	"context"
	"encoding/base64"
	"io"
	"net/http"
	"strings"
	"time"

	"v2ray.com/core"
	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/errors"
	"v2ray.com/core/common/log"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	http_proto "v2ray.com/core/common/protocol/http"
	"v2ray.com/core/common/session"
	"v2ray.com/core/common/signal"
	"v2ray.com/core/common/task"
	"v2ray.com/core/features/policy"
	"v2ray.com/core/features/routing"
	"v2ray.com/core/transport/internet"
)

// Server is an HTTP proxy server.
type Server struct {
	config        *ServerConfig
	policyManager policy.Manager
}

// NewServer creates a new HTTP inbound handler.
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
	v := core.MustFromContext(ctx)
	s := &Server{
		config:        config,
		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
	}

	return s, nil
}

func (s *Server) policy() policy.Session {
	config := s.config
	p := s.policyManager.ForLevel(config.UserLevel)
	if config.Timeout > 0 && config.UserLevel == 0 {
		p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second
	}
	return p
}

// Network implements proxy.Inbound.
func (*Server) Network() []net.Network {
	return []net.Network{net.Network_TCP}
}

func isTimeout(err error) bool {
	nerr, ok := errors.Cause(err).(net.Error)
	return ok && nerr.Timeout()
}

func parseBasicAuth(auth string) (username, password string, ok bool) {
	const prefix = "Basic "
	if !strings.HasPrefix(auth, prefix) {
		return
	}
	c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
	if err != nil {
		return
	}
	cs := string(c)
	s := strings.IndexByte(cs, ':')
	if s < 0 {
		return
	}
	return cs[:s], cs[s+1:], true
}

type readerOnly struct {
	io.Reader
}

func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
	inbound := session.InboundFromContext(ctx)
	if inbound != nil {
		inbound.User = &protocol.MemoryUser{
			Level: s.config.UserLevel,
		}
	}

	reader := bufio.NewReaderSize(readerOnly{conn}, buf.Size)

Start:
	if err := conn.SetReadDeadline(time.Now().Add(s.policy().Timeouts.Handshake)); err != nil {
		newError("failed to set read deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
	}

	request, err := http.ReadRequest(reader)
	if err != nil {
		trace := newError("failed to read http request").Base(err)
		if errors.Cause(err) != io.EOF && !isTimeout(errors.Cause(err)) {
			trace.AtWarning() // nolint: errcheck
		}
		return trace
	}

	if len(s.config.Accounts) > 0 {
		user, pass, ok := parseBasicAuth(request.Header.Get("Proxy-Authorization"))
		if !ok || !s.config.HasAccount(user, pass) {
			return common.Error2(conn.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic realm=\"proxy\"\r\n\r\n")))
		}
		if inbound != nil {
			inbound.User.Email = user
		}
	}

	newError("request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]").WriteToLog(session.ExportIDToError(ctx))
	if err := conn.SetReadDeadline(time.Time{}); err != nil {
		newError("failed to clear read deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
	}

	defaultPort := net.Port(80)
	if strings.EqualFold(request.URL.Scheme, "https") {
		defaultPort = net.Port(443)
	}
	host := request.Host
	if host == "" {
		host = request.URL.Host
	}
	dest, err := http_proto.ParseHost(host, defaultPort)
	if err != nil {
		return newError("malformed proxy host: ", host).AtWarning().Base(err)
	}
	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
		From:   conn.RemoteAddr(),
		To:     request.URL,
		Status: log.AccessAccepted,
		Reason: "",
	})

	if strings.EqualFold(request.Method, "CONNECT") {
		return s.handleConnect(ctx, request, reader, conn, dest, dispatcher)
	}

	keepAlive := (strings.TrimSpace(strings.ToLower(request.Header.Get("Proxy-Connection"))) == "keep-alive")

	err = s.handlePlainHTTP(ctx, request, conn, dest, dispatcher)
	if err == errWaitAnother {
		if keepAlive {
			goto Start
		}
		err = nil
	}

	return err
}

func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher routing.Dispatcher) error {
	_, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
	if err != nil {
		return newError("failed to write back OK response").Base(err)
	}

	plcy := s.policy()
	ctx, cancel := context.WithCancel(ctx)
	timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)

	ctx = policy.ContextWithBufferPolicy(ctx, plcy.Buffer)
	link, err := dispatcher.Dispatch(ctx, dest)
	if err != nil {
		return err
	}

	if reader.Buffered() > 0 {
		payload, err := buf.ReadFrom(io.LimitReader(reader, int64(reader.Buffered())))
		if err != nil {
			return err
		}
		if err := link.Writer.WriteMultiBuffer(payload); err != nil {
			return err
		}
		reader = nil
	}

	requestDone := func() error {
		defer timer.SetTimeout(plcy.Timeouts.DownlinkOnly)

		return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
	}

	responseDone := func() error {
		defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)

		v2writer := buf.NewWriter(conn)
		if err := buf.Copy(link.Reader, v2writer, buf.UpdateActivity(timer)); err != nil {
			return err
		}

		return nil
	}

	var closeWriter = task.OnSuccess(requestDone, task.Close(link.Writer))
	if err := task.Run(ctx, closeWriter, responseDone); err != nil {
		common.Interrupt(link.Reader)
		common.Interrupt(link.Writer)
		return newError("connection ends").Base(err)
	}

	return nil
}

var errWaitAnother = newError("keep alive")

func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher routing.Dispatcher) error {
	if !s.config.AllowTransparent && request.URL.Host == "" {
		// RFC 2068 (HTTP/1.1) requires URL to be absolute URL in HTTP proxy.
		response := &http.Response{
			Status:        "Bad Request",
			StatusCode:    400,
			Proto:         "HTTP/1.1",
			ProtoMajor:    1,
			ProtoMinor:    1,
			Header:        http.Header(make(map[string][]string)),
			Body:          nil,
			ContentLength: 0,
			Close:         true,
		}
		response.Header.Set("Proxy-Connection", "close")
		response.Header.Set("Connection", "close")
		return response.Write(writer)
	}

	if len(request.URL.Host) > 0 {
		request.Host = request.URL.Host
	}
	http_proto.RemoveHopByHopHeaders(request.Header)

	// Prevent UA from being set to golang's default ones
	if request.Header.Get("User-Agent") == "" {
		request.Header.Set("User-Agent", "")
	}

	content := &session.Content{
		Protocol: "http/1.1",
	}

	content.SetAttribute(":method", strings.ToUpper(request.Method))
	content.SetAttribute(":path", request.URL.Path)
	for key := range request.Header {
		value := request.Header.Get(key)
		content.SetAttribute(strings.ToLower(key), value)
	}

	ctx = session.ContextWithContent(ctx, content)

	link, err := dispatcher.Dispatch(ctx, dest)
	if err != nil {
		return err
	}

	// Plain HTTP request is not a stream. The request always finishes before response. Hense request has to be closed later.
	defer common.Close(link.Writer) // nolint: errcheck
	var result error = errWaitAnother

	requestDone := func() error {
		request.Header.Set("Connection", "close")

		requestWriter := buf.NewBufferedWriter(link.Writer)
		common.Must(requestWriter.SetBuffered(false))
		if err := request.Write(requestWriter); err != nil {
			return newError("failed to write whole request").Base(err).AtWarning()
		}
		return nil
	}

	responseDone := func() error {
		responseReader := bufio.NewReaderSize(&buf.BufferedReader{Reader: link.Reader}, buf.Size)
		response, err := http.ReadResponse(responseReader, request)
		if err == nil {
			http_proto.RemoveHopByHopHeaders(response.Header)
			if response.ContentLength >= 0 {
				response.Header.Set("Proxy-Connection", "keep-alive")
				response.Header.Set("Connection", "keep-alive")
				response.Header.Set("Keep-Alive", "timeout=4")
				response.Close = false
			} else {
				response.Close = true
				result = nil
			}
		} else {
			newError("failed to read response from ", request.Host).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
			response = &http.Response{
				Status:        "Service Unavailable",
				StatusCode:    503,
				Proto:         "HTTP/1.1",
				ProtoMajor:    1,
				ProtoMinor:    1,
				Header:        http.Header(make(map[string][]string)),
				Body:          nil,
				ContentLength: 0,
				Close:         true,
			}
			response.Header.Set("Connection", "close")
			response.Header.Set("Proxy-Connection", "close")
		}
		if err := response.Write(writer); err != nil {
			return newError("failed to write response").Base(err).AtWarning()
		}
		return nil
	}

	if err := task.Run(ctx, requestDone, responseDone); err != nil {
		common.Interrupt(link.Reader)
		common.Interrupt(link.Writer)
		return newError("connection ends").Base(err)
	}

	return result
}

func init() {
	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		return NewServer(ctx, config.(*ServerConfig))
	}))
}
<commit_msg>支持非抢先验证的客户端<commit_after>// +build !confonly

package http

import (
	"bufio"
	"context"
	"encoding/base64"
	"io"
	"net/http"
	"strings"
	"time"

	"v2ray.com/core"
	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/errors"
	"v2ray.com/core/common/log"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	http_proto "v2ray.com/core/common/protocol/http"
	"v2ray.com/core/common/session"
	"v2ray.com/core/common/signal"
	"v2ray.com/core/common/task"
	"v2ray.com/core/features/policy"
	"v2ray.com/core/features/routing"
	"v2ray.com/core/transport/internet"
)

// Server is an HTTP proxy server.
type Server struct {
	config        *ServerConfig
	policyManager policy.Manager
}

// NewServer creates a new HTTP inbound handler.
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
	v := core.MustFromContext(ctx)
	s := &Server{
		config:        config,
		policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
	}

	return s, nil
}

func (s *Server) policy() policy.Session {
	config := s.config
	p := s.policyManager.ForLevel(config.UserLevel)
	if config.Timeout > 0 && config.UserLevel == 0 {
		p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second
	}
	return p
}

// Network implements proxy.Inbound.
func (*Server) Network() []net.Network {
	return []net.Network{net.Network_TCP}
}

func isTimeout(err error) bool {
	nerr, ok := errors.Cause(err).(net.Error)
	return ok && nerr.Timeout()
}

func parseBasicAuth(auth string) (username, password string, ok bool) {
	const prefix = "Basic "
	if !strings.HasPrefix(auth, prefix) {
		return
	}
	c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
	if err != nil {
		return
	}
	cs := string(c)
	s := strings.IndexByte(cs, ':')
	if s < 0 {
		return
	}
	return cs[:s], cs[s+1:], true
}

type readerOnly struct {
	io.Reader
}

func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
	inbound := session.InboundFromContext(ctx)
	if inbound != nil {
		inbound.User = &protocol.MemoryUser{
			Level: s.config.UserLevel,
		}
	}

	reader := bufio.NewReaderSize(readerOnly{conn}, buf.Size)

Start:
	if err := conn.SetReadDeadline(time.Now().Add(s.policy().Timeouts.Handshake)); err != nil {
		newError("failed to set read deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
	}

	request, err := http.ReadRequest(reader)
	if err != nil {
		trace := newError("failed to read http request").Base(err)
		if errors.Cause(err) != io.EOF && !isTimeout(errors.Cause(err)) {
			trace.AtWarning() // nolint: errcheck
		}
		return trace
	}

	if len(s.config.Accounts) > 0 {
		user, pass, ok := parseBasicAuth(request.Header.Get("Proxy-Authorization"))
		if !ok || !s.config.HasAccount(user, pass) {
			return common.Error2(conn.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic realm=\"proxy\"\r\nConnection: close\r\n\r\n")))
		}
		if inbound != nil {
			inbound.User.Email = user
		}
	}

	newError("request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]").WriteToLog(session.ExportIDToError(ctx))
	if err := conn.SetReadDeadline(time.Time{}); err != nil {
		newError("failed to clear read deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
	}

	defaultPort := net.Port(80)
	if strings.EqualFold(request.URL.Scheme, "https") {
		defaultPort = net.Port(443)
	}
	host := request.Host
	if host == "" {
		host = request.URL.Host
	}
	dest, err := http_proto.ParseHost(host, defaultPort)
	if err != nil {
		return newError("malformed proxy host: ", host).AtWarning().Base(err)
	}
	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
		From:   conn.RemoteAddr(),
		To:     request.URL,
		Status: log.AccessAccepted,
		Reason: "",
	})

	if strings.EqualFold(request.Method, "CONNECT") {
		return s.handleConnect(ctx, request, reader, conn, dest, dispatcher)
	}

	keepAlive := (strings.TrimSpace(strings.ToLower(request.Header.Get("Proxy-Connection"))) == "keep-alive")

	err = s.handlePlainHTTP(ctx, request, conn, dest, dispatcher)
	if err == errWaitAnother {
		if keepAlive {
			goto Start
		}
		err = nil
	}

	return err
}

func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher routing.Dispatcher) error {
	_, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
	if err != nil {
		return newError("failed to write back OK response").Base(err)
	}

	plcy := s.policy()
	ctx, cancel := context.WithCancel(ctx)
	timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)

	ctx = policy.ContextWithBufferPolicy(ctx, plcy.Buffer)
	link, err := dispatcher.Dispatch(ctx, dest)
	if err != nil {
		return err
	}

	if reader.Buffered() > 0 {
		payload, err := buf.ReadFrom(io.LimitReader(reader, int64(reader.Buffered())))
		if err != nil {
			return err
		}
		if err := link.Writer.WriteMultiBuffer(payload); err != nil {
			return err
		}
		reader = nil
	}

	requestDone := func() error {
		defer timer.SetTimeout(plcy.Timeouts.DownlinkOnly)

		return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
	}

	responseDone := func() error {
		defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)

		v2writer := buf.NewWriter(conn)
		if err := buf.Copy(link.Reader, v2writer, buf.UpdateActivity(timer)); err != nil {
			return err
		}

		return nil
	}

	var closeWriter = task.OnSuccess(requestDone, task.Close(link.Writer))
	if err := task.Run(ctx, closeWriter, responseDone); err != nil {
		common.Interrupt(link.Reader)
		common.Interrupt(link.Writer)
		return newError("connection ends").Base(err)
	}

	return nil
}

var errWaitAnother = newError("keep alive")

func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher routing.Dispatcher) error {
	if !s.config.AllowTransparent && request.URL.Host == "" {
		// RFC 2068 (HTTP/1.1) requires URL to be absolute URL in HTTP proxy.
		response := &http.Response{
			Status:        "Bad Request",
			StatusCode:    400,
			Proto:         "HTTP/1.1",
			ProtoMajor:    1,
			ProtoMinor:    1,
			Header:        http.Header(make(map[string][]string)),
			Body:          nil,
			ContentLength: 0,
			Close:         true,
		}
		response.Header.Set("Proxy-Connection", "close")
		response.Header.Set("Connection", "close")
		return response.Write(writer)
	}

	if len(request.URL.Host) > 0 {
		request.Host = request.URL.Host
	}
	http_proto.RemoveHopByHopHeaders(request.Header)

	// Prevent UA from being set to golang's default ones
	if request.Header.Get("User-Agent") == "" {
		request.Header.Set("User-Agent", "")
	}

	content := &session.Content{
		Protocol: "http/1.1",
	}

	content.SetAttribute(":method", strings.ToUpper(request.Method))
	content.SetAttribute(":path", request.URL.Path)
	for key := range request.Header {
		value := request.Header.Get(key)
		content.SetAttribute(strings.ToLower(key), value)
	}

	ctx = session.ContextWithContent(ctx, content)

	link, err := dispatcher.Dispatch(ctx, dest)
	if err != nil {
		return err
	}

	// Plain HTTP request is not a stream. The request always finishes before response. Hense request has to be closed later.
	defer common.Close(link.Writer) // nolint: errcheck
	var result error = errWaitAnother

	requestDone := func() error {
		request.Header.Set("Connection", "close")

		requestWriter := buf.NewBufferedWriter(link.Writer)
		common.Must(requestWriter.SetBuffered(false))
		if err := request.Write(requestWriter); err != nil {
			return newError("failed to write whole request").Base(err).AtWarning()
		}
		return nil
	}

	responseDone := func() error {
		responseReader := bufio.NewReaderSize(&buf.BufferedReader{Reader: link.Reader}, buf.Size)
		response, err := http.ReadResponse(responseReader, request)
		if err == nil {
			http_proto.RemoveHopByHopHeaders(response.Header)
			if response.ContentLength >= 0 {
				response.Header.Set("Proxy-Connection", "keep-alive")
				response.Header.Set("Connection", "keep-alive")
				response.Header.Set("Keep-Alive", "timeout=4")
				response.Close = false
			} else {
				response.Close = true
				result = nil
			}
		} else {
			newError("failed to read response from ", request.Host).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
			response = &http.Response{
				Status:        "Service Unavailable",
				StatusCode:    503,
				Proto:         "HTTP/1.1",
				ProtoMajor:    1,
				ProtoMinor:    1,
				Header:        http.Header(make(map[string][]string)),
				Body:          nil,
				ContentLength: 0,
				Close:         true,
			}
			response.Header.Set("Connection", "close")
			response.Header.Set("Proxy-Connection", "close")
		}
		if err := response.Write(writer); err != nil {
			return newError("failed to write response").Base(err).AtWarning()
		}
		return nil
	}

	if err := task.Run(ctx, requestDone, responseDone); err != nil {
		common.Interrupt(link.Reader)
		common.Interrupt(link.Writer)
		return newError("connection ends").Base(err)
	}

	return result
}

func init() {
	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		return NewServer(ctx, config.(*ServerConfig))
	}))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
	"testing"
)

func TestMissingScopesOSGroups(t *testing.T) {
	setup(t)
	payload := GenericWorkerPayload{
		Command:    helloGoodbye(),
		MaxRunTime: 1,
		OSGroups:   []string{"abc", "def"},
	}
	td := testTask()
	// don't set any scopes
	taskID, myQueue := submitTask(t, td, payload)
	runWorker()

	// check task had exception/malformed-payload
	tsr, err := myQueue.Status(taskID)
	if err != nil {
		t.Fatalf("Problem querying status of task %v: %v", taskID, err)
	}
	if tsr.Status.State != "exception" || tsr.Status.Runs[0].ReasonResolved != "malformed-payload" {
		t.Fatalf("Task %v did not complete as intended - it resolved as %v/%v but should have resolved as exception/malformed-payload", taskID, tsr.Status.State, tsr.Status.Runs[0].ReasonResolved)
	}

	// check log mentions both missing scopes
	bytes, err := ioutil.ReadFile(filepath.Join(taskContext.TaskDir, "public", "logs", "live_backing.log"))
	if err != nil {
		t.Fatalf("Error when trying to read log file: %v", err)
	}
	logtext := string(bytes)
	if !strings.Contains(logtext, "generic-worker:os-group:abc") || !strings.Contains(logtext, "generic-worker:os-group:def") {
		t.Fatalf("Was expecting log file to contain missing scopes, but it doesn't")
	}
}

func TestOSGroupsRespected(t *testing.T) {
	setup(t)
	payload := GenericWorkerPayload{
		Command:    helloGoodbye(),
		MaxRunTime: 30,
		OSGroups:   []string{"abc", "def"},
	}
	td := testTask()
	td.Scopes = []string{"generic-worker:os-group:abc", "generic-worker:os-group:def"}
	taskID, myQueue := submitTask(t, td, payload)
	runWorker()

	if config.RunTasksAsCurrentUser {
		// check task resolved successfully
		tsr, err := myQueue.Status(taskID)
		if err != nil {
			t.Fatalf("Problem querying status of task %v: %v", taskID, err)
		}
		if tsr.Status.State != "completed" {
			t.Fatalf("Task %v resolved as %v/%v but should have resolved as completed", taskID, tsr.Status.State, tsr.Status.Runs[0].ReasonResolved)
		}

		// check log mentions both missing scopes
		bytes, err := ioutil.ReadFile(filepath.Join(taskContext.TaskDir, "public", "logs", "live_backing.log"))
		if err != nil {
			t.Fatalf("Error when trying to read log file: %v", err)
		}
		logtext := string(bytes)
		substring := fmt.Sprintf("Could not add os group(s) to task user: %v", payload.OSGroups)
		if !strings.Contains(logtext, substring) {
			t.Log(logtext)
			t.Fatalf("Was expecting log to contain string %v. Log content is actually:\n%v", substring, logtext)
		}
	} else {
		// check task had malformed payload, due to non existent groups
		tsr, err := myQueue.Status(taskID)
		if err != nil {
			t.Fatalf("Problem querying status of task %v: %v", taskID, err)
		}
		if tsr.Status.State != "exception" || tsr.Status.Runs[0].ReasonResolved != "malformed-payload" {
			t.Fatalf("Task %v resolved as %v/%v but should have resolved as exception/malformed-payload", taskID, tsr.Status.State, tsr.Status.Runs[0].ReasonResolved)
		}

		// check log mentions both missing scopes
		bytes, err := ioutil.ReadFile(filepath.Join(taskContext.TaskDir, "public", "logs", "live_backing.log"))
		if err != nil {
			t.Fatalf("Error when trying to read log file: %v", err)
		}
		logtext := string(bytes)
		substring := fmt.Sprintf("Not adding user to groups %v since we are running as current user.", payload.OSGroups)
		if !strings.Contains(logtext, substring) {
			t.Log(logtext)
			t.Fatalf("Was expecting log to contain string %v. Log content is actually:\n%v", substring, logtext)
		}
	}
}
<commit_msg>try again<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
	"testing"
)

func TestMissingScopesOSGroups(t *testing.T) {
	setup(t)
	payload := GenericWorkerPayload{
		Command:    helloGoodbye(),
		MaxRunTime: 1,
		OSGroups:   []string{"abc", "def"},
	}
	td := testTask()
	// don't set any scopes
	taskID, myQueue := submitTask(t, td, payload)
	runWorker()

	// check task had exception/malformed-payload
	tsr, err := myQueue.Status(taskID)
	if err != nil {
		t.Fatalf("Problem querying status of task %v: %v", taskID, err)
	}
	if tsr.Status.State != "exception" || tsr.Status.Runs[0].ReasonResolved != "malformed-payload" {
		t.Fatalf("Task %v did not complete as intended - it resolved as %v/%v but should have resolved as exception/malformed-payload", taskID, tsr.Status.State, tsr.Status.Runs[0].ReasonResolved)
	}

	// check log mentions both missing scopes
	bytes, err := ioutil.ReadFile(filepath.Join(taskContext.TaskDir, "public", "logs", "live_backing.log"))
	if err != nil {
		t.Fatalf("Error when trying to read log file: %v", err)
	}
	logtext := string(bytes)
	if !strings.Contains(logtext, "generic-worker:os-group:abc") || !strings.Contains(logtext, "generic-worker:os-group:def") {
		t.Fatalf("Was expecting log file to contain missing scopes, but it doesn't")
	}
}

func TestOSGroupsRespected(t *testing.T) {
	setup(t)
	payload := GenericWorkerPayload{
		Command:    helloGoodbye(),
		MaxRunTime: 30,
		OSGroups:   []string{"abc", "def"},
	}
	td := testTask()
	td.Scopes = []string{"generic-worker:os-group:abc", "generic-worker:os-group:def"}
	taskID, myQueue := submitTask(t, td, payload)
	runWorker()

	if config.RunTasksAsCurrentUser {
		// check task resolved successfully
		tsr, err := myQueue.Status(taskID)
		if err != nil {
			t.Fatalf("Problem querying status of task %v: %v", taskID, err)
		}
		if tsr.Status.State != "completed" {
			t.Fatalf("Task %v resolved as %v/%v but should have resolved as completed", taskID, tsr.Status.State, tsr.Status.Runs[0].ReasonResolved)
		}

		// check log mentions both missing scopes
		bytes, err := ioutil.ReadFile(filepath.Join(taskContext.TaskDir, "public", "logs", "live_backing.log"))
		if err != nil {
			t.Fatalf("Error when trying to read log file: %v", err)
		}
		logtext := string(bytes)
		substring := fmt.Sprintf("Not adding user to groups %v since we are running as current user.", payload.OSGroups)
		if !strings.Contains(logtext, substring) {
			t.Log(logtext)
			t.Fatalf("Was expecting log to contain string %v.", substring)
		}
	} else {
		// check task had malformed payload, due to non existent groups
		tsr, err := myQueue.Status(taskID)
		if err != nil {
			t.Fatalf("Problem querying status of task %v: %v", taskID, err)
		}
		if tsr.Status.State != "exception" || tsr.Status.Runs[0].ReasonResolved != "malformed-payload" {
			t.Fatalf("Task %v resolved as %v/%v but should have resolved as exception/malformed-payload", taskID, tsr.Status.State, tsr.Status.Runs[0].ReasonResolved)
		}

		// check log mentions both missing scopes
		bytes, err := ioutil.ReadFile(filepath.Join(taskContext.TaskDir, "public", "logs", "live_backing.log"))
		if err != nil {
			t.Fatalf("Error when trying to read log file: %v", err)
		}
		logtext := string(bytes)
		substring := fmt.Sprintf("Could not add os group(s) to task user: %v", payload.OSGroups)
		if !strings.Contains(logtext, substring) {
			t.Log(logtext)
			t.Fatalf("Was expecting log to contain string %v.", substring)
		}
	}
}
<|endoftext|>


<commit_before>/**
* Author: CZ cz.theng@gmail.com
 */

package ossapi

import (
	"encoding/xml"
	"fmt"
)

type Bucket struct {
	Name         string
	CreationDate string
	Location     string
}

type Buckets struct {
	Bucket []Bucket
}

type Owner struct {
	ID          string
	DisplayName string
}

type BucketsInfo struct {
	XMLName     xml.Name `xml:"ListAllMyBucketsResult"`
	Prefix      string   `xml:"Prefix"`
	Marker      string   `xml:"Marker"`
	MaxKeys     int      `xml:"MaxKeys"`
	IsTruncated bool     `xml:"IsTruncated"`
	NextMarker  string   `xml:"NextMarker"`
	Owner       Owner    `xml:"Owner"`
	Buckets     Buckets  `xml:"Buckets"`
}

func GetServiceWith(prefix, marker string, maxKeys int) (bucketsInfo *BucketsInfo, error *Error) {
	args := ""
	path := "/"
	if "" != prefix {
		args += "prefix=" + prefix
	}
	if "" != marker {
		args += "marker=" + marker
	}
	if 0 < maxKeys && maxKeys <= 1000 {
		args += "maxkeys=" + string(maxKeys)
	}

	if "" != args {
		path += "?" + args
	}
	Logger.Info("path is %s", path)
	req := &Request{Host: "oss.aliyuncs.com", Path: "/", Method: "GET", Resource: "/"}
	rsp, err := req.Send()
	if err != nil {
		if _, ok := err.(*Error); !ok {
			Logger.Error("GetService's Send Error:%s", err.Error())
			error = &Error{ErrNo: EAPI,
				ErrMsg:       "OSSAPI SDK's Inner Error,You Can Find More Details In Log Files",
				ErrDetailMsg: "OSSAPI SDK's Inner Error,You Can Find More Details In Log Files"}
			return
		}
	}
	if rsp.Result != ESUCC {
		error = err.(*Error)
		return
	}
	body := make([]byte, 10000)
	rsp.httpRsp.Body.Read(body)
	fmt.Println(string(body))
	bucketsInfo = new(BucketsInfo)
	xml.Unmarshal(body, bucketsInfo)
	return
}

func GetService() (bucketsInfo *BucketsInfo, err *Error) {
	bucketsInfo, err = GetServiceWith("", "", 0)
	return
}
<commit_msg>delete print<commit_after>/**
* Author: CZ cz.theng@gmail.com
 */

package ossapi

import (
	"encoding/xml"
)

type Bucket struct {
	Name         string
	CreationDate string
	Location     string
}

type Buckets struct {
	Bucket []Bucket
}

type Owner struct {
	ID          string
	DisplayName string
}

type BucketsInfo struct {
	XMLName     xml.Name `xml:"ListAllMyBucketsResult"`
	Prefix      string   `xml:"Prefix"`
	Marker      string   `xml:"Marker"`
	MaxKeys     int      `xml:"MaxKeys"`
	IsTruncated bool     `xml:"IsTruncated"`
	NextMarker  string   `xml:"NextMarker"`
	Owner       Owner    `xml:"Owner"`
	Buckets     Buckets  `xml:"Buckets"`
}

func GetServiceWith(prefix, marker string, maxKeys int) (bucketsInfo *BucketsInfo, error *Error) {
	args := ""
	path := "/"
	if "" != prefix {
		args += "prefix=" + prefix
	}
	if "" != marker {
		args += "marker=" + marker
	}
	if 0 < maxKeys && maxKeys <= 1000 {
		args += "maxkeys=" + string(maxKeys)
	}

	if "" != args {
		path += "?" + args
	}
	Logger.Info("path is %s", path)
	req := &Request{Host: "oss.aliyuncs.com", Path: "/", Method: "GET", Resource: "/"}
	rsp, err := req.Send()
	if err != nil {
		if _, ok := err.(*Error); !ok {
			Logger.Error("GetService's Send Error:%s", err.Error())
			error = &Error{ErrNo: EAPI,
				ErrMsg:       "OSSAPI SDK's Inner Error,You Can Find More Details In Log Files",
				ErrDetailMsg: "OSSAPI SDK's Inner Error,You Can Find More Details In Log Files"}
			return
		}
	}
	if rsp.Result != ESUCC {
		error = err.(*Error)
		return
	}
	body := make([]byte, 10000)
	rsp.httpRsp.Body.Read(body)
	bucketsInfo = new(BucketsInfo)
	xml.Unmarshal(body, bucketsInfo)
	return
}

func GetService() (bucketsInfo *BucketsInfo, err *Error) {
	bucketsInfo, err = GetServiceWith("", "", 0)
	return
}
<|endoftext|>


<commit_before>package svg

// generated by hasher -type=Hash -file=hash.go; DO NOT EDIT, except for adding more constants to the list and rerun go generate

// uses github.com/tdewolff/hasher
//go:generate hasher -type=Hash -file=hash.go
type Hash uint32

const (
	A             Hash = 0x901
	D             Hash = 0x1
	Defs          Hash = 0x4
	G             Hash = 0x2301
	Height        Hash = 0x2906
	Line          Hash = 0x4d04
	Marker        Hash = 0x806
	Mask          Hash = 0x1104
	Metadata      Hash = 0x1508
	Missing_Glyph Hash = 0x1d0d
	Path          Hash = 0x2f04
	Pattern       Hash = 0x3307
	Points        Hash = 0x3a06
	Polygon       Hash = 0x4207
	Polyline      Hash = 0x4908
	Rect          Hash = 0xd04
	Rx            Hash = 0x5102
	Ry            Hash = 0x5402
	Style         Hash = 0x305
	Svg           Hash = 0x3f03
	Switch        Hash = 0x5706
	Symbol        Hash = 0x5d06
	Version       Hash = 0x6307
	ViewBox       Hash = 0x6a07
	Width         Hash = 0x7205
	X             Hash = 0x5201
	X1            Hash = 0x5202
	X2            Hash = 0x7002
	Y             Hash = 0x501
	Y1            Hash = 0x5502
	Y2            Hash = 0x7702
)

// String returns the hash' name.
func (i Hash) String() string {
	start := uint32(i >> 8)
	n := uint32(i & 0xff)
	if start+n > uint32(len(_Hash_text)) {
		return ""
	}
	return _Hash_text[start : start+n]
}

// Hash returns the hash whose name is s. It returns zero if there is no
// such hash. It is case sensitive.
func ToHash(s []byte) Hash {
	if len(s) == 0 || len(s) > _Hash_maxLen {
		return 0
	}
	h := _Hash_fnv(s)
	if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) && _Hash_match(_Hash_string(i), s) {
		return i
	}
	if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) && _Hash_match(_Hash_string(i), s) {
		return i
	}
	return 0
}

// _Hash_fnv computes the FNV hash with an arbitrary starting value h.
func _Hash_fnv(s []byte) uint32 {
	h := uint32(_Hash_hash0)
	for i := range s {
		h ^= uint32(s[i])
		h *= 16777619
	}
	return h
}

func _Hash_match(s string, t []byte) bool {
	for i, c := range t {
		if s[i] != c {
			return false
		}
	}
	return true
}

func _Hash_string(i Hash) string {
	return _Hash_text[i>>8 : i>>8+i&0xff]
}

const _Hash_hash0 = 0x9110278f
const _Hash_maxLen = 13
const _Hash_text = "defstylemarkerectmaskmetadatamissing-glypheightpathpatternpo" +
	"intsvgpolygonpolylinerx1ry1switchsymbolversionviewBox2widthy" +
	"2"

var _Hash_table = [1 << 5]Hash{
	0x0:  0x2906, // height
	0x1:  0x7205, // width
	0x2:  0x501,  // y
	0x3:  0x5d06, // symbol
	0x4:  0x2f04, // path
	0x5:  0x7002, // x2
	0x6:  0x4,    // defs
	0x7:  0x6a07, // viewBox
	0x8:  0x5102, // rx
	0x9:  0x5502, // y1
	0xa:  0x901,  // a
	0xb:  0x1104, // mask
	0xc:  0x5202, // x1
	0xd:  0x4d04, // line
	0xe:  0x1,    // d
	0xf:  0x3307, // pattern
	0x10: 0x806,  // marker
	0x11: 0xd04,  // rect
	0x12: 0x305,  // style
	0x13: 0x3f03, // svg
	0x15: 0x5201, // x
	0x16: 0x6307, // version
	0x17: 0x7702, // y2
	0x18: 0x2301, // g
	0x19: 0x5706, // switch
	0x1a: 0x5402, // ry
	0x1b: 0x4908, // polyline
	0x1c: 0x3a06, // points
	0x1d: 0x1508, // metadata
	0x1e: 0x1d0d, // missing-glyph
	0x1f: 0x4207, // polygon
}
<commit_msg>More hashes<commit_after>package svg

// generated by hasher -type=Hash -file=hash.go; DO NOT EDIT, except for adding more constants to the list and rerun go generate

// uses github.com/tdewolff/hasher
//go:generate hasher -type=Hash -file=hash.go
type Hash uint32

const (
	A              Hash = 0x3101
	D              Hash = 0x1
	Defs           Hash = 0x4
	Fill           Hash = 0x1004
	Flood_Color    Hash = 0x230b
	G              Hash = 0x1501
	Height         Hash = 0x4e06
	Lighting_Color Hash = 0x130e
	Line           Hash = 0x7504
	Marker         Hash = 0x3006
	Mask           Hash = 0x3604
	Metadata       Hash = 0x3a08
	Missing_Glyph  Hash = 0x420d
	Path           Hash = 0x5404
	Pattern        Hash = 0x5807
	Points         Hash = 0x5f06
	Polygon        Hash = 0x6a07
	Polyline       Hash = 0x7108
	Rect           Hash = 0xc04
	Rx             Hash = 0x2002
	Ry             Hash = 0x2d02
	Stop_Color     Hash = 0x30a
	Stroke         Hash = 0x6406
	Style          Hash = 0x7905
	Svg            Hash = 0x7e03
	Switch         Hash = 0x8106
	Symbol         Hash = 0x8706
	Version        Hash = 0x8d07
	ViewBox        Hash = 0x9407
	Width          Hash = 0x9c05
	X              Hash = 0x2101
	X1             Hash = 0x2102
	X2             Hash = 0x9a02
	Y              Hash = 0x2e01
	Y1             Hash = 0x2e02
	Y2             Hash = 0xa102
)

// String returns the hash' name.
func (i Hash) String() string {
	start := uint32(i >> 8)
	n := uint32(i & 0xff)
	if start+n > uint32(len(_Hash_text)) {
		return ""
	}
	return _Hash_text[start : start+n]
}

// Hash returns the hash whose name is s. It returns zero if there is no
// such hash. It is case sensitive.
func ToHash(s []byte) Hash {
	if len(s) == 0 || len(s) > _Hash_maxLen {
		return 0
	}
	h := _Hash_fnv(s)
	if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) && _Hash_match(_Hash_string(i), s) {
		return i
	}
	if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) && _Hash_match(_Hash_string(i), s) {
		return i
	}
	return 0
}

// _Hash_fnv computes the FNV hash with an arbitrary starting value h.
func _Hash_fnv(s []byte) uint32 {
	h := uint32(_Hash_hash0)
	for i := range s {
		h ^= uint32(s[i])
		h *= 16777619
	}
	return h
}

func _Hash_match(s string, t []byte) bool {
	for i, c := range t {
		if s[i] != c {
			return false
		}
	}
	return true
}

func _Hash_string(i Hash) string {
	return _Hash_text[i>>8 : i>>8+i&0xff]
}

const _Hash_hash0 = 0xaa209b8e
const _Hash_maxLen = 14
const _Hash_text = "defstop-colorectfillighting-colorx1flood-colory1markermaskme" +
	"tadatamissing-glypheightpathpatternpointstrokepolygonpolylin" +
	"estylesvgswitchsymbolversionviewBox2widthy2"

var _Hash_table = [1 << 6]Hash{
	0x2:  0x2101, // x
	0x3:  0x1004, // fill
	0x6:  0x8706, // symbol
	0x9:  0x2102, // x1
	0xa:  0x5404, // path
	0xb:  0x1501, // g
	0xc:  0x3604, // mask
	0xd:  0x9c05, // width
	0x10: 0x9a02, // x2
	0x14: 0x30a,  // stop-color
	0x15: 0x2e01, // y
	0x18: 0x4,    // defs
	0x1c: 0x5807, // pattern
	0x1d: 0x7504, // line
	0x1e: 0x1,    // d
	0x20: 0x230b, // flood-color
	0x21: 0xa102, // y2
	0x22: 0x6406, // stroke
	0x24: 0x2002, // rx
	0x25: 0x4e06, // height
	0x26: 0xc04,  // rect
	0x29: 0x5f06, // points
	0x2b: 0x6a07, // polygon
	0x2c: 0x2e02, // y1
	0x2d: 0x420d, // missing-glyph
	0x2e: 0x2d02, // ry
	0x2f: 0x3006, // marker
	0x30: 0x9407, // viewBox
	0x32: 0x8d07, // version
	0x34: 0x7905, // style
	0x36: 0x8106, // switch
	0x37: 0x7e03, // svg
	0x3a: 0x7108, // polyline
	0x3b: 0x3a08, // metadata
	0x3c: 0x130e, // lighting-color
	0x3d: 0x3101, // a
}
<|endoftext|>


<commit_before>//   Copyright 2017 MSolution.IO
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package routes

import (
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

const (
	maxUint = ^uint(0)
	maxInt  = int(maxUint >> 1)
	minInt  = -maxInt - 1
	// TagRequiredQueryArg is the tag used to document required query args.
	TagRequiredQueryArg = "required:allof:queryarg"
	// TagOptionalQueryArg is the tag used to document optional query args.
	TagOptionalQueryArg = "optional:allof:queryarg"
)

type (
	// QueryArgInt denotes an int query argument. It fulfills the QueryParser
	// interface.
	QueryArgInt struct{}

	// QueryArgUint denotes a uint query argument. It fulfills the QueryParser
	// interface.
	QueryArgUint struct{}

	// QueryArgString denotes a string query argument. It fulfills the QueryParser
	// interface.
	QueryArgString struct{}

	// QueryArgIntSlice denotes a []int query argument. It fulfills the QueryParser
	// interface.
	QueryArgIntSlice struct{}

	// QueryArgUintSlice denotes a []uint query argument. It fulfills the QueryParser
	// interface.
	QueryArgUintSlice struct{}

	// QueryParser parses a string and returns a typed value. An error can
	// be returned if the value could not be parsed.
	QueryParser interface {
		// QueryParse parses a query string argument.
		QueryParse(string) (interface{}, error)
		// FormatName returns the name of the parameter type.
		FormatName() string
	}

	// QueryArg defines an argument by its name and its type. A description
	// can be used for documentation purposes. The argument can be optional
	// by changing the Optional value to true.
	QueryArg struct {
		Name        string
		Description string
		Type        QueryParser
		Optional    bool
	}

	// QueryArgs contains all the arguments to parse in the URL.
	// QueryArgs has a method Decorate called to apply the
	// decorators on an endpoint.
	QueryArgs []QueryArg
)

// QueryParse parses an int. A nil error indicates a success. With this func,
// QueryArgInt fulfills QueryArgType.
func (d QueryArgInt) QueryParse(val string) (interface{}, error) {
	if i, err := strconv.ParseInt(val, 10, 64); err == nil &&
		i <= int64(maxInt) && i >= int64(minInt) {
		return int(i), nil
	}
	return nil, errors.New("must be an int")
}

func (d QueryArgInt) FormatName() string       { return "int" }
func (d QueryArgUint) FormatName() string      { return "uint" }
func (d QueryArgString) FormatName() string    { return "string" }
func (d QueryArgIntSlice) FormatName() string  { return "[]int" }
func (d QueryArgUintSlice) FormatName() string { return "[]uint" }

// QueryParse parses a uint. A nil error indicates a success. With this func,
// QueryArgUint fulfills QueryArgType.
func (d QueryArgUint) QueryParse(val string) (interface{}, error) {
	if i, err := strconv.ParseUint(val, 10, 64); err == nil &&
		i <= uint64(maxUint) {
		return uint(i), nil
	}
	return nil, errors.New("must be a uint")
}

// QueryParse parses a string. A nil error indicates a success. With this func,
// QueryArgString fulfills QueryArgType.
func (d QueryArgString) QueryParse(val string) (interface{}, error) {
	return val, nil
}

// QueryParse parses an []int. A nil error indicates a success. With this func,
// QueryArgIntSlice fulfills QueryArgType.
func (d QueryArgIntSlice) QueryParse(val string) (interface{}, error) {
	vals := strings.Split(val, ",")
	res := make([]int, 0, len(vals))
	for _, v := range vals {
		if i, err := strconv.ParseInt(v, 10, 64); err == nil &&
			i <= int64(maxInt) && i >= int64(minInt) {
			res = append(res, int(i))
		} else {
			return nil, errors.New("must be a slice of int")
		}
	}
	return res, nil
}

// QueryParse parses an []uint. A nil error indicates a success. With this func,
// QueryArgUintSlice fulfills QueryArgType.
func (d QueryArgUintSlice) QueryParse(val string) (interface{}, error) {
	vals := strings.Split(val, ",")
	res := make([]uint, 0, len(vals))
	for _, v := range vals {
		if i, err := strconv.ParseUint(v, 10, 64); err == nil &&
			i <= uint64(maxUint) {
			res = append(res, uint(i))
		} else {
			return nil, errors.New("must be a slice of uint")
		}
	}
	return res, nil
}

func parseArg(arg QueryArg, r *http.Request, a Arguments) (int, error) {
	if rawVal := r.URL.Query().Get(arg.Name); rawVal != "" {
		if val, err := arg.Type.QueryParse(rawVal); err == nil {
			a[arg] = val
		} else {
			return http.StatusBadRequest, fmt.Errorf("query arg '%s': %s", arg.Name, err.Error())
		}
	} else if !arg.Optional {
		return http.StatusBadRequest, fmt.Errorf("query arg '%s': not found", arg.Name)
	}
	return http.StatusOK, nil
}

// Decorate is the function called to apply the decorators to an endpoint. It returns
// a function. This function produces a 400 error code with a json error message or
// calls the next IntermediateHandler.
// The goal of this function is to get the URL parameters to store them in
// the Arguments.
func (qa QueryArgs) Decorate(h Handler) Handler {
	h.Func = qa.getFunc(h.Func)
	h.Documentation = qa.getDocumentation(h.Documentation)
	return h
}

// getFunc builds a handler function for QueryArgs.Decorate
func (qa QueryArgs) getFunc(hf HandlerFunc) HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, a Arguments) (int, interface{}) {
		for _, arg := range qa {
			if code, err := parseArg(arg, r, a); code != http.StatusOK {
				return code, err
			}
		}
		return hf(w, r, a)
	}
}

// createDocumentationSlice creates the slice of string and fills it with documentation
func createDocumentationSlice(index string, optional bool, qa QueryArgs) []string {
	ts := make([]string, 0)
	for i := range qa {
		if qa[i].Optional == optional {
			ts = append(ts, fmt.Sprintf("%s:%s:%s", qa[i].Name, qa[i].Type.FormatName(), qa[i].Description))
		}
	}
	return ts
}

// getDocumentation builds the documentation for QueryArgs.Decorate
func (qa QueryArgs) getDocumentation(hd HandlerDocumentation) HandlerDocumentation {
	if hd.Tags == nil {
		hd.Tags = make(Tags)
	}
	hd.Tags[TagRequiredContentType] = append(hd.Tags[TagRequiredQueryArg], createDocumentationSlice(TagRequiredQueryArg, false, qa)...)
	hd.Tags[TagOptionalQueryArg] = append(hd.Tags[TagOptionalQueryArg], createDocumentationSlice(TagOptionalQueryArg, true, qa)...)
	return hd
}
<commit_msg>routes: fixed typo on the generated documentation<commit_after>//   Copyright 2017 MSolution.IO
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package routes

import (
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

const (
	maxUint = ^uint(0)
	maxInt  = int(maxUint >> 1)
	minInt  = -maxInt - 1
	// TagRequiredQueryArg is the tag used to document required query args.
	TagRequiredQueryArg = "required:allof:queryarg"
	// TagOptionalQueryArg is the tag used to document optional query args.
	TagOptionalQueryArg = "optional:allof:queryarg"
)

type (
	// QueryArgInt denotes an int query argument. It fulfills the QueryParser
	// interface.
	QueryArgInt struct{}

	// QueryArgUint denotes a uint query argument. It fulfills the QueryParser
	// interface.
	QueryArgUint struct{}

	// QueryArgString denotes a string query argument. It fulfills the QueryParser
	// interface.
	QueryArgString struct{}

	// QueryArgIntSlice denotes a []int query argument. It fulfills the QueryParser
	// interface.
	QueryArgIntSlice struct{}

	// QueryArgUintSlice denotes a []uint query argument. It fulfills the QueryParser
	// interface.
	QueryArgUintSlice struct{}

	// QueryParser parses a string and returns a typed value. An error can
	// be returned if the value could not be parsed.
	QueryParser interface {
		// QueryParse parses a query string argument.
		QueryParse(string) (interface{}, error)
		// FormatName returns the name of the parameter type.
		FormatName() string
	}

	// QueryArg defines an argument by its name and its type. A description
	// can be used for documentation purposes. The argument can be optional
	// by changing the Optional value to true.
	QueryArg struct {
		Name        string
		Description string
		Type        QueryParser
		Optional    bool
	}

	// QueryArgs contains all the arguments to parse in the URL.
	// QueryArgs has a method Decorate called to apply the
	// decorators on an endpoint.
	QueryArgs []QueryArg
)

// QueryParse parses an int. A nil error indicates a success. With this func,
// QueryArgInt fulfills QueryArgType.
func (d QueryArgInt) QueryParse(val string) (interface{}, error) {
	if i, err := strconv.ParseInt(val, 10, 64); err == nil &&
		i <= int64(maxInt) && i >= int64(minInt) {
		return int(i), nil
	}
	return nil, errors.New("must be an int")
}

func (d QueryArgInt) FormatName() string       { return "int" }
func (d QueryArgUint) FormatName() string      { return "uint" }
func (d QueryArgString) FormatName() string    { return "string" }
func (d QueryArgIntSlice) FormatName() string  { return "[]int" }
func (d QueryArgUintSlice) FormatName() string { return "[]uint" }

// QueryParse parses a uint. A nil error indicates a success. With this func,
// QueryArgUint fulfills QueryArgType.
func (d QueryArgUint) QueryParse(val string) (interface{}, error) {
	if i, err := strconv.ParseUint(val, 10, 64); err == nil &&
		i <= uint64(maxUint) {
		return uint(i), nil
	}
	return nil, errors.New("must be a uint")
}

// QueryParse parses a string. A nil error indicates a success. With this func,
// QueryArgString fulfills QueryArgType.
func (d QueryArgString) QueryParse(val string) (interface{}, error) {
	return val, nil
}

// QueryParse parses an []int. A nil error indicates a success. With this func,
// QueryArgIntSlice fulfills QueryArgType.
func (d QueryArgIntSlice) QueryParse(val string) (interface{}, error) {
	vals := strings.Split(val, ",")
	res := make([]int, 0, len(vals))
	for _, v := range vals {
		if i, err := strconv.ParseInt(v, 10, 64); err == nil &&
			i <= int64(maxInt) && i >= int64(minInt) {
			res = append(res, int(i))
		} else {
			return nil, errors.New("must be a slice of int")
		}
	}
	return res, nil
}

// QueryParse parses an []uint. A nil error indicates a success. With this func,
// QueryArgUintSlice fulfills QueryArgType.
func (d QueryArgUintSlice) QueryParse(val string) (interface{}, error) {
	vals := strings.Split(val, ",")
	res := make([]uint, 0, len(vals))
	for _, v := range vals {
		if i, err := strconv.ParseUint(v, 10, 64); err == nil &&
			i <= uint64(maxUint) {
			res = append(res, uint(i))
		} else {
			return nil, errors.New("must be a slice of uint")
		}
	}
	return res, nil
}

func parseArg(arg QueryArg, r *http.Request, a Arguments) (int, error) {
	if rawVal := r.URL.Query().Get(arg.Name); rawVal != "" {
		if val, err := arg.Type.QueryParse(rawVal); err == nil {
			a[arg] = val
		} else {
			return http.StatusBadRequest, fmt.Errorf("query arg '%s': %s", arg.Name, err.Error())
		}
	} else if !arg.Optional {
		return http.StatusBadRequest, fmt.Errorf("query arg '%s': not found", arg.Name)
	}
	return http.StatusOK, nil
}

// Decorate is the function called to apply the decorators to an endpoint. It returns
// a function. This function produces a 400 error code with a json error message or
// calls the next IntermediateHandler.
// The goal of this function is to get the URL parameters to store them in
// the Arguments.
func (qa QueryArgs) Decorate(h Handler) Handler {
	h.Func = qa.getFunc(h.Func)
	h.Documentation = qa.getDocumentation(h.Documentation)
	return h
}

// getFunc builds a handler function for QueryArgs.Decorate
func (qa QueryArgs) getFunc(hf HandlerFunc) HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, a Arguments) (int, interface{}) {
		for _, arg := range qa {
			if code, err := parseArg(arg, r, a); code != http.StatusOK {
				return code, err
			}
		}
		return hf(w, r, a)
	}
}

// createDocumentationSlice creates the slice of string and fills it with documentation
func createDocumentationSlice(index string, optional bool, qa QueryArgs) []string {
	ts := make([]string, 0)
	for i := range qa {
		if qa[i].Optional == optional {
			ts = append(ts, fmt.Sprintf("%s:%s:%s", qa[i].Name, qa[i].Type.FormatName(), qa[i].Description))
		}
	}
	return ts
}

// getDocumentation builds the documentation for QueryArgs.Decorate
func (qa QueryArgs) getDocumentation(hd HandlerDocumentation) HandlerDocumentation {
	if hd.Tags == nil {
		hd.Tags = make(Tags)
	}
	hd.Tags[TagRequiredQueryArg] = append(hd.Tags[TagRequiredQueryArg], createDocumentationSlice(TagRequiredQueryArg, false, qa)...)
	hd.Tags[TagOptionalQueryArg] = append(hd.Tags[TagOptionalQueryArg], createDocumentationSlice(TagOptionalQueryArg, true, qa)...)
	return hd
}
<|endoftext|>


<commit_before>/*
goRBAC provides a lightweight role-based access control implementation
in Golang.

For the purposes of this package:

	* an identity has one or more roles.
	* a role requests access to a permission.
	* a permission is given to a role.

Thus, RBAC has the following model:

	* many to many relationship between identities and roles.
	* many to many relationship between roles and permissions.
	* roles can have parent roles.
*/
package gorbac

import (
	"sync"
)

const (
	bufferSize = 16
)

// Assertion function supplies more fine-grained permission controls.
type AssertionFunc func(string, string, *Rbac) bool

// RBAC
type Rbac struct {
	sync.RWMutex
	roles   map[string]Role
	factory RoleFactoryFunc
}

// Return a RBAC structure with a specific factory function.
// Role structure will be generated by the function.
func NewWithFactory(factory RoleFactoryFunc) *Rbac {
	rbac := &Rbac{
		roles:   make(map[string]Role, bufferSize),
		factory: factory,
	}
	return rbac
}

// Return a RBAC structure.
// The default role structure will be used.
func New() *Rbac {
	return NewWithFactory(newBaseRole)
}

// Set a role with `name`. It has `permissions` and `parents`.
// If the role is not existing, a new one will be created.
// This function will cover role's orignal permissions and parents.
func (rbac *Rbac) Set(name string, permissions []string, parents []string) {
	rbac.Lock()
	defer rbac.Unlock()
	role := rbac.getRole(name)
	role.Reset()
	for _, p := range permissions {
		role.AddPermission(p)
	}
	for _, pname := range parents {
		role.AddParent(pname)
	}
	rbac.roles[name] = role
}

// Add a role with `name`. It has `permissions` and `parents`.
// If the role is not existing, a new one will be created.
// This function will add new permissions and parents to the role,
// and keep orignals.
func (rbac *Rbac) Add(name string, permissions []string, parents []string) {
	rbac.Lock()
	defer rbac.Unlock()
	role := rbac.getRole(name)
	for _, p := range permissions {
		role.AddPermission(p)
	}
	for _, pname := range parents {
		role.AddParent(pname)
	}
	rbac.roles[name] = role
}

// Remove a role.
func (rbac *Rbac) Remove(name string) {
	rbac.Lock()
	defer rbac.Unlock()
	delete(rbac.roles, name)
}

// Internal getRole
func  (rbac *Rbac) getRole(name string) Role {
	role, ok := rbac.roles[name]
	if !ok {
		role = rbac.factory(rbac, name)
	}
	return role
}

// Return a role or nil if not exists.
func  (rbac *Rbac) Get(name string) Role {
	role, ok := rbac.roles[name]
	if !ok {
		return nil
	}
	return role
}

// Test if the `name` has `permission` in the `assert` condition.
func (rbac *Rbac) IsGranted(name, permission string,
	assert AssertionFunc) bool {
	rbac.RLock()
	defer rbac.RUnlock()
	if assert != nil && !assert(name, permission, rbac) {
		return false
	}
	if role, ok := rbac.roles[name]; ok {
		return role.HasPermission(permission)
	}
	return false
}
<commit_msg>RWMutex should be invisible<commit_after>/*
goRBAC provides a lightweight role-based access control implementation
in Golang.

For the purposes of this package:

	* an identity has one or more roles.
	* a role requests access to a permission.
	* a permission is given to a role.

Thus, RBAC has the following model:

	* many to many relationship between identities and roles.
	* many to many relationship between roles and permissions.
	* roles can have parent roles.
*/
package gorbac

import (
	"sync"
)

const (
	bufferSize = 16
)

// Assertion function supplies more fine-grained permission controls.
type AssertionFunc func(string, string, *Rbac) bool

// RBAC
type Rbac struct {
	mutex sync.RWMutex
	roles   map[string]Role
	factory RoleFactoryFunc
}

// Return a RBAC structure with a specific factory function.
// Role structure will be generated by the function.
func NewWithFactory(factory RoleFactoryFunc) *Rbac {
	rbac := &Rbac{
		roles:   make(map[string]Role, bufferSize),
		factory: factory,
	}
	return rbac
}

// Return a RBAC structure.
// The default role structure will be used.
func New() *Rbac {
	return NewWithFactory(newBaseRole)
}

// Set a role with `name`. It has `permissions` and `parents`.
// If the role is not existing, a new one will be created.
// This function will cover role's orignal permissions and parents.
func (rbac *Rbac) Set(name string, permissions []string, parents []string) {
	rbac.mutex.Lock()
	defer rbac.mutex.Unlock()
	role := rbac.getRole(name)
	role.Reset()
	for _, p := range permissions {
		role.AddPermission(p)
	}
	for _, pname := range parents {
		role.AddParent(pname)
	}
	rbac.roles[name] = role
}

// Add a role with `name`. It has `permissions` and `parents`.
// If the role is not existing, a new one will be created.
// This function will add new permissions and parents to the role,
// and keep orignals.
func (rbac *Rbac) Add(name string, permissions []string, parents []string) {
	rbac.mutex.Lock()
	defer rbac.mutex.Unlock()
	role := rbac.getRole(name)
	for _, p := range permissions {
		role.AddPermission(p)
	}
	for _, pname := range parents {
		role.AddParent(pname)
	}
	rbac.roles[name] = role
}

// Remove a role.
func (rbac *Rbac) Remove(name string) {
	rbac.mutex.Lock()
	defer rbac.mutex.Unlock()
	delete(rbac.roles, name)
}

// Internal getRole
func  (rbac *Rbac) getRole(name string) Role {
	role, ok := rbac.roles[name]
	if !ok {
		role = rbac.factory(rbac, name)
	}
	return role
}

// Return a role or nil if not exists.
func  (rbac *Rbac) Get(name string) Role {
	rbac.mutex.RLock()
	defer rbac.mutex.RUnlock()
	role, ok := rbac.roles[name]
	if !ok {
		return nil
	}
	return role
}

// Test if the `name` has `permission` in the `assert` condition.
func (rbac *Rbac) IsGranted(name, permission string,
	assert AssertionFunc) bool {
	rbac.mutex.RLock()
	defer rbac.mutex.RUnlock()
	if assert != nil && !assert(name, permission, rbac) {
		return false
	}
	if role, ok := rbac.roles[name]; ok {
		return role.HasPermission(permission)
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	// _ "expvar"

	"fmt"
	"koding/db/mongodb/modelhelper"
	"net/http"
	// _ "net/http/pprof" // Imported for side-effect of handling /debug/pprof.

	"socialapi/config"
	"socialapi/models"
	"socialapi/workers/api/handlers"
	"socialapi/workers/common/runner"
	"socialapi/workers/helper"
	notificationapi "socialapi/workers/notification/api"
	paymentapi "socialapi/workers/payment/api"
	"socialapi/workers/payment/stripe"
	sitemapapi "socialapi/workers/sitemap/api"
	trollmodeapi "socialapi/workers/trollmode/api"

	"github.com/rcrowley/go-tigertonic"
)

var (
	mux, nsMux *tigertonic.TrieServeMux

	Name = "SocialAPI"
)

func init() {
	mux = tigertonic.NewTrieServeMux()
	mux = notificationapi.InitHandlers(mux)
	mux = trollmodeapi.InitHandlers(mux)
	mux = sitemapapi.InitHandlers(mux)

	// add namespace support into
	// all handlers
	nsMux = tigertonic.NewTrieServeMux()
	nsMux.HandleNamespace("", mux)
	nsMux.HandleNamespace("/1.0", mux)
	tigertonic.SnakeCaseHTTPEquivErrors = true

}

func main() {
	r := runner.New(Name)
	if err := r.Init(); err != nil {
		fmt.Println(err)
		return
	}

	server := newServer(r.Conf)
	// shutdown server
	defer server.Close()

	mux = handlers.Inject(mux, r.Metrics)

	// init payment handlers, this done here instead of in `init()`
	// like others so we can've access to `metrics`
	mux = paymentapi.InitHandlers(mux, r.Metrics)

	mux.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello from socialapi")
	})

	// init redis
	redisConn := helper.MustInitRedisConn(r.Conf)
	defer redisConn.Close()

	// init mongo connection
	modelhelper.Initialize(r.Conf.Mongo)

	// init stripe client
	stripe.InitializeClientKey(config.MustGet().Stripe.SecretToken)

	go func() {
		err := stripe.CreateDefaultPlans()
		if err != nil {
			fmt.Println(err)
			panic(err)
		}
	}()

	r.Wait()
}

func newServer(conf *config.Config) *tigertonic.Server {
	// go metrics.Log(
	// 	metrics.DefaultRegistry,
	// 	60e9,
	// 	stdlog.New(os.Stderr, "metrics ", stdlog.Lmicroseconds),
	// )

	var handler http.Handler
	handler = tigertonic.WithContext(nsMux, models.Context{})
	if conf.Debug {
		handler = tigertonic.Logged(handler, nil)
	}

	addr := conf.Host + ":" + conf.Port

	server := tigertonic.NewServer(addr, handler)

	go listener(server)
	return server
}

func listener(server *tigertonic.Server) {
	if err := server.ListenAndServe(); nil != err {
		panic(err)
	}
}
<commit_msg>Social: use koding/logger for tiger tonic logging<commit_after>package main

import (
	// _ "expvar"

	"fmt"
	"koding/db/mongodb/modelhelper"
	"net/http"
	// _ "net/http/pprof" // Imported for side-effect of handling /debug/pprof.

	"socialapi/config"
	"socialapi/models"
	"socialapi/workers/api/handlers"
	"socialapi/workers/common/runner"
	"socialapi/workers/helper"
	notificationapi "socialapi/workers/notification/api"
	paymentapi "socialapi/workers/payment/api"
	"socialapi/workers/payment/stripe"
	sitemapapi "socialapi/workers/sitemap/api"
	trollmodeapi "socialapi/workers/trollmode/api"

	"github.com/rcrowley/go-tigertonic"
)

var (
	mux, nsMux *tigertonic.TrieServeMux

	Name = "SocialAPI"
)

func init() {
	mux = tigertonic.NewTrieServeMux()
	mux = notificationapi.InitHandlers(mux)
	mux = trollmodeapi.InitHandlers(mux)
	mux = sitemapapi.InitHandlers(mux)

	// add namespace support into
	// all handlers
	nsMux = tigertonic.NewTrieServeMux()
	nsMux.HandleNamespace("", mux)
	nsMux.HandleNamespace("/1.0", mux)
	tigertonic.SnakeCaseHTTPEquivErrors = true

}

func main() {
	r := runner.New(Name)
	if err := r.Init(); err != nil {
		fmt.Println(err)
		return
	}

	server := newServer(r)
	// shutdown server
	defer server.Close()

	mux = handlers.Inject(mux, r.Metrics)

	// init payment handlers, this done here instead of in `init()`
	// like others so we can've access to `metrics`
	mux = paymentapi.InitHandlers(mux, r.Metrics)

	mux.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello from socialapi")
	})

	// init redis
	redisConn := helper.MustInitRedisConn(r.Conf)
	defer redisConn.Close()

	// init mongo connection
	modelhelper.Initialize(r.Conf.Mongo)

	// init stripe client
	stripe.InitializeClientKey(config.MustGet().Stripe.SecretToken)

	go func() {
		err := stripe.CreateDefaultPlans()
		if err != nil {
			fmt.Println(err)
			panic(err)
		}
	}()

	r.Wait()
}

func newServer(r *runner.Runner) *tigertonic.Server {
	// go metrics.Log(
	// 	metrics.DefaultRegistry,
	// 	60e9,
	// 	stdlog.New(os.Stderr, "metrics ", stdlog.Lmicroseconds),
	// )

	conf := r.Conf

	var handler http.Handler
	handler = tigertonic.WithContext(nsMux, models.Context{})
	if conf.Debug {
		h := tigertonic.Logged(handler, nil)
		h.Logger = NewTigerTonicLogger(r.Log)
		handler = h
	}

	addr := conf.Host + ":" + conf.Port
	server := tigertonic.NewServer(addr, handler)

	go listener(server)
	return server
}

func listener(server *tigertonic.Server) {
	if err := server.ListenAndServe(); nil != err {
		panic(err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package engine

import (
	"vitess.io/vitess/go/sqltypes"
	querypb "vitess.io/vitess/go/vt/proto/query"
	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"
)

var _ Primitive = (*RenameFields)(nil)

// RenameFields is a primitive that renames the fields
type RenameFields struct {
	Cols    []string
	Indices []int
	Input   Primitive
	noTxNeeded
}

// NewRenameField creates a new rename field
func NewRenameField(cols []string, indices []int, input Primitive) (*RenameFields, error) {
	if len(cols) != len(indices) {
		return nil, vterrors.New(vtrpc.Code_INTERNAL, "Unequal length of columns and indices in RenameField primitive")
	}
	return &RenameFields{
		Cols:    cols,
		Indices: indices,
		Input:   input,
	}, nil
}

// RouteType implements the primitive interface
func (r *RenameFields) RouteType() string {
	return r.Input.RouteType()
}

// GetKeyspaceName implements the primitive interface
func (r *RenameFields) GetKeyspaceName() string {
	return r.Input.GetKeyspaceName()
}

// GetTableName implements the primitive interface
func (r *RenameFields) GetTableName() string {
	return r.Input.GetTableName()
}

// Execute implements the primitive interface
func (r *RenameFields) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) {
	qr, err := r.Input.Execute(vcursor, bindVars, wantfields)
	if err != nil {
		return nil, err
	}
	if wantfields {
		r.renameFields(qr)
	}
	return qr, nil
}

func (r *RenameFields) renameFields(qr *sqltypes.Result) {
	for i := 0; i < len(r.Indices) && i < len(qr.Fields); i++ {
		colName := r.Cols[r.Indices[i]]
		qr.Fields[i].Name = colName
	}
}

// StreamExecute implements the primitive interface
func (r *RenameFields) StreamExecute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error {
	if wantfields {
		innerCallback := callback
		callback = func(result *sqltypes.Result) error {
			r.renameFields(result)
			return innerCallback(result)
		}
	}
	return r.Input.StreamExecute(vcursor, bindVars, wantfields, callback)
}

// GetFields implements the primitive interface
func (r *RenameFields) GetFields(vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) {
	qr, err := r.Input.GetFields(vcursor, bindVars)
	if err != nil {
		return nil, err
	}
	r.renameFields(qr)
	return qr, nil
}

// Inputs implements the primitive interface
func (r *RenameFields) Inputs() []Primitive {
	return []Primitive{r.Input}
}

// description implements the primitive interface
func (r *RenameFields) description() PrimitiveDescription {
	return PrimitiveDescription{
		OperatorType: "RenameFields",
		Other: map[string]interface{}{
			"Indices": r.Indices,
			"Columns": r.Cols,
		},
	}
}
<commit_msg>Fixing renameFields for loop logic<commit_after>/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package engine

import (
	"vitess.io/vitess/go/sqltypes"
	querypb "vitess.io/vitess/go/vt/proto/query"
	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"
)

var _ Primitive = (*RenameFields)(nil)

// RenameFields is a primitive that renames the fields
type RenameFields struct {
	Cols    []string
	Indices []int
	Input   Primitive
	noTxNeeded
}

// NewRenameField creates a new rename field
func NewRenameField(cols []string, indices []int, input Primitive) (*RenameFields, error) {
	if len(cols) != len(indices) {
		return nil, vterrors.New(vtrpc.Code_INTERNAL, "Unequal length of columns and indices in RenameField primitive")
	}
	return &RenameFields{
		Cols:    cols,
		Indices: indices,
		Input:   input,
	}, nil
}

// RouteType implements the primitive interface
func (r *RenameFields) RouteType() string {
	return r.Input.RouteType()
}

// GetKeyspaceName implements the primitive interface
func (r *RenameFields) GetKeyspaceName() string {
	return r.Input.GetKeyspaceName()
}

// GetTableName implements the primitive interface
func (r *RenameFields) GetTableName() string {
	return r.Input.GetTableName()
}

// Execute implements the primitive interface
func (r *RenameFields) Execute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) {
	qr, err := r.Input.Execute(vcursor, bindVars, wantfields)
	if err != nil {
		return nil, err
	}
	if wantfields {
		r.renameFields(qr)
	}
	return qr, nil
}

func (r *RenameFields) renameFields(qr *sqltypes.Result) {
	for ind, index := range r.Indices {
		if ind == len(qr.Fields) {
			break
		}
		colName := r.Cols[ind]
		qr.Fields[index].Name = colName
	}
}

// StreamExecute implements the primitive interface
func (r *RenameFields) StreamExecute(vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error {
	if wantfields {
		innerCallback := callback
		callback = func(result *sqltypes.Result) error {
			r.renameFields(result)
			return innerCallback(result)
		}
	}
	return r.Input.StreamExecute(vcursor, bindVars, wantfields, callback)
}

// GetFields implements the primitive interface
func (r *RenameFields) GetFields(vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) {
	qr, err := r.Input.GetFields(vcursor, bindVars)
	if err != nil {
		return nil, err
	}
	r.renameFields(qr)
	return qr, nil
}

// Inputs implements the primitive interface
func (r *RenameFields) Inputs() []Primitive {
	return []Primitive{r.Input}
}

// description implements the primitive interface
func (r *RenameFields) description() PrimitiveDescription {
	return PrimitiveDescription{
		OperatorType: "RenameFields",
		Other: map[string]interface{}{
			"Indices": r.Indices,
			"Columns": r.Cols,
		},
	}
}
<|endoftext|>