<commit_before>// Copyright 2022 Google LLC
//
// 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 multiple_buckets

import (
	"fmt"
	"testing"

	"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud"
	"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft"
	"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils"
	"github.com/stretchr/testify/assert"
)

func TestSimpleExample(t *testing.T) {
	example := tft.NewTFBlueprintTest(t)

	sqlname := example.GetStringOutput("sqlservername")
	projectID := example.GetTFSetupStringOutput("project_id")
	projectNumber := example.GetTFSetupStringOutput("project_number")
	prefix := "three-tier-app"
	region := "us-central1"

	example.DefineVerify(func(assert *assert.Assertions) {
		example.DefaultVerify(assert)

		labelTests := map[string]struct {
			subsection string
			name       string
			global     bool
			region     bool
			query      string
		}{
			"Label: Secret SQLHost":   {subsection: "secrets", global: false, region: false, name: "sqlhost", query: "labels.three-tier-app"},
			"Label: Secret RedisHost": {subsection: "secrets", global: false, region: false, name: "redishost", query: "labels.three-tier-app"},
			"Label: Secret todo_user": {subsection: "secrets", global: false, region: false, name: "todo_user", query: "labels.three-tier-app"},
			"Label: Secret todo_pass": {subsection: "secrets", global: false, region: false, name: "todo_pass", query: "labels.three-tier-app"},
			"Label: Service api":      {subsection: "run services", global: false, region: true, name: "three-tier-app-api", query: "metadata.labels.three-tier-app"},
			"Label: Service fe":       {subsection: "run services", global: false, region: true, name: "three-tier-app-fe", query: "metadata.labels.three-tier-app"},
			"Label: SQL":              {subsection: "sql instances", global: false, region: false, name: sqlname, query: "settings.userLabels.three-tier-app"},
			"Label: Redis":            {subsection: "redis instances", global: false, region: true, name: "three-tier-app-cache", query: "labels.three-tier-app"},
		}

		for name, tc := range labelTests {
			t.Run(name, func(t *testing.T) {
				gcloudOps := gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json"})
				if tc.region {
					gcloudOps = gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json", "--region", region})
				}

				cmdstr := fmt.Sprintf("%s describe %s", tc.subsection, tc.name)
				template := gcloud.Run(t, cmdstr, gcloudOps).Array()

				match := template[0].Get(tc.query).String()
				assert.Equal("true", match, fmt.Sprintf("expected label (three-tier-app) in subsection %s to be present", tc.subsection))
			})
		}

		existenceTests := map[string]struct {
			subsection string
			field      string
			global     bool
			region     bool
			expected   string
		}{
			"Existence: Secret SQLHost":   {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/sqlhost", projectNumber)},
			"Existence: Secret RedisHost": {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/redishost", projectNumber)},
			"Existence: Secret todo_user": {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/todo_user", projectNumber)},
			"Existence: Secret todo_pass": {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/todo_pass", projectNumber)},
			"Existence: Service todo-fe":  {subsection: "run services", field: "metadata.name", global: false, region: true, expected: fmt.Sprintf("%s-fe", prefix)},
			"Existence: Service todo-api": {subsection: "run services", field: "metadata.name", global: false, region: true, expected: fmt.Sprintf("%s-api", prefix)},
			"Existence: Redis":            {subsection: "redis instances", field: "name", global: false, region: true, expected: fmt.Sprintf("projects/%s/locations/%s/instances/%s-cache", projectID, region, prefix)},
			"Existence: SQL":              {subsection: "sql instances", field: "name", global: false, region: false, expected: sqlname},
			"Existence: VPN Connector":    {subsection: "compute networks vpc-access connectors", field: "name", global: false, region: true, expected: fmt.Sprintf("projects/%s/locations/%s/connectors/%s-vpc-cx", projectID, region, prefix)},
			"Existence: VPN Address":      {subsection: "compute addresses", field: "name", global: true, region: false, expected: fmt.Sprintf("%s-vpc-address", prefix)},
		}

		for name, tc := range existenceTests {
			t.Run(name, func(t *testing.T) {
				gcloudOps := gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json"})
				if tc.global {
					gcloudOps = gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json", "--global"})
				}
				if tc.region {
					gcloudOps = gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json", "--region", region})
				}

				cmdstr := fmt.Sprintf("%s describe %s", tc.subsection, tc.expected)
				template := gcloud.Run(t, cmdstr, gcloudOps).Array()

				got := utils.GetFirstMatchResult(t, template, tc.field, tc.expected).Get(tc.field).String()
				assert.Equal(tc.expected, got, fmt.Sprintf("expected %s got %s", tc.expected, got))
			})
		}

		serviceTests := map[string]struct {
			service string
		}{
			"Service compute":           {service: "compute"},
			"Service cloudapis":         {service: "cloudapis"},
			"Service vpcaccess":         {service: "vpcaccess"},
			"Service servicenetworking": {service: "servicenetworking"},
			"Service cloudbuild":        {service: "cloudbuild"},
			"Service sql-component":     {service: "sql-component"},
			"Service sqladmin":          {service: "sqladmin"},
			"Service storage":           {service: "storage"},
			"Service secretmanager":     {service: "secretmanager"},
			"Service run":               {service: "run"},
			"Service redis":             {service: "redis"},
		}

		services := gcloud.Run(t, "services list", gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json"})).Array()

		for name, tc := range serviceTests {
			t.Run(name, func(t *testing.T) {
				match := utils.GetFirstMatchResult(t, services, "config.name", fmt.Sprintf("%s.googleapis.com", tc.service))
				assert.Equal("ENABLED", match.Get("state").String(), "%s service should be enabled", tc.service)
			})
		}
	})
	example.Test()
}
<commit_msg>chore: getting tests to finally work.<commit_after>// Copyright 2022 Google LLC
//
// 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 multiple_buckets

import (
	"fmt"
	"testing"

	"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud"
	"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft"
	"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils"
	"github.com/stretchr/testify/assert"
)

func TestSimpleExample(t *testing.T) {
	example := tft.NewTFBlueprintTest(t)

	example.DefineVerify(func(assert *assert.Assertions) {
		example.DefaultVerify(assert)
		sqlname := example.GetStringOutput("sqlservername")
		projectID := example.GetTFSetupStringOutput("project_id")
		projectNumber := example.GetTFSetupStringOutput("project_number")
		prefix := "three-tier-app"
		region := "us-central1"

		labelTests := map[string]struct {
			subsection string
			name       string
			global     bool
			region     bool
			query      string
		}{
			"Label: Secret SQLHost":   {subsection: "secrets", global: false, region: false, name: "sqlhost", query: "labels.three-tier-app"},
			"Label: Secret RedisHost": {subsection: "secrets", global: false, region: false, name: "redishost", query: "labels.three-tier-app"},
			"Label: Secret todo_user": {subsection: "secrets", global: false, region: false, name: "todo_user", query: "labels.three-tier-app"},
			"Label: Secret todo_pass": {subsection: "secrets", global: false, region: false, name: "todo_pass", query: "labels.three-tier-app"},
			"Label: Service api":      {subsection: "run services", global: false, region: true, name: "three-tier-app-api", query: "metadata.labels.three-tier-app"},
			"Label: Service fe":       {subsection: "run services", global: false, region: true, name: "three-tier-app-fe", query: "metadata.labels.three-tier-app"},
			"Label: SQL":              {subsection: "sql instances", global: false, region: false, name: sqlname, query: "settings.userLabels.three-tier-app"},
			"Label: Redis":            {subsection: "redis instances", global: false, region: true, name: "three-tier-app-cache", query: "labels.three-tier-app"},
		}

		for name, tc := range labelTests {
			t.Run(name, func(t *testing.T) {
				gcloudOps := gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json"})
				if tc.region {
					gcloudOps = gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json", "--region", region})
				}

				cmdstr := fmt.Sprintf("%s describe %s", tc.subsection, tc.name)
				template := gcloud.Run(t, cmdstr, gcloudOps).Array()

				match := template[0].Get(tc.query).String()
				assert.Equal("true", match, fmt.Sprintf("expected label (three-tier-app) in subsection %s to be present", tc.subsection))
			})
		}

		existenceTests := map[string]struct {
			subsection string
			field      string
			global     bool
			region     bool
			expected   string
		}{
			"Existence: Secret SQLHost":   {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/sqlhost", projectNumber)},
			"Existence: Secret RedisHost": {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/redishost", projectNumber)},
			"Existence: Secret todo_user": {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/todo_user", projectNumber)},
			"Existence: Secret todo_pass": {subsection: "secrets", field: "name", global: false, region: false, expected: fmt.Sprintf("projects/%s/secrets/todo_pass", projectNumber)},
			"Existence: Service todo-fe":  {subsection: "run services", field: "metadata.name", global: false, region: true, expected: fmt.Sprintf("%s-fe", prefix)},
			"Existence: Service todo-api": {subsection: "run services", field: "metadata.name", global: false, region: true, expected: fmt.Sprintf("%s-api", prefix)},
			"Existence: Redis":            {subsection: "redis instances", field: "name", global: false, region: true, expected: fmt.Sprintf("projects/%s/locations/%s/instances/%s-cache", projectID, region, prefix)},
			"Existence: SQL":              {subsection: "sql instances", field: "name", global: false, region: false, expected: sqlname},
			"Existence: VPN Connector":    {subsection: "compute networks vpc-access connectors", field: "name", global: false, region: true, expected: fmt.Sprintf("projects/%s/locations/%s/connectors/%s-vpc-cx", projectID, region, prefix)},
			"Existence: VPN Address":      {subsection: "compute addresses", field: "name", global: true, region: false, expected: fmt.Sprintf("%s-vpc-address", prefix)},
		}

		for name, tc := range existenceTests {
			t.Run(name, func(t *testing.T) {
				gcloudOps := gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json"})
				if tc.global {
					gcloudOps = gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json", "--global"})
				}
				if tc.region {
					gcloudOps = gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json", "--region", region})
				}

				cmdstr := fmt.Sprintf("%s describe %s", tc.subsection, tc.expected)
				template := gcloud.Run(t, cmdstr, gcloudOps).Array()

				got := utils.GetFirstMatchResult(t, template, tc.field, tc.expected).Get(tc.field).String()
				assert.Equal(tc.expected, got, fmt.Sprintf("expected %s got %s", tc.expected, got))
			})
		}

		serviceTests := map[string]struct {
			service string
		}{
			"Service compute":           {service: "compute"},
			"Service cloudapis":         {service: "cloudapis"},
			"Service vpcaccess":         {service: "vpcaccess"},
			"Service servicenetworking": {service: "servicenetworking"},
			"Service cloudbuild":        {service: "cloudbuild"},
			"Service sql-component":     {service: "sql-component"},
			"Service sqladmin":          {service: "sqladmin"},
			"Service storage":           {service: "storage"},
			"Service secretmanager":     {service: "secretmanager"},
			"Service run":               {service: "run"},
			"Service redis":             {service: "redis"},
		}

		services := gcloud.Run(t, "services list", gcloud.WithCommonArgs([]string{"--project", projectID, "--format", "json"})).Array()

		for name, tc := range serviceTests {
			t.Run(name, func(t *testing.T) {
				match := utils.GetFirstMatchResult(t, services, "config.name", fmt.Sprintf("%s.googleapis.com", tc.service))
				assert.Equal("ENABLED", match.Get("state").String(), "%s service should be enabled", tc.service)
			})
		}
	})
	example.Test()
}
<|endoftext|>


<commit_before>package mp

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"crypto/subtle"
	"encoding/base64"
	"encoding/hex"
	"encoding/xml"
	"github.com/ridewindx/mel"
	"github.com/ridewindx/mel/binding"
	"sort"
	"sync"
	"sync/atomic"
	"unsafe"
	"go.uber.org/zap"
	"github.com/jiudaoyun/wechat"
	"net/http"
	"fmt"
	"encoding/json"
	"strings"
	"github.com/ridewindx/melware"
)

type Server struct {
	*mel.Mel
	urlPrefix string

	appID string // App ID
	ID    string // Wechat ID

	tokenMutex sync.Mutex
	token      unsafe.Pointer

	aesKeyMutex sync.Mutex
	aesKey      unsafe.Pointer

	client            *Client
	middlewares       []Handler
	messageHandlerMap map[string]Handler
	eventHandlerMap   map[string]Handler

	logger *zap.SugaredLogger
}

func (srv *Server) setURLPrefix(urlPrefix string) {
	if !strings.HasPrefix(urlPrefix, "/") {
		urlPrefix = "/" + urlPrefix
	}
	urlPrefix = strings.TrimRight(urlPrefix, "/")
	srv.urlPrefix = urlPrefix
}

func (srv *Server) SetID(id string) {
	srv.ID = id
}

func (srv *Server) SetAppID(appID string) {
	srv.appID = appID
}

func (srv *Server) SetClient(client *Client) {
	srv.client = client
}

type Token struct {
	current string
	last    string
}

type AESKey struct {
	current string
	last    string
}

func (srv *Server) GetToken() (string, string) {
	p := (*Token)(atomic.LoadPointer(&srv.token))
	if p != nil {
		return p.current, p.last
	}
	return "", ""
}

func (srv *Server) SetToken(token string) {
	if token == "" {
		return
	}

	srv.tokenMutex.Lock()
	defer srv.tokenMutex.Unlock()

	current, _ := srv.GetToken()
	if token == current {
		return
	}

	t := Token{
		current: token,
		last:    current,
	}
	atomic.StorePointer(&srv.token, unsafe.Pointer(&t))
}

func (srv *Server) deleteLastToken() {
	srv.tokenMutex.Lock()
	defer srv.tokenMutex.Unlock()

	current, last := srv.GetToken()
	if last == "" {
		return
	}

	t := Token{
		current: current,
	}
	atomic.StorePointer(&srv.token, unsafe.Pointer(&t))
}

func (srv *Server) GetAESKey() (string, string) {
	p := (*AESKey)(atomic.LoadPointer(&srv.aesKey))
	if p != nil {
		return p.current, p.last
	}
	return "", ""
}

func (srv *Server) SetAESKey(base64AESKey string) {
	if len(base64AESKey) != 43 {
		return
	}
	aesKey, err := base64.StdEncoding.DecodeString(base64AESKey + "=")
	if err != nil {
		return
	}

	srv.aesKeyMutex.Lock()
	defer srv.aesKeyMutex.Unlock()

	current, _ := srv.GetAESKey()
	if bytes.Equal(aesKey, []byte(current)) {
		return
	}

	k := AESKey{
		current: string(aesKey),
		last:    current,
	}
	atomic.StorePointer(&srv.aesKey, unsafe.Pointer(&k))
}

func (srv *Server) deleteLastAESKey() {
	srv.aesKeyMutex.Lock()
	defer srv.aesKeyMutex.Unlock()

	current, last := srv.GetAESKey()
	if last == "" {
		return
	}

	k := AESKey{
		current: current,
	}
	atomic.StorePointer(&srv.aesKey, unsafe.Pointer(&k))
}

func (srv *Server) Use(middlewares ...Handler) {
	srv.middlewares = append(srv.middlewares, middlewares...)
	if len(srv.middlewares)+1 > int(abortIndex) {
		panic("too many middlewares")
	}
}

func (srv *Server) HandleMessage(msgType string, handler Handler) {
	srv.messageHandlerMap[msgType] = handler
}

func (srv *Server) HandleEvent(eventType string, handler Handler) {
	srv.eventHandlerMap[eventType] = handler
}

func (srv *Server) GetVerifyFile(filename string, content []byte) {
	srv.Get(srv.urlPrefix+"/"+filename, func(c *mel.Context) {
		c.Data(200, "text/plain", content)
	})
}

func NewServer(token, aesKey string, urlPrefix ...string) *Server {
	srv := &Server{
		Mel:               mel.New(),
		messageHandlerMap: make(map[string]Handler),
		eventHandlerMap:   make(map[string]Handler),
		logger:            wechat.Sugar,
	}

	srv.SetToken(token)
	srv.SetAESKey(aesKey)

	srv.Mel.Use(melware.Zap(srv.logger))

	cors := melware.CorsAllowAll()
	cors.AllowCredentials = false
	srv.Mel.Use(cors.Middleware())

	if len(urlPrefix) > 0 {
		srv.setURLPrefix(urlPrefix[0])
	}

	equal := func(a, b string) bool {
		return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
	}

	verifySignReturnToken := func(signature, timestamp, nonce string) string {
		currentToken, lastToken := srv.GetToken()
		token := currentToken

		isValid := func() bool {
			computedSignature := computeSign(token, timestamp, nonce)
			return equal(signature, computedSignature)
		}

		if isValid() {
			srv.deleteLastToken()
			return token
		}

		if lastToken != "" {
			token = lastToken
			if isValid() {
				return token
			}
		}

		return ""
	}

	verifySign := func(c *mel.Context) bool {
		signature := c.Query("signature")
		timestamp := c.Query("timestamp")
		nonce := c.Query("nonce")

		return verifySignReturnToken(signature, timestamp, nonce) != ""
	}

	type EncryptMsg struct {
		ToUserName string `xml:"ToUserName"`
		Encrypt    string `xml:"Encrypt"`
	}

	srv.Head("/", func(c *mel.Context) { // health check
		c.Status(200)
	})

	srv.Get(srv.urlPrefix+"/", func(c *mel.Context) {
		if verifySign(c) {
			echostr := c.Query("echostr")
			c.Text(200, echostr)
		}
	})

	handleMessage := func(event *Event) interface{} {
		var handler Handler
		var ok bool
		if event.Type == MessageEvent {
			handler, ok = srv.eventHandlerMap[event.Event]
		} else {
			handler, ok = srv.messageHandlerMap[event.Type]
		}
		if !ok {
			return nil // no registered handler, just respond with empty string
		}

		ctx := &Context{
			Client:   srv.client,
			index:    preStartIndex,
			handlers: append(srv.middlewares, handler),
			Event:    event,
		}

		ctx.Next()

		return ctx.response
	}

	srv.Post(srv.urlPrefix+"/", func(c *mel.Context) {
		encryptType := c.Query("encrypt_type")
		signature := c.Query("signature")
		timestamp := c.Query("timestamp")
		nonce := c.Query("nonce")

		switch encryptType {
		case "aes":
			token := verifySignReturnToken(signature, timestamp, nonce)
			if token == "" {
				srv.logger.Error("Verify sign empty token")
				return
			}

			msgSign := c.Query("msg_signature")

			var obj EncryptMsg
			err := c.BindWith(&obj, binding.XML)
			if err != nil {
				srv.logger.Errorw("Bind with XML failed", "error", err)
				return
			}

			if srv.ID != "" && !equal(obj.ToUserName, srv.ID) {
				srv.logger.Errorw("Wechat ID inconsistent", "id", srv.ID, "ToUserName", obj.ToUserName)
				return
			}

			computedSign := computeSign(token, timestamp, nonce, obj.Encrypt)
			if !equal(computedSign, msgSign) {
				srv.logger.Errorw("Signature inconsistent")
				return
			}

			encryptedMsg, err := base64.StdEncoding.DecodeString(obj.Encrypt)
			if err != nil {
				srv.logger.Errorw("Decode base64 string failed", "error", err)
				return
			}

			current, last := srv.GetAESKey()
			aesKey := current
			random, msg, appId, err := decryptMsg(encryptedMsg, []byte(aesKey))
			if err != nil {
				if last == "" {
					srv.logger.Errorw("Decrypt AES msg failed", "error", err)
					return
				}
				aesKey = last
				random, msg, appId, err = decryptMsg(encryptedMsg, []byte(aesKey))
				if err != nil {
					srv.logger.Errorw("Decrypt AES msg failed", "error", err)
					return
				}
			} else {
				srv.deleteLastAESKey()
			}
			if srv.appID != "" && string(appId) != srv.appID {
				srv.logger.Errorw("AppID inconsistent", "AppID", appId)
				return
			}

			var event Event
			if err = xml.Unmarshal(msg, &event); err != nil {
				srv.logger.Errorw("Unmarshal msg failed", "error", err)
				return
			}

			repBytes, err := xml.Marshal(handleMessage(&event))
			if err != nil {
				srv.logger.Errorw("Marshal msg failed", "error", err)
				return
			}

			encryptedRepBytes := encryptMsg(random, repBytes, appId, []byte(aesKey))
			encryptedRepStr := base64.StdEncoding.EncodeToString(encryptedRepBytes)
			repSignature := computeSign(token, timestamp, nonce, encryptedRepStr)

			type EncryptRepMsg struct {
				Encrypt      string
				MsgSignature string
				TimeStamp    string
				Nonce        string
			}

			err = c.XML(200, &EncryptRepMsg{encryptedRepStr, repSignature, timestamp, nonce})
			if err != nil {
				srv.logger.Errorw("Reply msg failed", "error", err)
			}

		case "", "raw":
			if !verifySign(c) {
				return
			}

			var event Event
			err := c.BindWith(&event, binding.XML)
			if err != nil {
				return
			}

			c.XML(200, handleMessage(&event))

		default:
			return
		}
	})

	handleAuthorize := func(c *mel.Context, url string, state string) {
		srv.logger.Infof("authorize", "url", url)
		rep, err := srv.client.Client.Get(url)
		if err != nil {
			c.AbortWithError(http.StatusUnauthorized, err)
			return
		}
		defer rep.Body.Close()

		if rep.StatusCode != http.StatusOK {
			c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("http.Status: %s", rep.Status))
			return
		}

		type Result struct {
			AccessToken  string `json:"access_token"`
			ExpiresIn    string `json:"expires_in"`
			RefreshToken string `json:"refresh_token"`
			OpenID       string `json:"openid"`
			Scope        string `json:"scope"`
			State        string `json:"state,omitempty"`
		}

		type ResultWithErr struct {
			Result
			Err
		}

		var result ResultWithErr
		err = json.NewDecoder(rep.Body).Decode(&result)
		if err != nil {
			c.AbortWithError(http.StatusUnauthorized, err)
			return
		}

		if result.Code() != OK {
			c.AbortWithError(http.StatusUnauthorized, &result)
			return
		}

		result.State = state
		c.JSON(http.StatusOK, &result.Result)
		srv.logger.Infof("/token", "result", result.Result)
	}

	srv.Get(srv.urlPrefix+"/token", func(c *mel.Context) {
		code := c.Query("code")
		state := c.Query("state")

		url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", srv.client.appId, srv.client.appSecret, code)

		handleAuthorize(c, url, state)
	})

	srv.Get(srv.urlPrefix+"/refresh-token", func(c *mel.Context) {
		refreshToken := c.Query("refresh_token")

		url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s", srv.client.appId, refreshToken)

		handleAuthorize(c, url, "")
	})

	srv.Get(srv.urlPrefix+"/signature", func(c *mel.Context) {
		timestamp := c.Query("timestamp")
		noncestr := c.Query("noncestr")
		url := c.Query("url")
		refresh := c.Query("refresh")

		var ticket string
		var err error
		if refresh != "" && (refresh == "true" || refresh == "True" || refresh == "1") {
			ticket, err = srv.client.RefreshTicket("")
		} else {
			ticket, err = srv.client.Ticket()
		}
		if err != nil {
			c.AbortWithError(http.StatusInternalServerError, err)
			return
		}

		strs := sort.StringSlice{
			"timestamp=" + timestamp,
			"noncestr=" + noncestr,
			"url=" + url,
			"jsapi_ticket=" + ticket,
		}
		strs.Sort()
		h := sha1.New()
		buf := bufio.NewWriterSize(h, 1024)
		for i, s := range strs {
			buf.WriteString(s)
			if i < len(strs)-1 {
				buf.WriteByte('&')
			}
		}
		buf.Flush()
		sign := hex.EncodeToString(h.Sum(nil))
		c.JSON(http.StatusOK, map[string]string{
			"signature": sign,
		})
		srv.logger.Infow("signature", "strs", strs, "sign", sign)
	})

	return srv
}

func computeSign(elements ...string) string {
	strs := sort.StringSlice(elements)
	strs.Sort()

	h := sha1.New()

	buf := bufio.NewWriterSize(h, 1024)
	for _, s := range strs {
		buf.WriteString(s)
	}
	buf.Flush()

	return hex.EncodeToString(h.Sum(nil))
}
<commit_msg>Update files<commit_after>package mp

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"crypto/subtle"
	"encoding/base64"
	"encoding/hex"
	"encoding/xml"
	"github.com/ridewindx/mel"
	"github.com/ridewindx/mel/binding"
	"sort"
	"sync"
	"sync/atomic"
	"unsafe"
	"go.uber.org/zap"
	"github.com/jiudaoyun/wechat"
	"net/http"
	"fmt"
	"encoding/json"
	"strings"
	"github.com/ridewindx/melware"
)

type Server struct {
	*mel.Mel
	urlPrefix string

	appID string // App ID
	ID    string // Wechat ID

	tokenMutex sync.Mutex
	token      unsafe.Pointer

	aesKeyMutex sync.Mutex
	aesKey      unsafe.Pointer

	client            *Client
	middlewares       []Handler
	messageHandlerMap map[string]Handler
	eventHandlerMap   map[string]Handler

	logger *zap.SugaredLogger
}

func (srv *Server) setURLPrefix(urlPrefix string) {
	if !strings.HasPrefix(urlPrefix, "/") {
		urlPrefix = "/" + urlPrefix
	}
	urlPrefix = strings.TrimRight(urlPrefix, "/")
	srv.urlPrefix = urlPrefix
}

func (srv *Server) SetID(id string) {
	srv.ID = id
}

func (srv *Server) SetAppID(appID string) {
	srv.appID = appID
}

func (srv *Server) SetClient(client *Client) {
	srv.client = client
}

type Token struct {
	current string
	last    string
}

type AESKey struct {
	current string
	last    string
}

func (srv *Server) GetToken() (string, string) {
	p := (*Token)(atomic.LoadPointer(&srv.token))
	if p != nil {
		return p.current, p.last
	}
	return "", ""
}

func (srv *Server) SetToken(token string) {
	if token == "" {
		return
	}

	srv.tokenMutex.Lock()
	defer srv.tokenMutex.Unlock()

	current, _ := srv.GetToken()
	if token == current {
		return
	}

	t := Token{
		current: token,
		last:    current,
	}
	atomic.StorePointer(&srv.token, unsafe.Pointer(&t))
}

func (srv *Server) deleteLastToken() {
	srv.tokenMutex.Lock()
	defer srv.tokenMutex.Unlock()

	current, last := srv.GetToken()
	if last == "" {
		return
	}

	t := Token{
		current: current,
	}
	atomic.StorePointer(&srv.token, unsafe.Pointer(&t))
}

func (srv *Server) GetAESKey() (string, string) {
	p := (*AESKey)(atomic.LoadPointer(&srv.aesKey))
	if p != nil {
		return p.current, p.last
	}
	return "", ""
}

func (srv *Server) SetAESKey(base64AESKey string) {
	if len(base64AESKey) != 43 {
		return
	}
	aesKey, err := base64.StdEncoding.DecodeString(base64AESKey + "=")
	if err != nil {
		return
	}

	srv.aesKeyMutex.Lock()
	defer srv.aesKeyMutex.Unlock()

	current, _ := srv.GetAESKey()
	if bytes.Equal(aesKey, []byte(current)) {
		return
	}

	k := AESKey{
		current: string(aesKey),
		last:    current,
	}
	atomic.StorePointer(&srv.aesKey, unsafe.Pointer(&k))
}

func (srv *Server) deleteLastAESKey() {
	srv.aesKeyMutex.Lock()
	defer srv.aesKeyMutex.Unlock()

	current, last := srv.GetAESKey()
	if last == "" {
		return
	}

	k := AESKey{
		current: current,
	}
	atomic.StorePointer(&srv.aesKey, unsafe.Pointer(&k))
}

func (srv *Server) Use(middlewares ...Handler) {
	srv.middlewares = append(srv.middlewares, middlewares...)
	if len(srv.middlewares)+1 > int(abortIndex) {
		panic("too many middlewares")
	}
}

func (srv *Server) HandleMessage(msgType string, handler Handler) {
	srv.messageHandlerMap[msgType] = handler
}

func (srv *Server) HandleEvent(eventType string, handler Handler) {
	srv.eventHandlerMap[eventType] = handler
}

func (srv *Server) GetVerifyFile(filename string, content []byte) {
	srv.Get(srv.urlPrefix+"/"+filename, func(c *mel.Context) {
		c.Data(200, "text/plain", content)
	})
}

func NewServer(token, aesKey string, urlPrefix ...string) *Server {
	srv := &Server{
		Mel:               mel.New(),
		messageHandlerMap: make(map[string]Handler),
		eventHandlerMap:   make(map[string]Handler),
		logger:            wechat.Sugar,
	}

	srv.SetToken(token)
	srv.SetAESKey(aesKey)

	srv.Mel.Use(melware.Zap(srv.logger))

	cors := melware.CorsAllowAll()
	cors.AllowCredentials = false
	srv.Mel.Use(cors.Middleware())

	if len(urlPrefix) > 0 {
		srv.setURLPrefix(urlPrefix[0])
	}

	equal := func(a, b string) bool {
		return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
	}

	verifySignReturnToken := func(signature, timestamp, nonce string) string {
		currentToken, lastToken := srv.GetToken()
		token := currentToken

		isValid := func() bool {
			computedSignature := computeSign(token, timestamp, nonce)
			return equal(signature, computedSignature)
		}

		if isValid() {
			srv.deleteLastToken()
			return token
		}

		if lastToken != "" {
			token = lastToken
			if isValid() {
				return token
			}
		}

		return ""
	}

	verifySign := func(c *mel.Context) bool {
		signature := c.Query("signature")
		timestamp := c.Query("timestamp")
		nonce := c.Query("nonce")

		return verifySignReturnToken(signature, timestamp, nonce) != ""
	}

	type EncryptMsg struct {
		ToUserName string `xml:"ToUserName"`
		Encrypt    string `xml:"Encrypt"`
	}

	srv.Head("/", func(c *mel.Context) { // health check
		c.Status(200)
	})

	srv.Get(srv.urlPrefix+"/", func(c *mel.Context) {
		if verifySign(c) {
			echostr := c.Query("echostr")
			c.Text(200, echostr)
		}
	})

	handleMessage := func(event *Event) interface{} {
		var handler Handler
		var ok bool
		if event.Type == MessageEvent {
			handler, ok = srv.eventHandlerMap[event.Event]
		} else {
			handler, ok = srv.messageHandlerMap[event.Type]
		}
		if !ok {
			return nil // no registered handler, just respond with empty string
		}

		ctx := &Context{
			Client:   srv.client,
			index:    preStartIndex,
			handlers: append(srv.middlewares, handler),
			Event:    event,
		}

		ctx.Next()

		return ctx.response
	}

	srv.Post(srv.urlPrefix+"/", func(c *mel.Context) {
		encryptType := c.Query("encrypt_type")
		signature := c.Query("signature")
		timestamp := c.Query("timestamp")
		nonce := c.Query("nonce")

		switch encryptType {
		case "aes":
			token := verifySignReturnToken(signature, timestamp, nonce)
			if token == "" {
				srv.logger.Error("Verify sign empty token")
				return
			}

			msgSign := c.Query("msg_signature")

			var obj EncryptMsg
			err := c.BindWith(&obj, binding.XML)
			if err != nil {
				srv.logger.Errorw("Bind with XML failed", "error", err)
				return
			}

			if srv.ID != "" && !equal(obj.ToUserName, srv.ID) {
				srv.logger.Errorw("Wechat ID inconsistent", "id", srv.ID, "ToUserName", obj.ToUserName)
				return
			}

			computedSign := computeSign(token, timestamp, nonce, obj.Encrypt)
			if !equal(computedSign, msgSign) {
				srv.logger.Errorw("Signature inconsistent")
				return
			}

			encryptedMsg, err := base64.StdEncoding.DecodeString(obj.Encrypt)
			if err != nil {
				srv.logger.Errorw("Decode base64 string failed", "error", err)
				return
			}

			current, last := srv.GetAESKey()
			aesKey := current
			random, msg, appId, err := decryptMsg(encryptedMsg, []byte(aesKey))
			if err != nil {
				if last == "" {
					srv.logger.Errorw("Decrypt AES msg failed", "error", err)
					return
				}
				aesKey = last
				random, msg, appId, err = decryptMsg(encryptedMsg, []byte(aesKey))
				if err != nil {
					srv.logger.Errorw("Decrypt AES msg failed", "error", err)
					return
				}
			} else {
				srv.deleteLastAESKey()
			}
			if srv.appID != "" && string(appId) != srv.appID {
				srv.logger.Errorw("AppID inconsistent", "AppID", appId)
				return
			}

			var event Event
			if err = xml.Unmarshal(msg, &event); err != nil {
				srv.logger.Errorw("Unmarshal msg failed", "error", err)
				return
			}

			repBytes, err := xml.Marshal(handleMessage(&event))
			if err != nil {
				srv.logger.Errorw("Marshal msg failed", "error", err)
				return
			}

			encryptedRepBytes := encryptMsg(random, repBytes, appId, []byte(aesKey))
			encryptedRepStr := base64.StdEncoding.EncodeToString(encryptedRepBytes)
			repSignature := computeSign(token, timestamp, nonce, encryptedRepStr)

			type EncryptRepMsg struct {
				Encrypt      string
				MsgSignature string
				TimeStamp    string
				Nonce        string
			}

			err = c.XML(200, &EncryptRepMsg{encryptedRepStr, repSignature, timestamp, nonce})
			if err != nil {
				srv.logger.Errorw("Reply msg failed", "error", err)
			}

		case "", "raw":
			if !verifySign(c) {
				return
			}

			var event Event
			err := c.BindWith(&event, binding.XML)
			if err != nil {
				return
			}

			c.XML(200, handleMessage(&event))

		default:
			return
		}
	})

	handleAuthorize := func(c *mel.Context, url string, state string) {
		srv.logger.Infof("authorize", "url", url)
		rep, err := srv.client.Client.Get(url)
		if err != nil {
			c.AbortWithError(http.StatusUnauthorized, err)
			return
		}
		defer rep.Body.Close()

		if rep.StatusCode != http.StatusOK {
			c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("http.Status: %s", rep.Status))
			return
		}

		type Result struct {
			AccessToken  string `json:"access_token"`
			ExpiresIn    string `json:"expires_in"`
			RefreshToken string `json:"refresh_token"`
			OpenID       string `json:"openid"`
			Scope        string `json:"scope"`
			State        string `json:"state,omitempty"`
		}

		type ResultWithErr struct {
			Result
			Err
		}

		var result ResultWithErr
		err = json.NewDecoder(rep.Body).Decode(&result)
		if err != nil {
			c.AbortWithError(http.StatusUnauthorized, err)
			return
		}

		if result.Code() != OK {
			c.AbortWithError(http.StatusUnauthorized, &result)
			return
		}

		result.State = state
		c.JSON(http.StatusOK, &result.Result)
		srv.logger.Infof("/token", "result", result.Result)
	}

	srv.Get(srv.urlPrefix+"/token", func(c *mel.Context) {
		srv.logger.Infof("url: %s", c.Request.URL.RawQuery)
		code := c.Query("code")
		state := c.Query("state")

		url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", srv.client.appId, srv.client.appSecret, code)

		handleAuthorize(c, url, state)
	})

	srv.Get(srv.urlPrefix+"/refresh-token", func(c *mel.Context) {
		refreshToken := c.Query("refresh_token")

		url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s", srv.client.appId, refreshToken)

		handleAuthorize(c, url, "")
	})

	srv.Get(srv.urlPrefix+"/signature", func(c *mel.Context) {
		timestamp := c.Query("timestamp")
		noncestr := c.Query("noncestr")
		url := c.Query("url")
		refresh := c.Query("refresh")

		var ticket string
		var err error
		if refresh != "" && (refresh == "true" || refresh == "True" || refresh == "1") {
			ticket, err = srv.client.RefreshTicket("")
		} else {
			ticket, err = srv.client.Ticket()
		}
		if err != nil {
			c.AbortWithError(http.StatusInternalServerError, err)
			return
		}

		strs := sort.StringSlice{
			"timestamp=" + timestamp,
			"noncestr=" + noncestr,
			"url=" + url,
			"jsapi_ticket=" + ticket,
		}
		strs.Sort()
		h := sha1.New()
		buf := bufio.NewWriterSize(h, 1024)
		for i, s := range strs {
			buf.WriteString(s)
			if i < len(strs)-1 {
				buf.WriteByte('&')
			}
		}
		buf.Flush()
		sign := hex.EncodeToString(h.Sum(nil))
		c.JSON(http.StatusOK, map[string]string{
			"signature": sign,
		})
		srv.logger.Infow("signature", "strs", strs, "sign", sign)
	})

	return srv
}

func computeSign(elements ...string) string {
	strs := sort.StringSlice(elements)
	strs.Sort()

	h := sha1.New()

	buf := bufio.NewWriterSize(h, 1024)
	for _, s := range strs {
		buf.WriteString(s)
	}
	buf.Flush()

	return hex.EncodeToString(h.Sum(nil))
}
<|endoftext|>


<commit_before>package alsa

import (
	"fmt"
)

func (device *Device) NegotiateChannels(channels ...int) (int, error) {
	var err error

	for _, v := range channels {

		if !device.hwparams.IntervalInRange(paramChannels, uint32(v)) {
			err = fmt.Errorf("Channels %d out of range")
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramChannels, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiateRate(rates ...int) (int, error) {
	var err error

	for _, v := range rates {
		if !device.hwparams.IntervalInRange(paramRate, uint32(v)) {
			err = fmt.Errorf("Rate %d out of range")
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramRate, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiateFormat(formats ...FormatType) (FormatType, error) {
	var err error

	for _, v := range formats {
		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetFormat(v)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiateBufferSize(buffer_sizes ...int) (int, error) {
	var err error

	for _, v := range buffer_sizes {
		if !device.hwparams.IntervalInRange(paramBufferSize, uint32(v)) {
			err = fmt.Errorf("Buffer size %d out of range")
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramBufferSize, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiatePeriodSize(period_sizes ...int) (int, error) {
	var err error

	for _, v := range period_sizes {
		if !device.hwparams.IntervalInRange(paramPeriodSize, uint32(v)) {
			err = fmt.Errorf("Period size %d out of range")
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramPeriodSize, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) BytesPerFrame() int {
	sample_size := int(device.hwparams.Intervals[paramSampleBits-paramFirstInterval].Max) / 8
	channels := int(device.hwparams.Intervals[paramChannels-paramFirstInterval].Max)
	return sample_size * channels
}
<commit_msg>Fix some invalid printf calls<commit_after>package alsa

import (
	"fmt"
)

func (device *Device) NegotiateChannels(channels ...int) (int, error) {
	var err error

	for _, v := range channels {

		if !device.hwparams.IntervalInRange(paramChannels, uint32(v)) {
			err = fmt.Errorf("Channels %d out of range", v)
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramChannels, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiateRate(rates ...int) (int, error) {
	var err error

	for _, v := range rates {
		if !device.hwparams.IntervalInRange(paramRate, uint32(v)) {
			err = fmt.Errorf("Rate %d out of range", v)
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramRate, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiateFormat(formats ...FormatType) (FormatType, error) {
	var err error

	for _, v := range formats {
		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetFormat(v)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiateBufferSize(buffer_sizes ...int) (int, error) {
	var err error

	for _, v := range buffer_sizes {
		if !device.hwparams.IntervalInRange(paramBufferSize, uint32(v)) {
			err = fmt.Errorf("Buffer size %d out of range", v)
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramBufferSize, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) NegotiatePeriodSize(period_sizes ...int) (int, error) {
	var err error

	for _, v := range period_sizes {
		if !device.hwparams.IntervalInRange(paramPeriodSize, uint32(v)) {
			err = fmt.Errorf("Period size %d out of range", v)
			continue
		}

		device.hwparams.Cmask = 0
		device.hwparams.Rmask = 0xffffffff
		device.hwparams.SetInterval(paramPeriodSize, uint32(v), uint32(v), Integer)

		err = device.refine()
		if err == nil {
			return v, nil
		}
	}

	return 0, err
}

func (device *Device) BytesPerFrame() int {
	sample_size := int(device.hwparams.Intervals[paramSampleBits-paramFirstInterval].Max) / 8
	channels := int(device.hwparams.Intervals[paramChannels-paramFirstInterval].Max)
	return sample_size * channels
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
)

/*
type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files;
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}
*/

// Echos the $HOME env to find the home directory, returns root if err
func getHomeDir(id int) string {
	// Create a new ssh session to access the remote host's $HOME env variable
	session, err := conns[id].sshClient.NewSession()
	defer session.Close()

	if err != nil {
		fmt.Println("Error creating ssh session:", err)
		return "/"
	}
	output, err := session.Output("echo $HOME")
	if err != nil {
		fmt.Println("Error finding home dir:", err)
		return "/"
	}
	return strings.TrimSpace(string(output))
}

func FileStruct(file os.FileInfo, dir string) File {
	return File{
		Filename: file.Name(),
		Path:     dir + "/" + file.Name(),
		ModTime:  file.ModTime(),
		IsDir:    file.IsDir(),
		Size:     file.Size(),
	}
}

// Print the target directory's file listing
func printDirectory(id int, dirpath string) {
	fmt.Println("Printing contents of", dirpath)
	listing, err := conns[id].sftpClient.ReadDir(dirpath)
	if err != nil {
		log.Fatal(err)
	}

	var files []File
	for _, file := range listing {
		files = append(files, FileStruct(file, dirpath))
	}

	conns[id].putDirectory("./TestingDir", ".")

	jsonMessage, _ := json.Marshal(FileMessage{id, "FETCH_FILES_SUCCESS", files})
	_, _ = socket.Write(jsonMessage)
}

func (c *clients) putDirectory(src, dest string) {
	fmt.Println("Putting directory ", src)

	session, _ := c.sshClient.NewSession()
	session.Run("mkdir " + path.Join(dest, path.Base(src)))
	session.Close()

	files, _ := ioutil.ReadDir(src)
	for _, file := range files {
		if file.IsDir() {
			c.putDirectory(path.Join(src, file.Name()), path.Join(dest, path.Base(src)))
		} else {
			c.putFile(path.Join(src, file.Name()), path.Join(dest, path.Base(src)))
		}
	}
}

func (c *clients) putFile(src, dest string) {
	srcFile, _ := os.Open(src)
	destFile, err := c.sftpClient.Create(path.Join(dest, path.Base(src)))
	if err != nil {
		fmt.Println(err)
		return
	}

	info, _ := srcFile.Stat()
	contents := make([]byte, info.Size())
	srcFile.Read(contents)

	_, err = destFile.Write(contents)
	if err != nil {
		fmt.Println("Problem writing file : ", err)
	}
}

func (c *clients) getDirectory(filepath string) {
	fmt.Println("Fetching directory ", filepath)

	os.Mkdir(path.Base(filepath), os.ModeDir|os.ModePerm)
	os.Chdir(path.Base(filepath))

	files, err := c.sftpClient.ReadDir(filepath)
	if err != nil {
		fmt.Println(err)
		return
	}

	for _, file := range files {
		f := FileStruct(file, filepath)
		if f.IsDir {
			c.getDirectory(f.Path)
		} else {
			c.getFile(f)
		}
	}

	os.Chdir("..")
}

// getFile copies the file specified to the local host
func (c *clients) getFile(file File) {
	fmt.Println("Fetching ", file.Filename)
	dest, err := os.Create(file.Filename)
	if err != nil {
		fmt.Println(err)
	}

	src, err := c.sftpClient.Open(file.Path)
	info, err := src.Stat()
	contents := make([]byte, info.Size())

	src.Read(contents)
	dest.Write(contents)
	dest.Close()
}
<commit_msg>Added a temporary fix in parsing the quotations out of the file path<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
)

/*
type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files;
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}
*/

// Echos the $HOME env to find the home directory, returns root if err
func getHomeDir(id int) string {
	// Create a new ssh session to access the remote host's $HOME env variable
	session, err := conns[id].sshClient.NewSession()
	defer session.Close()

	if err != nil {
		fmt.Println("Error creating ssh session:", err)
		return "/"
	}
	output, err := session.Output("echo $HOME")
	if err != nil {
		fmt.Println("Error finding home dir:", err)
		return "/"
	}
	return strings.TrimSpace(string(output))
}

func FileStruct(file os.FileInfo, dir string) File {
	return File{
		Filename: file.Name(),
		Path:     dir + "/" + file.Name(),
		ModTime:  file.ModTime(),
		IsDir:    file.IsDir(),
		Size:     file.Size(),
	}
}

// Print the target directory's file listing
func printDirectory(id int, dirpath string) {
	fmt.Println("Printing contents of", dirpath)
	if dirpath[0] == '"' {
		dirpath = dirpath[1 : len(dirpath)-1]
	}
	listing, err := conns[id].sftpClient.ReadDir(dirpath)
	fmt.Println("[", dirpath, "]")
	if err != nil {
		log.Fatal("Could not open directory : ", err)
	}

	var files []File
	for _, file := range listing {
		files = append(files, FileStruct(file, dirpath))
	}

	conns[id].putDirectory("./TestingDir", ".")

	jsonMessage, _ := json.Marshal(FileMessage{id, "FETCH_FILES_SUCCESS", files})
	_, _ = socket.Write(jsonMessage)
}

func (c *clients) putDirectory(src, dest string) {
	fmt.Println("Putting directory ", src)

	session, _ := c.sshClient.NewSession()
	session.Run("mkdir " + path.Join(dest, path.Base(src)))
	session.Close()

	files, _ := ioutil.ReadDir(src)
	for _, file := range files {
		if file.IsDir() {
			c.putDirectory(path.Join(src, file.Name()), path.Join(dest, path.Base(src)))
		} else {
			c.putFile(path.Join(src, file.Name()), path.Join(dest, path.Base(src)))
		}
	}
}

func (c *clients) putFile(src, dest string) {
	srcFile, _ := os.Open(src)
	destFile, err := c.sftpClient.Create(path.Join(dest, path.Base(src)))
	if err != nil {
		fmt.Println(err)
		return
	}

	info, _ := srcFile.Stat()
	contents := make([]byte, info.Size())
	srcFile.Read(contents)

	_, err = destFile.Write(contents)
	if err != nil {
		fmt.Println("Problem writing file : ", err)
	}
}

func (c *clients) getDirectory(filepath string) {
	fmt.Println("Fetching directory ", filepath)

	os.Mkdir(path.Base(filepath), os.ModeDir|os.ModePerm)
	os.Chdir(path.Base(filepath))

	files, err := c.sftpClient.ReadDir(filepath)
	if err != nil {
		fmt.Println(err)
		return
	}

	for _, file := range files {
		f := FileStruct(file, filepath)
		if f.IsDir {
			c.getDirectory(f.Path)
		} else {
			c.getFile(f)
		}
	}

	os.Chdir("..")
}

// getFile copies the file specified to the local host
func (c *clients) getFile(file File) {
	fmt.Println("Fetching ", file.Filename)
	dest, err := os.Create(file.Filename)
	if err != nil {
		fmt.Println(err)
	}

	src, err := c.sftpClient.Open(file.Path)
	info, err := src.Stat()
	contents := make([]byte, info.Size())

	src.Read(contents)
	dest.Write(contents)
	dest.Close()
}
<|endoftext|>


<commit_before>// Package tabsupport offers functionality to add tab support to a textarea element.
package tabsupport

import (
	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// Add is a helper that modifies a <textarea>, so that pressing tab key will insert tabs.
func Add(textArea *dom.HTMLTextAreaElement) {
	textArea.AddEventListener("keydown", false, func(event dom.Event) {
		switch ke := event.(*dom.KeyboardEvent); {
		case ke.KeyCode == '\t' && !ke.CtrlKey && !ke.AltKey && !ke.MetaKey && !ke.ShiftKey: // Tab.
			value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

			textArea.Value = value[:start] + "\t" + value[end:]

			textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

			event.PreventDefault()

			// Trigger "input" event listeners.
			inputEvent := js.Global.Get("CustomEvent").New("input")
			textArea.Underlying().Call("dispatchEvent", inputEvent)
		}
	})
}
<commit_msg>tabsupport: Add KeyDownHandler event handler.<commit_after>// Package tabsupport offers functionality to add tab support to a textarea element.
package tabsupport

import (
	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// Add is a helper that modifies a <textarea>, so that pressing tab key will insert tabs.
func Add(textArea *dom.HTMLTextAreaElement) {
	textArea.AddEventListener("keydown", false, func(event dom.Event) {
		switch ke := event.(*dom.KeyboardEvent); {
		case ke.KeyCode == '\t' && !ke.CtrlKey && !ke.AltKey && !ke.MetaKey && !ke.ShiftKey: // Tab.
			value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

			textArea.Value = value[:start] + "\t" + value[end:]

			textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

			event.PreventDefault()

			// Trigger "input" event listeners.
			inputEvent := js.Global.Get("CustomEvent").New("input")
			textArea.Underlying().Call("dispatchEvent", inputEvent)
		}
	})
}

// KeyDownHandler is a keydown event handler for a <textarea> element.
// It makes it so that pressing tab key will insert tabs.
//
// To use it, first make it available to the JavaScript world, e.g.:
//
// 	js.Global.Set("TabSupportKeyDownHandler", jsutil.Wrap(tabsupport.KeyDownHandler))
//
// Then use it as follows in the HTML:
//
// 	<textarea onkeydown="TabSupportKeyDownHandler(this, event);"></textarea>
//
func KeyDownHandler(element dom.HTMLElement, event dom.Event) {
	switch ke := event.(*dom.KeyboardEvent); {
	case ke.KeyCode == '\t' && !ke.CtrlKey && !ke.AltKey && !ke.MetaKey && !ke.ShiftKey: // Tab.
		textArea := element.(*dom.HTMLTextAreaElement)

		value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

		textArea.Value = value[:start] + "\t" + value[end:]

		textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

		event.PreventDefault()

		// Trigger "input" event listeners.
		inputEvent := js.Global.Get("CustomEvent").New("input")
		textArea.Underlying().Call("dispatchEvent", inputEvent)
	}
}
<|endoftext|>


<commit_before>package asm

import (
	"bytes"
	"compress/gzip"
	"crypto/sha1"
	"fmt"
	"hash/crc64"
	"io"
	"io/ioutil"
	"os"
	"testing"
	"unicode/utf8"

	"github.com/vbatts/tar-split/archive/tar"
	"github.com/vbatts/tar-split/tar/storage"
)

func TestISO8859(t *testing.T) {
	fh, err := os.Open("./testdata/iso-8859.tar.gz")
	if err != nil {
		t.Fatal(err)
	}
	defer fh.Close()
	gzRdr, err := gzip.NewReader(fh)
	if err != nil {
		t.Fatal(err)
	}
	defer gzRdr.Close()
	tr := tar.NewReader(gzRdr)
	for {
		hdr, err := tr.Next()
		if err != nil {
			if err != io.EOF {
				t.Error(err)
			}
			break
		}
		fmt.Println(hdr.Name)
		if !utf8.ValidString(hdr.Name) {
			fmt.Println([]byte(hdr.Name))
		}
	}
}

var entries = []struct {
	Entry storage.Entry
	Body  []byte
}{
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./hurr.txt",
			Payload: []byte{2, 116, 164, 177, 171, 236, 107, 78},
			Size:    20,
		},
		Body: []byte("imma hurr til I derp"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./ermahgerd.txt",
			Payload: []byte{126, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		Body: []byte("café con leche, por favor"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			NameRaw: []byte{0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe4}, // this is invalid UTF-8. Just checking the round trip.
			Payload: []byte{126, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		Body: []byte("café con leche, por favor"),
	},
}
var entriesMangled = []struct {
	Entry storage.Entry
	Body  []byte
}{
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./hurr.txt",
			Payload: []byte{3, 116, 164, 177, 171, 236, 107, 78},
			Size:    20,
		},
		// switch
		Body: []byte("imma derp til I hurr"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./ermahgerd.txt",
			Payload: []byte{127, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		// san not con
		Body: []byte("café sans leche, por favor"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			NameRaw: []byte{0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe4},
			Payload: []byte{127, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		Body: []byte("café con leche, por favor"),
	},
}

func TestTarStreamMangledGetterPutter(t *testing.T) {
	fgp := storage.NewBufferFileGetPutter()

	// first lets prep a GetPutter and Packer
	for i := range entries {
		if entries[i].Entry.Type == storage.FileType {
			j, csum, err := fgp.Put(entries[i].Entry.GetName(), bytes.NewBuffer(entries[i].Body))
			if err != nil {
				t.Error(err)
			}
			if j != entries[i].Entry.Size {
				t.Errorf("size %q: expected %d; got %d",
					entries[i].Entry.GetName(),
					entries[i].Entry.Size,
					j)
			}
			if !bytes.Equal(csum, entries[i].Entry.Payload) {
				t.Errorf("checksum %q: expected %v; got %v",
					entries[i].Entry.GetName(),
					entries[i].Entry.Payload,
					csum)
			}
		}
	}

	for _, e := range entriesMangled {
		if e.Entry.Type == storage.FileType {
			rdr, err := fgp.Get(e.Entry.GetName())
			if err != nil {
				t.Error(err)
			}
			c := crc64.New(storage.CRCTable)
			i, err := io.Copy(c, rdr)
			if err != nil {
				t.Fatal(err)
			}
			rdr.Close()

			csum := c.Sum(nil)
			if bytes.Equal(csum, e.Entry.Payload) {
				t.Errorf("wrote %d bytes. checksum for %q should not have matched! %v",
					i,
					e.Entry.GetName(),
					csum)
			}
		}
	}
}

func TestTarStream(t *testing.T) {
	testCases := []struct {
		path            string
		expectedSHA1Sum string
		expectedSize    int64
	}{
		{"./testdata/t.tar.gz", "1eb237ff69bca6e22789ecb05b45d35ca307adbd", 10240},
		{"./testdata/longlink.tar.gz", "d9f6babe107b7247953dff6b5b5ae31a3a880add", 20480},
		{"./testdata/fatlonglink.tar.gz", "8537f03f89aeef537382f8b0bb065d93e03b0be8", 26234880},
		{"./testdata/iso-8859.tar.gz", "ddafa51cb03c74ec117ab366ee2240d13bba1ec3", 10240},
	}

	for _, tc := range testCases {
		fh, err := os.Open(tc.path)
		if err != nil {
			t.Fatal(err)
		}
		defer fh.Close()
		gzRdr, err := gzip.NewReader(fh)
		if err != nil {
			t.Fatal(err)
		}
		defer gzRdr.Close()

		// Setup where we'll store the metadata
		w := bytes.NewBuffer([]byte{})
		sp := storage.NewJSONPacker(w)
		fgp := storage.NewBufferFileGetPutter()

		// wrap the disassembly stream
		tarStream, err := NewInputTarStream(gzRdr, sp, fgp)
		if err != nil {
			t.Fatal(err)
		}

		// get a sum of the stream after it has passed through to ensure it's the same.
		h0 := sha1.New()
		tRdr0 := io.TeeReader(tarStream, h0)

		// read it all to the bit bucket
		i, err := io.Copy(ioutil.Discard, tRdr0)
		if err != nil {
			t.Fatal(err)
		}

		if i != tc.expectedSize {
			t.Errorf("size of tar: expected %d; got %d", tc.expectedSize, i)
		}
		if fmt.Sprintf("%x", h0.Sum(nil)) != tc.expectedSHA1Sum {
			t.Fatalf("checksum of tar: expected %s; got %x", tc.expectedSHA1Sum, h0.Sum(nil))
		}

		//t.Logf("%s", w.String()) // if we fail, then show the packed info

		// If we've made it this far, then we'll turn it around and create a tar
		// stream from the packed metadata and buffered file contents.
		r := bytes.NewBuffer(w.Bytes())
		sup := storage.NewJSONUnpacker(r)
		// and reuse the fgp that we Put the payloads to.

		rc := NewOutputTarStream(fgp, sup)
		h1 := sha1.New()
		i, err = io.Copy(h1, rc)
		if err != nil {
			t.Fatal(err)
		}

		if i != tc.expectedSize {
			t.Errorf("size of output tar: expected %d; got %d", tc.expectedSize, i)
		}
		if fmt.Sprintf("%x", h1.Sum(nil)) != tc.expectedSHA1Sum {
			t.Fatalf("checksum of output tar: expected %s; got %x", tc.expectedSHA1Sum, h1.Sum(nil))
		}
	}
}
<commit_msg>tar/asm: remove useless test<commit_after>package asm

import (
	"bytes"
	"compress/gzip"
	"crypto/sha1"
	"fmt"
	"hash/crc64"
	"io"
	"io/ioutil"
	"os"
	"testing"

	"github.com/vbatts/tar-split/tar/storage"
)

var entries = []struct {
	Entry storage.Entry
	Body  []byte
}{
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./hurr.txt",
			Payload: []byte{2, 116, 164, 177, 171, 236, 107, 78},
			Size:    20,
		},
		Body: []byte("imma hurr til I derp"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./ermahgerd.txt",
			Payload: []byte{126, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		Body: []byte("café con leche, por favor"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			NameRaw: []byte{0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe4}, // this is invalid UTF-8. Just checking the round trip.
			Payload: []byte{126, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		Body: []byte("café con leche, por favor"),
	},
}
var entriesMangled = []struct {
	Entry storage.Entry
	Body  []byte
}{
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./hurr.txt",
			Payload: []byte{3, 116, 164, 177, 171, 236, 107, 78},
			Size:    20,
		},
		// switch
		Body: []byte("imma derp til I hurr"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			Name:    "./ermahgerd.txt",
			Payload: []byte{127, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		// san not con
		Body: []byte("café sans leche, por favor"),
	},
	{
		Entry: storage.Entry{
			Type:    storage.FileType,
			NameRaw: []byte{0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe4},
			Payload: []byte{127, 72, 89, 239, 230, 252, 160, 187},
			Size:    26,
		},
		Body: []byte("café con leche, por favor"),
	},
}

func TestTarStreamMangledGetterPutter(t *testing.T) {
	fgp := storage.NewBufferFileGetPutter()

	// first lets prep a GetPutter and Packer
	for i := range entries {
		if entries[i].Entry.Type == storage.FileType {
			j, csum, err := fgp.Put(entries[i].Entry.GetName(), bytes.NewBuffer(entries[i].Body))
			if err != nil {
				t.Error(err)
			}
			if j != entries[i].Entry.Size {
				t.Errorf("size %q: expected %d; got %d",
					entries[i].Entry.GetName(),
					entries[i].Entry.Size,
					j)
			}
			if !bytes.Equal(csum, entries[i].Entry.Payload) {
				t.Errorf("checksum %q: expected %v; got %v",
					entries[i].Entry.GetName(),
					entries[i].Entry.Payload,
					csum)
			}
		}
	}

	for _, e := range entriesMangled {
		if e.Entry.Type == storage.FileType {
			rdr, err := fgp.Get(e.Entry.GetName())
			if err != nil {
				t.Error(err)
			}
			c := crc64.New(storage.CRCTable)
			i, err := io.Copy(c, rdr)
			if err != nil {
				t.Fatal(err)
			}
			rdr.Close()

			csum := c.Sum(nil)
			if bytes.Equal(csum, e.Entry.Payload) {
				t.Errorf("wrote %d bytes. checksum for %q should not have matched! %v",
					i,
					e.Entry.GetName(),
					csum)
			}
		}
	}
}

func TestTarStream(t *testing.T) {
	testCases := []struct {
		path            string
		expectedSHA1Sum string
		expectedSize    int64
	}{
		{"./testdata/t.tar.gz", "1eb237ff69bca6e22789ecb05b45d35ca307adbd", 10240},
		{"./testdata/longlink.tar.gz", "d9f6babe107b7247953dff6b5b5ae31a3a880add", 20480},
		{"./testdata/fatlonglink.tar.gz", "8537f03f89aeef537382f8b0bb065d93e03b0be8", 26234880},
		{"./testdata/iso-8859.tar.gz", "ddafa51cb03c74ec117ab366ee2240d13bba1ec3", 10240},
	}

	for _, tc := range testCases {
		fh, err := os.Open(tc.path)
		if err != nil {
			t.Fatal(err)
		}
		defer fh.Close()
		gzRdr, err := gzip.NewReader(fh)
		if err != nil {
			t.Fatal(err)
		}
		defer gzRdr.Close()

		// Setup where we'll store the metadata
		w := bytes.NewBuffer([]byte{})
		sp := storage.NewJSONPacker(w)
		fgp := storage.NewBufferFileGetPutter()

		// wrap the disassembly stream
		tarStream, err := NewInputTarStream(gzRdr, sp, fgp)
		if err != nil {
			t.Fatal(err)
		}

		// get a sum of the stream after it has passed through to ensure it's the same.
		h0 := sha1.New()
		tRdr0 := io.TeeReader(tarStream, h0)

		// read it all to the bit bucket
		i, err := io.Copy(ioutil.Discard, tRdr0)
		if err != nil {
			t.Fatal(err)
		}

		if i != tc.expectedSize {
			t.Errorf("size of tar: expected %d; got %d", tc.expectedSize, i)
		}
		if fmt.Sprintf("%x", h0.Sum(nil)) != tc.expectedSHA1Sum {
			t.Fatalf("checksum of tar: expected %s; got %x", tc.expectedSHA1Sum, h0.Sum(nil))
		}

		//t.Logf("%s", w.String()) // if we fail, then show the packed info

		// If we've made it this far, then we'll turn it around and create a tar
		// stream from the packed metadata and buffered file contents.
		r := bytes.NewBuffer(w.Bytes())
		sup := storage.NewJSONUnpacker(r)
		// and reuse the fgp that we Put the payloads to.

		rc := NewOutputTarStream(fgp, sup)
		h1 := sha1.New()
		i, err = io.Copy(h1, rc)
		if err != nil {
			t.Fatal(err)
		}

		if i != tc.expectedSize {
			t.Errorf("size of output tar: expected %d; got %d", tc.expectedSize, i)
		}
		if fmt.Sprintf("%x", h1.Sum(nil)) != tc.expectedSHA1Sum {
			t.Fatalf("checksum of output tar: expected %s; got %x", tc.expectedSHA1Sum, h1.Sum(nil))
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 integration_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/jacobsa/fuse"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestGcsfuse(t *testing.T) { RunTests(t) }

// Cf. bucket.go.
const fakeBucketName = "fake@bucket"

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type GcsfuseTest struct {
	// Path to the gcsfuse binary.
	gcsfusePath string

	// A temporary directory into which a file system may be mounted. Removed in
	// TearDown.
	dir string
}

var _ SetUpInterface = &GcsfuseTest{}
var _ TearDownInterface = &GcsfuseTest{}

func init() { RegisterTestSuite(&GcsfuseTest{}) }

func (t *GcsfuseTest) SetUp(_ *TestInfo) {
	var err error
	t.gcsfusePath = path.Join(gBuildDir, "bin/gcsfuse")

	// Set up the temporary directory.
	t.dir, err = ioutil.TempDir("", "gcsfuse_test")
	AssertEq(nil, err)
}

func (t *GcsfuseTest) TearDown() {
	err := os.Remove(t.dir)
	AssertEq(nil, err)
}

// Call gcsfuse with the supplied args, waiting for it to mount. Return nil
// only if it mounts successfully.
func (t *GcsfuseTest) mount(args []string) (err error) {
	// Set up a pipe that gcsfuse can write to to tell us when it has
	// successfully mounted.
	statusR, statusW, err := os.Pipe()
	if err != nil {
		err = fmt.Errorf("Pipe: %v", err)
		return
	}

	// Run gcsfuse, writing the result of waiting for it to a channel.
	gcsfuseErr := make(chan error, 1)
	go func() {
		gcsfuseErr <- t.runGcsfuse(args, statusW)
	}()

	// In the background, wait for something to be written to the pipe.
	pipeErr := make(chan error, 1)
	go func() {
		defer statusR.Close()
		n, err := statusR.Read(make([]byte, 1))
		if n == 1 {
			pipeErr <- nil
			return
		}

		pipeErr <- fmt.Errorf("statusR.Read: %v", err)
	}()

	// Watch for a result from one of them.
	select {
	case err = <-gcsfuseErr:
		err = fmt.Errorf("gcsfuse: %v", err)
		return

	case err = <-pipeErr:
		if err == nil {
			// All is good.
			return
		}

		err = <-gcsfuseErr
		err = fmt.Errorf("gcsfuse after pipe error: %v", err)
		return
	}
}

// Run gcsfuse and wait for it to return. Hand it the supplied pipe to write
// into when it successfully mounts. This function takes responsibility for
// closing the write end of the pipe locally.
func (t *GcsfuseTest) runGcsfuse(args []string, statusW *os.File) (err error) {
	defer statusW.Close()

	cmd := exec.Command(t.gcsfusePath)
	cmd.Args = append(cmd.Args, args...)
	cmd.ExtraFiles = []*os.File{statusW}
	cmd.Env = []string{"STATUS_PIPE=3"}

	output, err := cmd.CombinedOutput()
	if err != nil {
		err = fmt.Errorf("%v\nOutput:\n%s", err, output)
		return
	}

	return
}

// Unmount the file system mounted at the supplied directory. Try again on
// "resource busy" errors, which happen from time to time on OS X (due to weird
// requests from the Finder).
func unmount(dir string) (err error) {
	delay := 10 * time.Millisecond
	for {
		err = fuse.Unmount(dir)
		if err == nil {
			return
		}

		if strings.Contains(err.Error(), "resource busy") {
			log.Println("Resource busy error while unmounting; trying again")
			time.Sleep(delay)
			delay = time.Duration(1.3 * float64(delay))
			continue
		}

		err = fmt.Errorf("Unmount: %v", err)
		return
	}
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *GcsfuseTest) BadUsage() {
	testCases := []struct {
		args           []string
		expectedOutput string
	}{
		// Too few args
		0: {
			[]string{fakeBucketName},
			"exactly two arguments",
		},

		// Too many args
		1: {
			[]string{fakeBucketName, "a", "b"},
			"exactly two arguments",
		},

		// Unknown flag
		2: {
			[]string{"--tweak_frobnicator", fakeBucketName, "a"},
			"not defined.*tweak_frobnicator",
		},
	}

	// Run each test case.
	for i, tc := range testCases {
		cmd := exec.Command(t.gcsfusePath)
		cmd.Args = append(cmd.Args, tc.args...)

		output, err := cmd.CombinedOutput()
		ExpectThat(err, Error(HasSubstr("exit status")), "case %d", i)
		ExpectThat(string(output), MatchesRegexp(tc.expectedOutput), "case %d", i)
	}
}

func (t *GcsfuseTest) CannedContents() {
	var err error
	var fi os.FileInfo

	// Mount.
	args := []string{fakeBucketName, t.dir}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Check the expected contents of the file system (cf. bucket.go).
	fi, err = os.Lstat(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq(os.FileMode(0644), fi.Mode())

	contents, err := ioutil.ReadFile(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq("taco", string(contents))

	fi, err = os.Lstat(path.Join(t.dir, "bar"))
	AssertEq(nil, err)
	ExpectEq(0755|os.ModeDir, fi.Mode())

	// The implicit directory shouldn't be visible, since we don't have implicit
	// directories enabled.
	_, err = os.Lstat(path.Join(t.dir, "baz"))
	ExpectTrue(os.IsNotExist(err), "err: %v", err)
}

func (t *GcsfuseTest) ReadOnlyMode() {
	var err error

	// Mount.
	args := []string{"-o", "ro", fakeBucketName, t.dir}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Writing to the file system should fail.
	err = ioutil.WriteFile(path.Join(t.dir, "blah"), []byte{}, 0400)
	ExpectThat(err, Error(HasSubstr("read-only")))
}

func (t *GcsfuseTest) ReadWriteMode() {
	var err error

	// Mount.
	args := []string{fakeBucketName, t.dir}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Overwrite the canned file.
	p := path.Join(t.dir, "foo")

	err = ioutil.WriteFile(p, []byte("enchilada"), 0400)
	AssertEq(nil, err)

	contents, err := ioutil.ReadFile(p)
	AssertEq(nil, err)
	ExpectEq("enchilada", string(contents))
}

func (t *GcsfuseTest) FileAndDirModeFlags() {
	var err error
	var fi os.FileInfo

	// Mount with non-standard modes.
	args := []string{
		"--file-mode", "461",
		"--dir-mode", "511",
		fakeBucketName,
		t.dir,
	}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Stat contents.
	fi, err = os.Lstat(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq(os.FileMode(0461), fi.Mode())

	fi, err = os.Lstat(path.Join(t.dir, "bar"))
	AssertEq(nil, err)
	ExpectEq(0511|os.ModeDir, fi.Mode())
}

func (t *GcsfuseTest) UidAndGidFlags() {
	var err error
	var fi os.FileInfo

	// Mount, setting the flags. Make sure to set the directory mode such that we
	// can actually see the contents.
	args := []string{
		"--uid", "1719",
		"--gid", "2329",
		"--dir-mode", "555",
		fakeBucketName,
		t.dir,
	}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Stat contents.
	fi, err = os.Lstat(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq(1719, fi.Sys().(*syscall.Stat_t).Uid)
	ExpectEq(2329, fi.Sys().(*syscall.Stat_t).Gid)

	fi, err = os.Lstat(path.Join(t.dir, "bar"))
	AssertEq(nil, err)
	ExpectEq(1719, fi.Sys().(*syscall.Stat_t).Uid)
	ExpectEq(2329, fi.Sys().(*syscall.Stat_t).Gid)
}

func (t *GcsfuseTest) ImplicitDirs() {
	var err error
	var fi os.FileInfo

	// Mount with implicit directories enabled.
	args := []string{
		"--implicit-dirs",
		fakeBucketName,
		t.dir,
	}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// The implicit directory should be visible, as should its child.
	fi, err = os.Lstat(path.Join(t.dir, "baz"))
	AssertEq(nil, err)
	ExpectEq(0755|os.ModeDir, fi.Mode())

	fi, err = os.Lstat(path.Join(t.dir, "baz/qux"))
	AssertEq(nil, err)
	ExpectEq(os.FileMode(0644), fi.Mode())
}

func (t *GcsfuseTest) VersionFlags() {
	AssertTrue(false, "TODO")
}

func (t *GcsfuseTest) HelpFlags() {
	AssertTrue(false, "TODO")
}
<commit_msg>GcsfuseTest.VersionFlags<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 integration_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/jacobsa/fuse"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestGcsfuse(t *testing.T) { RunTests(t) }

// Cf. bucket.go.
const fakeBucketName = "fake@bucket"

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type GcsfuseTest struct {
	// Path to the gcsfuse binary.
	gcsfusePath string

	// A temporary directory into which a file system may be mounted. Removed in
	// TearDown.
	dir string
}

var _ SetUpInterface = &GcsfuseTest{}
var _ TearDownInterface = &GcsfuseTest{}

func init() { RegisterTestSuite(&GcsfuseTest{}) }

func (t *GcsfuseTest) SetUp(_ *TestInfo) {
	var err error
	t.gcsfusePath = path.Join(gBuildDir, "bin/gcsfuse")

	// Set up the temporary directory.
	t.dir, err = ioutil.TempDir("", "gcsfuse_test")
	AssertEq(nil, err)
}

func (t *GcsfuseTest) TearDown() {
	err := os.Remove(t.dir)
	AssertEq(nil, err)
}

// Call gcsfuse with the supplied args, waiting for it to mount. Return nil
// only if it mounts successfully.
func (t *GcsfuseTest) mount(args []string) (err error) {
	// Set up a pipe that gcsfuse can write to to tell us when it has
	// successfully mounted.
	statusR, statusW, err := os.Pipe()
	if err != nil {
		err = fmt.Errorf("Pipe: %v", err)
		return
	}

	// Run gcsfuse, writing the result of waiting for it to a channel.
	gcsfuseErr := make(chan error, 1)
	go func() {
		gcsfuseErr <- t.runGcsfuse(args, statusW)
	}()

	// In the background, wait for something to be written to the pipe.
	pipeErr := make(chan error, 1)
	go func() {
		defer statusR.Close()
		n, err := statusR.Read(make([]byte, 1))
		if n == 1 {
			pipeErr <- nil
			return
		}

		pipeErr <- fmt.Errorf("statusR.Read: %v", err)
	}()

	// Watch for a result from one of them.
	select {
	case err = <-gcsfuseErr:
		err = fmt.Errorf("gcsfuse: %v", err)
		return

	case err = <-pipeErr:
		if err == nil {
			// All is good.
			return
		}

		err = <-gcsfuseErr
		err = fmt.Errorf("gcsfuse after pipe error: %v", err)
		return
	}
}

// Run gcsfuse and wait for it to return. Hand it the supplied pipe to write
// into when it successfully mounts. This function takes responsibility for
// closing the write end of the pipe locally.
func (t *GcsfuseTest) runGcsfuse(args []string, statusW *os.File) (err error) {
	defer statusW.Close()

	cmd := exec.Command(t.gcsfusePath)
	cmd.Args = append(cmd.Args, args...)
	cmd.ExtraFiles = []*os.File{statusW}
	cmd.Env = []string{"STATUS_PIPE=3"}

	output, err := cmd.CombinedOutput()
	if err != nil {
		err = fmt.Errorf("%v\nOutput:\n%s", err, output)
		return
	}

	return
}

// Unmount the file system mounted at the supplied directory. Try again on
// "resource busy" errors, which happen from time to time on OS X (due to weird
// requests from the Finder).
func unmount(dir string) (err error) {
	delay := 10 * time.Millisecond
	for {
		err = fuse.Unmount(dir)
		if err == nil {
			return
		}

		if strings.Contains(err.Error(), "resource busy") {
			log.Println("Resource busy error while unmounting; trying again")
			time.Sleep(delay)
			delay = time.Duration(1.3 * float64(delay))
			continue
		}

		err = fmt.Errorf("Unmount: %v", err)
		return
	}
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *GcsfuseTest) BadUsage() {
	testCases := []struct {
		args           []string
		expectedOutput string
	}{
		// Too few args
		0: {
			[]string{fakeBucketName},
			"exactly two arguments",
		},

		// Too many args
		1: {
			[]string{fakeBucketName, "a", "b"},
			"exactly two arguments",
		},

		// Unknown flag
		2: {
			[]string{"--tweak_frobnicator", fakeBucketName, "a"},
			"not defined.*tweak_frobnicator",
		},
	}

	// Run each test case.
	for i, tc := range testCases {
		cmd := exec.Command(t.gcsfusePath)
		cmd.Args = append(cmd.Args, tc.args...)

		output, err := cmd.CombinedOutput()
		ExpectThat(err, Error(HasSubstr("exit status")), "case %d", i)
		ExpectThat(string(output), MatchesRegexp(tc.expectedOutput), "case %d", i)
	}
}

func (t *GcsfuseTest) CannedContents() {
	var err error
	var fi os.FileInfo

	// Mount.
	args := []string{fakeBucketName, t.dir}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Check the expected contents of the file system (cf. bucket.go).
	fi, err = os.Lstat(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq(os.FileMode(0644), fi.Mode())

	contents, err := ioutil.ReadFile(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq("taco", string(contents))

	fi, err = os.Lstat(path.Join(t.dir, "bar"))
	AssertEq(nil, err)
	ExpectEq(0755|os.ModeDir, fi.Mode())

	// The implicit directory shouldn't be visible, since we don't have implicit
	// directories enabled.
	_, err = os.Lstat(path.Join(t.dir, "baz"))
	ExpectTrue(os.IsNotExist(err), "err: %v", err)
}

func (t *GcsfuseTest) ReadOnlyMode() {
	var err error

	// Mount.
	args := []string{"-o", "ro", fakeBucketName, t.dir}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Writing to the file system should fail.
	err = ioutil.WriteFile(path.Join(t.dir, "blah"), []byte{}, 0400)
	ExpectThat(err, Error(HasSubstr("read-only")))
}

func (t *GcsfuseTest) ReadWriteMode() {
	var err error

	// Mount.
	args := []string{fakeBucketName, t.dir}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Overwrite the canned file.
	p := path.Join(t.dir, "foo")

	err = ioutil.WriteFile(p, []byte("enchilada"), 0400)
	AssertEq(nil, err)

	contents, err := ioutil.ReadFile(p)
	AssertEq(nil, err)
	ExpectEq("enchilada", string(contents))
}

func (t *GcsfuseTest) FileAndDirModeFlags() {
	var err error
	var fi os.FileInfo

	// Mount with non-standard modes.
	args := []string{
		"--file-mode", "461",
		"--dir-mode", "511",
		fakeBucketName,
		t.dir,
	}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Stat contents.
	fi, err = os.Lstat(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq(os.FileMode(0461), fi.Mode())

	fi, err = os.Lstat(path.Join(t.dir, "bar"))
	AssertEq(nil, err)
	ExpectEq(0511|os.ModeDir, fi.Mode())
}

func (t *GcsfuseTest) UidAndGidFlags() {
	var err error
	var fi os.FileInfo

	// Mount, setting the flags. Make sure to set the directory mode such that we
	// can actually see the contents.
	args := []string{
		"--uid", "1719",
		"--gid", "2329",
		"--dir-mode", "555",
		fakeBucketName,
		t.dir,
	}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// Stat contents.
	fi, err = os.Lstat(path.Join(t.dir, "foo"))
	AssertEq(nil, err)
	ExpectEq(1719, fi.Sys().(*syscall.Stat_t).Uid)
	ExpectEq(2329, fi.Sys().(*syscall.Stat_t).Gid)

	fi, err = os.Lstat(path.Join(t.dir, "bar"))
	AssertEq(nil, err)
	ExpectEq(1719, fi.Sys().(*syscall.Stat_t).Uid)
	ExpectEq(2329, fi.Sys().(*syscall.Stat_t).Gid)
}

func (t *GcsfuseTest) ImplicitDirs() {
	var err error
	var fi os.FileInfo

	// Mount with implicit directories enabled.
	args := []string{
		"--implicit-dirs",
		fakeBucketName,
		t.dir,
	}

	err = t.mount(args)
	AssertEq(nil, err)
	defer unmount(t.dir)

	// The implicit directory should be visible, as should its child.
	fi, err = os.Lstat(path.Join(t.dir, "baz"))
	AssertEq(nil, err)
	ExpectEq(0755|os.ModeDir, fi.Mode())

	fi, err = os.Lstat(path.Join(t.dir, "baz/qux"))
	AssertEq(nil, err)
	ExpectEq(os.FileMode(0644), fi.Mode())
}

func (t *GcsfuseTest) VersionFlags() {
	testCases := []struct {
		args []string
	}{
		0: {[]string{"-v"}},
		1: {[]string{"--version"}},
	}

	// For each argument, gcsfuse should exist successfully.
	for i, tc := range testCases {
		cmd := exec.Command(t.gcsfusePath)
		cmd.Args = append(cmd.Args, tc.args...)

		output, err := cmd.CombinedOutput()
		ExpectEq(nil, err, "case %d\nOutput:\n%s", i, output)
	}
}

func (t *GcsfuseTest) HelpFlags() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>// unitygooglelivecaption.go
// intended to be used in unity project
// modification of livecaption.go found in https://github.com/GoogleCloudPlatform/golang-samples.git
//
// process requires google service accounts credential file's path
// you can get one in your google cloud console
// ----------------------------------------------------------------//

// livecaption.go
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Command livecaption pipes the stdin audio data to
// Google Speech API and outputs the transcript.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"

	speech "cloud.google.com/go/speech/apiv1beta1"
	"golang.org/x/net/context"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
	speechpb "google.golang.org/genproto/googleapis/cloud/speech/v1beta1"
)

var (
	version        = "v0.1"
	responcePrefix = "response: "
)

func main() {
	var credentialDir string
	var language string
	flag.StringVar(&credentialDir, "cred", "/path/to/file/", "path of google service account credential json file")
	flag.StringVar(&language, "language", "ja-JP", "languagecode of voice")
	flag.Parse()

	os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", credentialDir)
	ctx := context.Background()
	conn, err := transport.DialGRPC(
		ctx,
		option.WithEndpoint("speech.googleapis.com:443"),
		option.WithScopes("https://www.googleapis.com/auth/cloud-platform"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// [START speech_streaming_mic_recognize]
	client, err := speech.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	stream, err := client.StreamingRecognize(ctx)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("ready to start")
	reader := bufio.NewScanner(os.Stdin)
	for reader.Scan() {
		if reader.Text() == "start" {
			break
		}
	}

	// Send the initial configuration message.
	if err := stream.Send(&speechpb.StreamingRecognizeRequest{
		StreamingRequest: &speechpb.StreamingRecognizeRequest_StreamingConfig{
			StreamingConfig: &speechpb.StreamingRecognitionConfig{
				Config: &speechpb.RecognitionConfig{
					LanguageCode: language,
					Encoding:     speechpb.RecognitionConfig_LINEAR16,
					SampleRate:   16000,
				},
				InterimResults: true,
			},
		},
	}); err != nil {
		log.Fatal(err)
	}

	go func() {
		buf := make([]byte, 1024)
		threadScanner := bufio.NewScanner(os.Stdin)
		for threadScanner.Scan() {
			// get filepath form unity and get the raw file data
			file, err := os.Open(filepath.Clean(threadScanner.Text()))
			if err != nil {
				log.Fatal(err)
			}
			n, err := file.Read(buf)
			file.Close()
			if err == io.EOF {
				break // Nothing else to pipe, return from this goroutine.
			}
			if err != nil {
				log.Printf("Could not read from stdin: %v", err)
				continue
			}
			if err = stream.Send(&speechpb.StreamingRecognizeRequest{
				StreamingRequest: &speechpb.StreamingRecognizeRequest_AudioContent{
					AudioContent: buf[:n],
				},
			}); err != nil {
				log.Printf("Could not send audio: %v", err)
			}
		}
		log.Println("end")
	}()

	for {
		resp, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("Cannot stream results: %v", err)
		}
		if err := resp.Error; err != nil {
			log.Fatalf("Could not recognize: %v", err)
		}
		for _, result := range resp.Results {
			fmt.Println(responcePrefix + result.Alternatives[0].Transcript)
		}
	}
	// [END speech_streaming_mic_recognize]
}
<commit_msg>bigger buffer<commit_after>// unitygooglelivecaption.go
// intended to be used in unity project
// modification of livecaption.go found in https://github.com/GoogleCloudPlatform/golang-samples.git
//
// process requires google service accounts credential file's path
// you can get one in your google cloud console
// ----------------------------------------------------------------//

// livecaption.go
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Command livecaption pipes the stdin audio data to
// Google Speech API and outputs the transcript.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"

	speech "cloud.google.com/go/speech/apiv1beta1"
	"golang.org/x/net/context"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
	speechpb "google.golang.org/genproto/googleapis/cloud/speech/v1beta1"
)

var (
	version        = "v0.1"
	responcePrefix = "response: "
)

func main() {
	var credentialDir string
	var language string
	flag.StringVar(&credentialDir, "cred", "/path/to/file/", "path of google service account credential json file")
	flag.StringVar(&language, "language", "ja-JP", "languagecode of voice")
	flag.Parse()

	os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", credentialDir)
	ctx := context.Background()
	conn, err := transport.DialGRPC(
		ctx,
		option.WithEndpoint("speech.googleapis.com:443"),
		option.WithScopes("https://www.googleapis.com/auth/cloud-platform"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// [START speech_streaming_mic_recognize]
	client, err := speech.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	stream, err := client.StreamingRecognize(ctx)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("ready to start")
	reader := bufio.NewScanner(os.Stdin)
	for reader.Scan() {
		if reader.Text() == "start" {
			break
		}
	}

	// Send the initial configuration message.
	if err := stream.Send(&speechpb.StreamingRecognizeRequest{
		StreamingRequest: &speechpb.StreamingRecognizeRequest_StreamingConfig{
			StreamingConfig: &speechpb.StreamingRecognitionConfig{
				Config: &speechpb.RecognitionConfig{
					LanguageCode: language,
					Encoding:     speechpb.RecognitionConfig_LINEAR16,
					SampleRate:   16000,
				},
				InterimResults: true,
			},
		},
	}); err != nil {
		log.Fatal(err)
	}

	go func() {
		buf := make([]byte, 4096)
		threadScanner := bufio.NewScanner(os.Stdin)
		for threadScanner.Scan() {
			// get filepath form unity and get the raw file data
			file, err := os.Open(filepath.Clean(threadScanner.Text()))
			if err != nil {
				log.Fatal(err)
			}
			n, err := file.Read(buf)
			file.Close()
			// if err == io.EOF {
			// 	break // Nothing else to pipe, return from this goroutine.
			// }
			if err != nil {
				log.Fatal(err)
			}
			if err = stream.Send(&speechpb.StreamingRecognizeRequest{
				StreamingRequest: &speechpb.StreamingRecognizeRequest_AudioContent{
					AudioContent: buf[:n],
				},
			}); err != nil {
				log.Printf("Could not send audio: %v", err)
			}
		}
	}()

	for {
		resp, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("Cannot stream results: %v", err)
		}
		if err := resp.Error; err != nil {
			log.Fatalf("Could not recognize: %v", err)
		}
		for _, result := range resp.Results {
			fmt.Println(responcePrefix + result.Alternatives[0].Transcript)
		}
	}
	// [END speech_streaming_mic_recognize]
}
<|endoftext|>