<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package sources

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strings"

	"github.com/OWASP/Amass/amass/core"
	"github.com/OWASP/Amass/amass/utils"
)

// VirusTotal is the Service that handles access to the VirusTotal data source.
type VirusTotal struct {
	core.BaseService

	API        *core.APIKey
	SourceType string

	haveAPIKey bool
}

// NewVirusTotal returns he object initialized, but not yet started.
func NewVirusTotal(config *core.Config, bus *core.EventBus) *VirusTotal {
	v := &VirusTotal{
		SourceType: core.API,
		haveAPIKey: true,
	}

	v.BaseService = *core.NewBaseService(v, "VirusTotal", config, bus)
	return v
}

// OnStart implements the Service interface
func (v *VirusTotal) OnStart() error {
	v.BaseService.OnStart()

	v.API = v.Config().GetAPIKey(v.String())
	if v.API == nil || v.API.Key == "" {
		v.haveAPIKey = false
		v.Config().Log.Printf("%s: API key data was not provided", v.String())
	}

	go v.processRequests()
	return nil
}

func (v *VirusTotal) processRequests() {
	for {
		select {
		case <-v.Quit():
			return
		case req := <-v.RequestChan():
			if v.Config().IsDomainInScope(req.Domain) {
				if v.haveAPIKey {
					v.apiQuery(req.Domain)
				} else {
					v.regularQuery(req.Domain)
				}
			}
		}
	}
}

func (v *VirusTotal) apiQuery(domain string) {
	url := v.apiURL(domain)
	headers := map[string]string{"Content-Type": "application/json"}
	page, err := utils.RequestWebPage(url, nil, headers, "", "")
	if err != nil {
		v.Config().Log.Printf("%s: %s: %v", v.String(), url, err)
		return
	}

	// Extract the subdomain names from the results
	var m struct {
		ResponseCode int      `json:"response_code"`
		Message      string   `json:"verbose_msg"`
		Subdomains   []string `json:"subdomains"`
		Resolutions  []struct {
			IP string `json:"ip_address"`
		} `json:"resolutions"`
	}
	if err := json.Unmarshal([]byte(page), &m); err != nil {
		return
	}

	if m.ResponseCode != 1 {
		v.Config().Log.Printf("%s: %s: Response code %d: %s", v.String(), url, m.ResponseCode, m.Message)
		return
	}

	v.SetActive()
	re := v.Config().DomainRegex(domain)
	for _, sub := range m.Subdomains {
		s := strings.ToLower(sub)

		if !re.MatchString(s) {
			continue
		}

		v.Bus().Publish(core.NewNameTopic, &core.Request{
			Name:   s,
			Domain: domain,
			Tag:    v.SourceType,
			Source: v.String(),
		})
	}

	for _, res := range m.Resolutions {
		v.Bus().Publish(core.NewNameTopic, &core.Request{
			Address: res.IP,
			Domain:  domain,
			Tag:     v.SourceType,
			Source:  v.String(),
		})
	}
}

func (v *VirusTotal) apiURL(domain string) string {
	u, _ := url.Parse("https://www.virustotal.com/vtapi/v2/domain/report")
	u.RawQuery = url.Values{"apikey": {v.API.Key}, "domain": {domain}}.Encode()

	return u.String()
}

func (v *VirusTotal) regularQuery(domain string) {
	url := v.getURL(domain)
	headers := map[string]string{"Content-Type": "application/json"}
	page, err := utils.RequestWebPage(url, nil, headers, "", "")
	if err != nil {
		v.Config().Log.Printf("%s: %s: %v", v.String(), url, err)
		return
	}

	// Extract the subdomain names from the results
	var m struct {
		Data []struct {
			ID   string `json:"id"`
			Type string `json:"type"`
		} `json:"data"`
	}
	if err := json.Unmarshal([]byte(page), &m); err != nil {
		return
	}

	v.SetActive()
	re := v.Config().DomainRegex(domain)
	for _, data := range m.Data {
		if data.Type != "domain" || !re.MatchString(data.ID) {
			continue
		}

		v.Bus().Publish(core.NewNameTopic, &core.Request{
			Name:   data.ID,
			Domain: domain,
			Tag:    v.SourceType,
			Source: v.String(),
		})
	}
}

func (v *VirusTotal) getURL(domain string) string {
	format := "https://www.virustotal.com/ui/domains/%s/subdomains?limit=40"

	return fmt.Sprintf(format, domain)
}
<commit_msg>fixed the ability to publish discovered IP addresses<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package sources

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strings"

	"github.com/OWASP/Amass/amass/core"
	"github.com/OWASP/Amass/amass/utils"
)

// VirusTotal is the Service that handles access to the VirusTotal data source.
type VirusTotal struct {
	core.BaseService

	API        *core.APIKey
	SourceType string

	haveAPIKey bool
}

// NewVirusTotal returns he object initialized, but not yet started.
func NewVirusTotal(config *core.Config, bus *core.EventBus) *VirusTotal {
	v := &VirusTotal{
		SourceType: core.API,
		haveAPIKey: true,
	}

	v.BaseService = *core.NewBaseService(v, "VirusTotal", config, bus)
	return v
}

// OnStart implements the Service interface
func (v *VirusTotal) OnStart() error {
	v.BaseService.OnStart()

	v.API = v.Config().GetAPIKey(v.String())
	if v.API == nil || v.API.Key == "" {
		v.haveAPIKey = false
		v.Config().Log.Printf("%s: API key data was not provided", v.String())
	}

	go v.processRequests()
	return nil
}

func (v *VirusTotal) processRequests() {
	for {
		select {
		case <-v.Quit():
			return
		case req := <-v.RequestChan():
			if v.Config().IsDomainInScope(req.Domain) {
				if v.haveAPIKey {
					v.apiQuery(req.Domain)
				} else {
					v.regularQuery(req.Domain)
				}
			}
		}
	}
}

func (v *VirusTotal) apiQuery(domain string) {
	url := v.apiURL(domain)
	headers := map[string]string{"Content-Type": "application/json"}
	page, err := utils.RequestWebPage(url, nil, headers, "", "")
	if err != nil {
		v.Config().Log.Printf("%s: %s: %v", v.String(), url, err)
		return
	}

	// Extract the subdomain names from the results
	var m struct {
		ResponseCode int      `json:"response_code"`
		Message      string   `json:"verbose_msg"`
		Subdomains   []string `json:"subdomains"`
		Resolutions  []struct {
			IP string `json:"ip_address"`
		} `json:"resolutions"`
	}
	if err := json.Unmarshal([]byte(page), &m); err != nil {
		return
	}

	if m.ResponseCode != 1 {
		v.Config().Log.Printf("%s: %s: Response code %d: %s", v.String(), url, m.ResponseCode, m.Message)
		return
	}

	v.SetActive()
	re := v.Config().DomainRegex(domain)
	for _, sub := range m.Subdomains {
		s := strings.ToLower(sub)

		if !re.MatchString(s) {
			continue
		}

		v.Bus().Publish(core.NewNameTopic, &core.Request{
			Name:   s,
			Domain: domain,
			Tag:    v.SourceType,
			Source: v.String(),
		})
	}

	for _, res := range m.Resolutions {
		v.Bus().Publish(core.NewAddrTopic, &core.Request{
			Address: res.IP,
			Domain:  domain,
			Tag:     v.SourceType,
			Source:  v.String(),
		})
	}
}

func (v *VirusTotal) apiURL(domain string) string {
	u, _ := url.Parse("https://www.virustotal.com/vtapi/v2/domain/report")
	u.RawQuery = url.Values{"apikey": {v.API.Key}, "domain": {domain}}.Encode()

	return u.String()
}

func (v *VirusTotal) regularQuery(domain string) {
	url := v.getURL(domain)
	headers := map[string]string{"Content-Type": "application/json"}
	page, err := utils.RequestWebPage(url, nil, headers, "", "")
	if err != nil {
		v.Config().Log.Printf("%s: %s: %v", v.String(), url, err)
		return
	}

	// Extract the subdomain names from the results
	var m struct {
		Data []struct {
			ID   string `json:"id"`
			Type string `json:"type"`
		} `json:"data"`
	}
	if err := json.Unmarshal([]byte(page), &m); err != nil {
		return
	}

	v.SetActive()
	re := v.Config().DomainRegex(domain)
	for _, data := range m.Data {
		if data.Type != "domain" || !re.MatchString(data.ID) {
			continue
		}

		v.Bus().Publish(core.NewNameTopic, &core.Request{
			Name:   data.ID,
			Domain: domain,
			Tag:    v.SourceType,
			Source: v.String(),
		})
	}
}

func (v *VirusTotal) getURL(domain string) string {
	format := "https://www.virustotal.com/ui/domains/%s/subdomains?limit=40"

	return fmt.Sprintf(format, domain)
}
<|endoftext|>


<commit_before>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015, 2016 Minio, Inc.
 *
 * 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 minio

import (
	"bytes"
	"encoding/hex"
	"encoding/xml"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strconv"
	"strings"
)

// Comprehensive put object operation involving multipart resumable uploads.
//
// Following code handles these types of readers.
//
//  - *os.File
//  - *minio.Object
//  - Any reader which has a method 'ReadAt()'
//
// If we exhaust all the known types, code proceeds to use stream as
// is where each part is re-downloaded, checksummed and verified
// before upload.
func (c Client) putObjectMultipart(bucketName, objectName string, reader io.Reader, size int64, contentType string, progress io.Reader) (n int64, err error) {
	if size > 0 && size > minPartSize {
		// Verify if reader is *os.File, then use file system functionalities.
		if isFile(reader) {
			return c.putObjectMultipartFromFile(bucketName, objectName, reader.(*os.File), size, contentType, progress)
		}
		// Verify if reader is *minio.Object or io.ReaderAt.
		// NOTE: Verification of object is kept for a specific purpose
		// while it is going to be duck typed similar to io.ReaderAt.
		// It is to indicate that *minio.Object implements io.ReaderAt.
		// and such a functionality is used in the subsequent code
		// path.
		if isObject(reader) || isReadAt(reader) {
			return c.putObjectMultipartFromReadAt(bucketName, objectName, reader.(io.ReaderAt), size, contentType, progress)
		}
	}
	// For any other data size and reader type we do generic multipart
	// approach by staging data in temporary files and uploading them.
	return c.putObjectMultipartStream(bucketName, objectName, reader, size, contentType, progress)
}

// putObjectStream uploads files bigger than 5MiB, and also supports
// special case where size is unknown i.e '-1'.
func (c Client) putObjectMultipartStream(bucketName, objectName string, reader io.Reader, size int64, contentType string, progress io.Reader) (n int64, err error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return 0, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return 0, err
	}

	// Total data read and written to server. should be equal to 'size' at the end of the call.
	var totalUploadedSize int64

	// Complete multipart upload.
	var complMultipartUpload completeMultipartUpload

	// A map of all previously uploaded parts.
	var partsInfo = make(map[int]objectPart)

	// getUploadID for an object, initiates a new multipart request
	// if it cannot find any previously partially uploaded object.
	uploadID, isNew, err := c.getUploadID(bucketName, objectName, contentType)
	if err != nil {
		return 0, err
	}

	// If This session is a continuation of a previous session fetch all
	// previously uploaded parts info.
	if !isNew {
		// Fetch previously uploaded parts and maximum part size.
		partsInfo, err = c.listObjectParts(bucketName, objectName, uploadID)
		if err != nil {
			return 0, err
		}
	}

	// Calculate the optimal parts info for a given size.
	totalPartsCount, partSize, _, err := optimalPartInfo(size)
	if err != nil {
		return 0, err
	}

	// Part number always starts with '1'.
	partNumber := 1

	// Initialize a temporary buffer.
	tmpBuffer := new(bytes.Buffer)

	for partNumber <= totalPartsCount {
		// Calculates MD5 and SHA256 sum while copying partSize bytes
		// into tmpBuffer.
		md5Sum, sha256Sum, prtSize, rErr := c.hashCopyN(tmpBuffer, reader, partSize)
		if rErr != nil {
			if rErr != io.EOF {
				return 0, rErr
			}
		}

		var reader io.Reader
		// Update progress reader appropriately to the latest offset
		// as we read from the source.
		reader = newHook(tmpBuffer, progress)

		// Verify if part should be uploaded.
		if shouldUploadPart(objectPart{
			ETag:       hex.EncodeToString(md5Sum),
			PartNumber: partNumber,
			Size:       prtSize,
		}, partsInfo) {
			// Proceed to upload the part.
			var objPart objectPart
			objPart, err = c.uploadPart(bucketName, objectName, uploadID, reader, partNumber, md5Sum, sha256Sum, prtSize)
			if err != nil {
				// Reset the temporary buffer upon any error.
				tmpBuffer.Reset()
				return totalUploadedSize, err
			}
			// Save successfully uploaded part metadata.
			partsInfo[partNumber] = objPart
		} else {
			// Update the progress reader for the skipped part.
			if progress != nil {
				if _, err = io.CopyN(ioutil.Discard, progress, prtSize); err != nil {
					return totalUploadedSize, err
				}
			}
		}

		// Reset the temporary buffer.
		tmpBuffer.Reset()

		// Save successfully uploaded size.
		totalUploadedSize += prtSize

		// For unknown size, Read EOF we break away.
		// We do not have to upload till totalPartsCount.
		if size < 0 && rErr == io.EOF {
			break
		}

		// Increment part number.
		partNumber++
	}

	// Verify if we uploaded all the data.
	if size > 0 {
		if totalUploadedSize != size {
			return totalUploadedSize, ErrUnexpectedEOF(totalUploadedSize, size, bucketName, objectName)
		}
	}

	// Loop over uploaded parts to save them in a Parts array before completing the multipart request.
	for _, part := range partsInfo {
		var complPart completePart
		complPart.ETag = part.ETag
		complPart.PartNumber = part.PartNumber
		complMultipartUpload.Parts = append(complMultipartUpload.Parts, complPart)
	}

	if size > 0 {
		// Verify if totalPartsCount is not equal to total list of parts.
		if totalPartsCount != len(complMultipartUpload.Parts) {
			return totalUploadedSize, ErrInvalidParts(partNumber, len(complMultipartUpload.Parts))
		}
	}

	// Sort all completed parts.
	sort.Sort(completedParts(complMultipartUpload.Parts))
	_, err = c.completeMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload)
	if err != nil {
		return totalUploadedSize, err
	}

	// Return final size.
	return totalUploadedSize, nil
}

// initiateMultipartUpload - Initiates a multipart upload and returns an upload ID.
func (c Client) initiateMultipartUpload(bucketName, objectName, contentType string) (initiateMultipartUploadResult, error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return initiateMultipartUploadResult{}, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return initiateMultipartUploadResult{}, err
	}

	// Initialize url queries.
	urlValues := make(url.Values)
	urlValues.Set("uploads", "")

	if contentType == "" {
		contentType = "application/octet-stream"
	}

	// Set ContentType header.
	customHeader := make(http.Header)
	customHeader.Set("Content-Type", contentType)

	reqMetadata := requestMetadata{
		bucketName:   bucketName,
		objectName:   objectName,
		queryValues:  urlValues,
		customHeader: customHeader,
	}

	// Execute POST on an objectName to initiate multipart upload.
	resp, err := c.executeMethod("POST", reqMetadata)
	defer closeResponse(resp)
	if err != nil {
		return initiateMultipartUploadResult{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return initiateMultipartUploadResult{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}
	// Decode xml for new multipart upload.
	initiateMultipartUploadResult := initiateMultipartUploadResult{}
	err = xmlDecoder(resp.Body, &initiateMultipartUploadResult)
	if err != nil {
		return initiateMultipartUploadResult, err
	}
	return initiateMultipartUploadResult, nil
}

// uploadPart - Uploads a part in a multipart upload.
func (c Client) uploadPart(bucketName, objectName, uploadID string, reader io.Reader, partNumber int, md5Sum, sha256Sum []byte, size int64) (objectPart, error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return objectPart{}, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return objectPart{}, err
	}
	if size > maxPartSize {
		return objectPart{}, ErrEntityTooLarge(size, maxPartSize, bucketName, objectName)
	}
	if size <= -1 {
		return objectPart{}, ErrEntityTooSmall(size, bucketName, objectName)
	}
	if partNumber <= 0 {
		return objectPart{}, ErrInvalidArgument("Part number cannot be negative or equal to zero.")
	}
	if uploadID == "" {
		return objectPart{}, ErrInvalidArgument("UploadID cannot be empty.")
	}

	// Get resources properly escaped and lined up before using them in http request.
	urlValues := make(url.Values)
	// Set part number.
	urlValues.Set("partNumber", strconv.Itoa(partNumber))
	// Set upload id.
	urlValues.Set("uploadId", uploadID)

	reqMetadata := requestMetadata{
		bucketName:         bucketName,
		objectName:         objectName,
		queryValues:        urlValues,
		contentBody:        reader,
		contentLength:      size,
		contentMD5Bytes:    md5Sum,
		contentSHA256Bytes: sha256Sum,
	}

	// Execute PUT on each part.
	resp, err := c.executeMethod("PUT", reqMetadata)
	defer closeResponse(resp)
	if err != nil {
		return objectPart{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return objectPart{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}
	// Once successfully uploaded, return completed part.
	objPart := objectPart{}
	objPart.Size = size
	objPart.PartNumber = partNumber
	// Trim off the odd double quotes from ETag in the beginning and end.
	objPart.ETag = strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
	objPart.ETag = strings.TrimSuffix(objPart.ETag, "\"")
	return objPart, nil
}

// completeMultipartUpload - Completes a multipart upload by assembling previously uploaded parts.
func (c Client) completeMultipartUpload(bucketName, objectName, uploadID string, complete completeMultipartUpload) (completeMultipartUploadResult, error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return completeMultipartUploadResult{}, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return completeMultipartUploadResult{}, err
	}

	// Initialize url queries.
	urlValues := make(url.Values)
	urlValues.Set("uploadId", uploadID)

	// Marshal complete multipart body.
	completeMultipartUploadBytes, err := xml.Marshal(complete)
	if err != nil {
		return completeMultipartUploadResult{}, err
	}

	// Instantiate all the complete multipart buffer.
	completeMultipartUploadBuffer := bytes.NewReader(completeMultipartUploadBytes)
	reqMetadata := requestMetadata{
		bucketName:         bucketName,
		objectName:         objectName,
		queryValues:        urlValues,
		contentBody:        completeMultipartUploadBuffer,
		contentLength:      int64(len(completeMultipartUploadBytes)),
		contentSHA256Bytes: sum256(completeMultipartUploadBytes),
	}

	// Execute POST to complete multipart upload for an objectName.
	resp, err := c.executeMethod("POST", reqMetadata)
	defer closeResponse(resp)
	if err != nil {
		return completeMultipartUploadResult{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return completeMultipartUploadResult{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}
	// Decode completed multipart upload response on success.
	completeMultipartUploadResult := completeMultipartUploadResult{}
	err = xmlDecoder(resp.Body, &completeMultipartUploadResult)
	if err != nil {
		return completeMultipartUploadResult, err
	}
	return completeMultipartUploadResult, nil
}
<commit_msg>CompleteMultipartUpload API may contain error response in resp.Body (#419)<commit_after>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015, 2016 Minio, Inc.
 *
 * 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 minio

import (
	"bytes"
	"encoding/hex"
	"encoding/xml"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strconv"
	"strings"
)

// Comprehensive put object operation involving multipart resumable uploads.
//
// Following code handles these types of readers.
//
//  - *os.File
//  - *minio.Object
//  - Any reader which has a method 'ReadAt()'
//
// If we exhaust all the known types, code proceeds to use stream as
// is where each part is re-downloaded, checksummed and verified
// before upload.
func (c Client) putObjectMultipart(bucketName, objectName string, reader io.Reader, size int64, contentType string, progress io.Reader) (n int64, err error) {
	if size > 0 && size > minPartSize {
		// Verify if reader is *os.File, then use file system functionalities.
		if isFile(reader) {
			return c.putObjectMultipartFromFile(bucketName, objectName, reader.(*os.File), size, contentType, progress)
		}
		// Verify if reader is *minio.Object or io.ReaderAt.
		// NOTE: Verification of object is kept for a specific purpose
		// while it is going to be duck typed similar to io.ReaderAt.
		// It is to indicate that *minio.Object implements io.ReaderAt.
		// and such a functionality is used in the subsequent code
		// path.
		if isObject(reader) || isReadAt(reader) {
			return c.putObjectMultipartFromReadAt(bucketName, objectName, reader.(io.ReaderAt), size, contentType, progress)
		}
	}
	// For any other data size and reader type we do generic multipart
	// approach by staging data in temporary files and uploading them.
	return c.putObjectMultipartStream(bucketName, objectName, reader, size, contentType, progress)
}

// putObjectStream uploads files bigger than 5MiB, and also supports
// special case where size is unknown i.e '-1'.
func (c Client) putObjectMultipartStream(bucketName, objectName string, reader io.Reader, size int64, contentType string, progress io.Reader) (n int64, err error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return 0, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return 0, err
	}

	// Total data read and written to server. should be equal to 'size' at the end of the call.
	var totalUploadedSize int64

	// Complete multipart upload.
	var complMultipartUpload completeMultipartUpload

	// A map of all previously uploaded parts.
	var partsInfo = make(map[int]objectPart)

	// getUploadID for an object, initiates a new multipart request
	// if it cannot find any previously partially uploaded object.
	uploadID, isNew, err := c.getUploadID(bucketName, objectName, contentType)
	if err != nil {
		return 0, err
	}

	// If This session is a continuation of a previous session fetch all
	// previously uploaded parts info.
	if !isNew {
		// Fetch previously uploaded parts and maximum part size.
		partsInfo, err = c.listObjectParts(bucketName, objectName, uploadID)
		if err != nil {
			return 0, err
		}
	}

	// Calculate the optimal parts info for a given size.
	totalPartsCount, partSize, _, err := optimalPartInfo(size)
	if err != nil {
		return 0, err
	}

	// Part number always starts with '1'.
	partNumber := 1

	// Initialize a temporary buffer.
	tmpBuffer := new(bytes.Buffer)

	for partNumber <= totalPartsCount {
		// Calculates MD5 and SHA256 sum while copying partSize bytes
		// into tmpBuffer.
		md5Sum, sha256Sum, prtSize, rErr := c.hashCopyN(tmpBuffer, reader, partSize)
		if rErr != nil {
			if rErr != io.EOF {
				return 0, rErr
			}
		}

		var reader io.Reader
		// Update progress reader appropriately to the latest offset
		// as we read from the source.
		reader = newHook(tmpBuffer, progress)

		// Verify if part should be uploaded.
		if shouldUploadPart(objectPart{
			ETag:       hex.EncodeToString(md5Sum),
			PartNumber: partNumber,
			Size:       prtSize,
		}, partsInfo) {
			// Proceed to upload the part.
			var objPart objectPart
			objPart, err = c.uploadPart(bucketName, objectName, uploadID, reader, partNumber, md5Sum, sha256Sum, prtSize)
			if err != nil {
				// Reset the temporary buffer upon any error.
				tmpBuffer.Reset()
				return totalUploadedSize, err
			}
			// Save successfully uploaded part metadata.
			partsInfo[partNumber] = objPart
		} else {
			// Update the progress reader for the skipped part.
			if progress != nil {
				if _, err = io.CopyN(ioutil.Discard, progress, prtSize); err != nil {
					return totalUploadedSize, err
				}
			}
		}

		// Reset the temporary buffer.
		tmpBuffer.Reset()

		// Save successfully uploaded size.
		totalUploadedSize += prtSize

		// For unknown size, Read EOF we break away.
		// We do not have to upload till totalPartsCount.
		if size < 0 && rErr == io.EOF {
			break
		}

		// Increment part number.
		partNumber++
	}

	// Verify if we uploaded all the data.
	if size > 0 {
		if totalUploadedSize != size {
			return totalUploadedSize, ErrUnexpectedEOF(totalUploadedSize, size, bucketName, objectName)
		}
	}

	// Loop over uploaded parts to save them in a Parts array before completing the multipart request.
	for _, part := range partsInfo {
		var complPart completePart
		complPart.ETag = part.ETag
		complPart.PartNumber = part.PartNumber
		complMultipartUpload.Parts = append(complMultipartUpload.Parts, complPart)
	}

	if size > 0 {
		// Verify if totalPartsCount is not equal to total list of parts.
		if totalPartsCount != len(complMultipartUpload.Parts) {
			return totalUploadedSize, ErrInvalidParts(partNumber, len(complMultipartUpload.Parts))
		}
	}

	// Sort all completed parts.
	sort.Sort(completedParts(complMultipartUpload.Parts))
	_, err = c.completeMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload)
	if err != nil {
		return totalUploadedSize, err
	}

	// Return final size.
	return totalUploadedSize, nil
}

// initiateMultipartUpload - Initiates a multipart upload and returns an upload ID.
func (c Client) initiateMultipartUpload(bucketName, objectName, contentType string) (initiateMultipartUploadResult, error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return initiateMultipartUploadResult{}, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return initiateMultipartUploadResult{}, err
	}

	// Initialize url queries.
	urlValues := make(url.Values)
	urlValues.Set("uploads", "")

	if contentType == "" {
		contentType = "application/octet-stream"
	}

	// Set ContentType header.
	customHeader := make(http.Header)
	customHeader.Set("Content-Type", contentType)

	reqMetadata := requestMetadata{
		bucketName:   bucketName,
		objectName:   objectName,
		queryValues:  urlValues,
		customHeader: customHeader,
	}

	// Execute POST on an objectName to initiate multipart upload.
	resp, err := c.executeMethod("POST", reqMetadata)
	defer closeResponse(resp)
	if err != nil {
		return initiateMultipartUploadResult{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return initiateMultipartUploadResult{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}
	// Decode xml for new multipart upload.
	initiateMultipartUploadResult := initiateMultipartUploadResult{}
	err = xmlDecoder(resp.Body, &initiateMultipartUploadResult)
	if err != nil {
		return initiateMultipartUploadResult, err
	}
	return initiateMultipartUploadResult, nil
}

// uploadPart - Uploads a part in a multipart upload.
func (c Client) uploadPart(bucketName, objectName, uploadID string, reader io.Reader, partNumber int, md5Sum, sha256Sum []byte, size int64) (objectPart, error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return objectPart{}, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return objectPart{}, err
	}
	if size > maxPartSize {
		return objectPart{}, ErrEntityTooLarge(size, maxPartSize, bucketName, objectName)
	}
	if size <= -1 {
		return objectPart{}, ErrEntityTooSmall(size, bucketName, objectName)
	}
	if partNumber <= 0 {
		return objectPart{}, ErrInvalidArgument("Part number cannot be negative or equal to zero.")
	}
	if uploadID == "" {
		return objectPart{}, ErrInvalidArgument("UploadID cannot be empty.")
	}

	// Get resources properly escaped and lined up before using them in http request.
	urlValues := make(url.Values)
	// Set part number.
	urlValues.Set("partNumber", strconv.Itoa(partNumber))
	// Set upload id.
	urlValues.Set("uploadId", uploadID)

	reqMetadata := requestMetadata{
		bucketName:         bucketName,
		objectName:         objectName,
		queryValues:        urlValues,
		contentBody:        reader,
		contentLength:      size,
		contentMD5Bytes:    md5Sum,
		contentSHA256Bytes: sha256Sum,
	}

	// Execute PUT on each part.
	resp, err := c.executeMethod("PUT", reqMetadata)
	defer closeResponse(resp)
	if err != nil {
		return objectPart{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return objectPart{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}
	// Once successfully uploaded, return completed part.
	objPart := objectPart{}
	objPart.Size = size
	objPart.PartNumber = partNumber
	// Trim off the odd double quotes from ETag in the beginning and end.
	objPart.ETag = strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
	objPart.ETag = strings.TrimSuffix(objPart.ETag, "\"")
	return objPart, nil
}

// completeMultipartUpload - Completes a multipart upload by assembling previously uploaded parts.
func (c Client) completeMultipartUpload(bucketName, objectName, uploadID string, complete completeMultipartUpload) (completeMultipartUploadResult, error) {
	// Input validation.
	if err := isValidBucketName(bucketName); err != nil {
		return completeMultipartUploadResult{}, err
	}
	if err := isValidObjectName(objectName); err != nil {
		return completeMultipartUploadResult{}, err
	}

	// Initialize url queries.
	urlValues := make(url.Values)
	urlValues.Set("uploadId", uploadID)

	// Marshal complete multipart body.
	completeMultipartUploadBytes, err := xml.Marshal(complete)
	if err != nil {
		return completeMultipartUploadResult{}, err
	}

	// Instantiate all the complete multipart buffer.
	completeMultipartUploadBuffer := bytes.NewReader(completeMultipartUploadBytes)
	reqMetadata := requestMetadata{
		bucketName:         bucketName,
		objectName:         objectName,
		queryValues:        urlValues,
		contentBody:        completeMultipartUploadBuffer,
		contentLength:      int64(len(completeMultipartUploadBytes)),
		contentSHA256Bytes: sum256(completeMultipartUploadBytes),
	}

	// Execute POST to complete multipart upload for an objectName.
	resp, err := c.executeMethod("POST", reqMetadata)
	defer closeResponse(resp)
	if err != nil {
		return completeMultipartUploadResult{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return completeMultipartUploadResult{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}

	// Read resp.Body into a []bytes to parse for Error response inside the body
	var b []byte
	b, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return completeMultipartUploadResult{}, err
	}
	// Decode completed multipart upload response on success.
	completeMultipartUploadResult := completeMultipartUploadResult{}
	err = xmlDecoder(bytes.NewReader(b), &completeMultipartUploadResult)
	if err != nil {
		// xml parsing failure due to presence an ill-formed xml fragment
		return completeMultipartUploadResult, err
	} else if completeMultipartUploadResult.Bucket == "" {
		// xml's Decode method ignores well-formed xml that don't apply to the type of value supplied.
		// In this case, it would leave completeMultipartUploadResult with the corresponding zero-values
		// of the members.

		// Decode completed multipart upload response on failure
		completeMultipartUploadErr := ErrorResponse{}
		err = xmlDecoder(bytes.NewReader(b), &completeMultipartUploadErr)
		if err != nil {
			// xml parsing failure due to presence an ill-formed xml fragment
			return completeMultipartUploadResult, err
		}
		return completeMultipartUploadResult, completeMultipartUploadErr
	}
	return completeMultipartUploadResult, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package api_test

import (
	"fmt"

	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/api"
	apitesting "github.com/juju/juju/api/testing"
	"github.com/juju/juju/testcharms"
)

var _ = gc.Suite(&clientMacaroonSuite{})

// clientMacaroonSuite tests that Client endpoints that are
// independent of the RPC-based API work with
// macaroon authentication.
type clientMacaroonSuite struct {
	apitesting.MacaroonSuite
	client    *api.Client
	cookieJar *apitesting.ClearableCookieJar
}

func (s *clientMacaroonSuite) SetUpTest(c *gc.C) {
	s.MacaroonSuite.SetUpTest(c)
	s.AddModelUser(c, "testuser@somewhere")
	s.cookieJar = apitesting.NewClearableCookieJar()
	s.DischargerLogin = func() string { return "testuser@somewhere" }
	s.client = s.OpenAPI(c, nil, s.cookieJar).Client()

	// Even though we've logged into the API, we want
	// the tests below to exercise the discharging logic
	// so we clear the cookies.
	s.cookieJar.Clear()
}

func (s *clientMacaroonSuite) TearDownTest(c *gc.C) {
	s.client.Close()
	s.MacaroonSuite.TearDownTest(c)
}

func (s *clientMacaroonSuite) TestAddLocalCharmWithFailedDischarge(c *gc.C) {
	s.DischargerLogin = func() string { return "" }
	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
	curl := charm.MustParseURL(
		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
	)
	savedURL, err := s.client.AddLocalCharm(curl, charmArchive)
	c.Assert(err, gc.ErrorMatches, `POST https://.*/model/deadbeef-0bad-400d-8000-4b1d0d06f00d/charms\?series=quantal: cannot get discharge from "https://.*": third party refused discharge: cannot discharge: login denied by discharger`)
	c.Assert(savedURL, gc.IsNil)
}

func (s *clientMacaroonSuite) TestAddLocalCharmSuccess(c *gc.C) {
	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
	curl := charm.MustParseURL(
		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
	)
	// Upload an archive with its original revision.
	savedURL, err := s.client.AddLocalCharm(curl, charmArchive)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(savedURL.String(), gc.Equals, curl.String())
}

func (s *clientMacaroonSuite) TestAddLocalCharmUnauthorized(c *gc.C) {
	s.DischargerLogin = func() string { return "baduser" }
	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
	curl := charm.MustParseURL(
		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
	)
	// Upload an archive with its original revision.
	_, err := s.client.AddLocalCharm(curl, charmArchive)
	c.Assert(err, gc.ErrorMatches, `POST https://.*/model/deadbeef-0bad-400d-8000-4b1d0d06f00d/charms\?series=quantal: invalid entity name or password`)
}
<commit_msg>api: Disabled flaky macaroon test TestAddLocalCharmSuccess<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package api_test

import (
	"fmt"

	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/api"
	apitesting "github.com/juju/juju/api/testing"
	"github.com/juju/juju/testcharms"
)

var _ = gc.Suite(&clientMacaroonSuite{})

// clientMacaroonSuite tests that Client endpoints that are
// independent of the RPC-based API work with
// macaroon authentication.
type clientMacaroonSuite struct {
	apitesting.MacaroonSuite
	client    *api.Client
	cookieJar *apitesting.ClearableCookieJar
}

func (s *clientMacaroonSuite) SetUpTest(c *gc.C) {
	s.MacaroonSuite.SetUpTest(c)
	s.AddModelUser(c, "testuser@somewhere")
	s.cookieJar = apitesting.NewClearableCookieJar()
	s.DischargerLogin = func() string { return "testuser@somewhere" }
	s.client = s.OpenAPI(c, nil, s.cookieJar).Client()

	// Even though we've logged into the API, we want
	// the tests below to exercise the discharging logic
	// so we clear the cookies.
	s.cookieJar.Clear()
}

func (s *clientMacaroonSuite) TearDownTest(c *gc.C) {
	s.client.Close()
	s.MacaroonSuite.TearDownTest(c)
}

func (s *clientMacaroonSuite) TestAddLocalCharmWithFailedDischarge(c *gc.C) {
	s.DischargerLogin = func() string { return "" }
	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
	curl := charm.MustParseURL(
		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
	)
	savedURL, err := s.client.AddLocalCharm(curl, charmArchive)
	c.Assert(err, gc.ErrorMatches, `POST https://.*/model/deadbeef-0bad-400d-8000-4b1d0d06f00d/charms\?series=quantal: cannot get discharge from "https://.*": third party refused discharge: cannot discharge: login denied by discharger`)
	c.Assert(savedURL, gc.IsNil)
}

func (s *clientMacaroonSuite) TestAddLocalCharmSuccess(c *gc.C) {
	c.Skip("dimitern: disabled as flaky - see http://pad.lv/1560511 as possible root cause")

	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
	curl := charm.MustParseURL(
		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
	)
	// Upload an archive with its original revision.
	savedURL, err := s.client.AddLocalCharm(curl, charmArchive)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(savedURL.String(), gc.Equals, curl.String())
}

func (s *clientMacaroonSuite) TestAddLocalCharmUnauthorized(c *gc.C) {
	s.DischargerLogin = func() string { return "baduser" }
	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
	curl := charm.MustParseURL(
		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
	)
	// Upload an archive with its original revision.
	_, err := s.client.AddLocalCharm(curl, charmArchive)
	c.Assert(err, gc.ErrorMatches, `POST https://.*/model/deadbeef-0bad-400d-8000-4b1d0d06f00d/charms\?series=quantal: invalid entity name or password`)
}
<|endoftext|>


<commit_before>package omxplayer

import (
	log "github.com/Sirupsen/logrus"
	"github.com/guelfey/go.dbus"
)

const (
	ifaceProps     = "org.freedesktop.DBus.Properties"
	ifaceOmxRoot   = ifaceMpris
	ifaceOmxPlayer = ifaceOmxRoot + ".Player"

	cmdQuit                 = ifaceOmxRoot + ".Quit"
	propCanQuit             = ifaceProps + ".CanQuit"
	propFullscreen          = ifaceProps + ".Fullscreen"
	propCanSetFullscreen    = ifaceProps + ".CanSetFullscreen"
	propCanRaise            = ifaceProps + ".CanRaise"
	propHasTrackList        = ifaceProps + ".HasTrackList"
	propIdentity            = ifaceProps + ".Identity"
	propSupportedUriSchemes = ifaceProps + ".SupportedUriSchemes"
	propSupportedMimeTypes  = ifaceProps + ".SupportedMimeTypes"
	propCanGoNext           = ifaceProps + ".CanGoNext"
	propCanGoPrevious       = ifaceProps + ".CanGoPrevious"
	propCanSeek             = ifaceProps + ".CanSeek"
	propCanControl          = ifaceProps + ".CanControl"
	propCanPlay             = ifaceProps + ".CanPlay"
	propCanPause            = ifaceProps + ".CanPause"
	cmdNext                 = ifaceOmxPlayer + ".Next"
	cmdPrevious             = ifaceOmxPlayer + ".Previous"
	cmdPause                = ifaceOmxPlayer + ".Pause"
	cmdPlayPause            = ifaceOmxPlayer + ".PlayPause"
	cmdStop                 = ifaceOmxPlayer + ".Stop"
	cmdSeek                 = ifaceOmxPlayer + ".Seek"
	cmdSetPosition          = ifaceOmxPlayer + ".SetPosition"
	propPlaybackStatus      = ifaceProps + ".PlaybackStatus"
	cmdVolume               = ifaceProps + ".Volume"
	cmdMute                 = ifaceProps + ".Mute"
	cmdUnmute               = ifaceProps + ".Unmute"
	propPosition            = ifaceProps + ".Position"
	propAspect              = ifaceProps + ".Aspect"
	propVideoStreamCount    = ifaceProps + ".VideoStreamCount"
	propResWidth            = ifaceProps + ".ResWidth"
	propResHeight           = ifaceProps + ".ResHeight"
	propDuration            = ifaceProps + ".Duration"
	propMinimumRate         = ifaceProps + ".MinimumRate"
	propMaximumRate         = ifaceProps + ".MaximumRate"
	cmdListSubtitles        = ifaceOmxPlayer + ".ListSubtitles"
	cmdHideVideo            = ifaceOmxPlayer + ".HideVideo"
	cmdUnHideVideo          = ifaceOmxPlayer + ".UnHideVideo"
	cmdListAudio            = ifaceOmxPlayer + ".ListAudio"
	cmdListVideo            = ifaceOmxPlayer + ".ListVideo"
	cmdSelectSubtitle       = ifaceOmxPlayer + ".SelectSubtitle"
	cmdSelectAudio          = ifaceOmxPlayer + ".SelectAudio"
	cmdShowSubtitles        = ifaceOmxPlayer + ".ShowSubtitles"
	cmdHideSubtitles        = ifaceOmxPlayer + ".HideSubtitles"
	cmdAction               = ifaceOmxPlayer + ".Action"
)

type Player struct {
	bus *dbus.Object
}

func (p *Player) Quit() error {
	return dbusCall(p.bus, cmdQuit)
}

func (p *Player) CanQuit() (bool, error) {
	return dbusGetBool(p.bus, propCanQuit)
}

func (p *Player) Fullscreen() (bool, error) {
	return dbusGetBool(p.bus, propFullscreen)
}

func (p *Player) CanSetFullscreen() (bool, error) {
	return dbusGetBool(p.bus, propCanSetFullscreen)
}

func (p *Player) CanRaise() (bool, error) {
	return dbusGetBool(p.bus, propCanRaise)
}

func (p *Player) HasTrackList() (bool, error) {
	return dbusGetBool(p.bus, propHasTrackList)
}

func (p *Player) Identity() (string, error) {
	return dbusGetString(p.bus, propIdentity)
}

func (p *Player) SupportedUriSchemes() ([]string, error) {
	return dbusGetStringArray(p.bus, propSupportedUriSchemes)
}

func (p *Player) SupportedMimeTypes() ([]string, error) {
	return dbusGetStringArray(p.bus, propSupportedMimeTypes)
}

func (p *Player) CanGoNext() (bool, error) {
	return dbusGetBool(p.bus, propCanGoNext)
}

func (p *Player) CanGoPrevious() (bool, error) {
	return dbusGetBool(p.bus, propCanGoPrevious)
}

func (p *Player) CanSeek() (bool, error) {
	return dbusGetBool(p.bus, cmdSeek)
}

func (p *Player) CanControl() (bool, error) {
	return dbusGetBool(p.bus, propCanControl)
}

func (p *Player) CanPlay() (bool, error) {
	return dbusGetBool(p.bus, propCanPlay)
}

func (p *Player) CanPause() (bool, error) {
	return dbusGetBool(p.bus, propCanPause)
}

func (p *Player) Next() error {
	return dbusCall(p.bus, cmdNext)
}

func (p *Player) Previous() error {
	return dbusCall(p.bus, cmdPrevious)
}

func (p *Player) Pause() error {
	return dbusCall(p.bus, cmdPause)
}

func (p *Player) PlayPause() error {
	return dbusCall(p.bus, cmdPlayPause)
}

func (p *Player) Stop() error {
	return dbusCall(p.bus, cmdStop)
}

func (p *Player) Seek(amount int64) (int64, error) {
	log.WithFields(log.Fields{
		"path":        cmdSeek,
		"paramAmount": amount,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSeek, 0, amount)
	if call.Err != nil {
		return 0, call.Err
	}
	return call.Body[0].(int64), nil
}

func (p *Player) SetPosition(path string, position int64) (int64, error) {
	log.WithFields(log.Fields{
		"path":          cmdSetPosition,
		"paramPath":     path,
		"paramPosition": position,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSetPosition, 0, path, position)
	if call.Err != nil {
		return 0, call.Err
	}
	return call.Body[0].(int64), nil
}

func (p *Player) PlaybackStatus() (string, error) {
	return dbusGetString(p.bus, propPlaybackStatus)
}

func (p *Player) Volume(volume ...float64) (float64, error) {
	log.WithFields(log.Fields{
		"path":        cmdVolume,
		"paramVolume": volume,
	}).Debug("omxplayer: dbus call")
	if len(volume) == 0 {
		return dbusGetFloat64(p.bus, cmdVolume)
	}
	call := p.bus.Call(cmdVolume, 0, volume[0])
	if call.Err != nil {
		return 0, call.Err
	}
	return call.Body[0].(float64), nil
}

func (p *Player) Mute() error {
	return dbusCall(p.bus, cmdMute)
}

func (p *Player) Unmute() error {
	return dbusCall(p.bus, cmdUnmute)
}

func (p *Player) Position() (int64, error) {
	return dbusGetInt64(p.bus, propPosition)
}

func (p *Player) Aspect() (float64, error) {
	return dbusGetFloat64(p.bus, propAspect)
}

func (p *Player) VideoStreamCount() (int64, error) {
	return dbusGetInt64(p.bus, propVideoStreamCount)
}

func (p *Player) ResWidth() (int64, error) {
	return dbusGetInt64(p.bus, propResWidth)
}

func (p *Player) ResHeight() (int64, error) {
	return dbusGetInt64(p.bus, propResHeight)
}

func (p *Player) Duration() (int64, error) {
	return dbusGetInt64(p.bus, propDuration)
}

func (p *Player) MinimumRate() (float64, error) {
	return dbusGetFloat64(p.bus, propMinimumRate)
}

func (p *Player) MaximumRate() (float64, error) {
	return dbusGetFloat64(p.bus, propMaximumRate)
}

func (p *Player) ListSubtitles() ([]string, error) {
	return dbusGetStringArray(p.bus, cmdListSubtitles)
}

func (p *Player) HideVideo() error {
	return dbusCall(p.bus, cmdHideVideo)
}

func (p *Player) UnHideVideo() error {
	return dbusCall(p.bus, cmdUnHideVideo)
}

func (p *Player) ListAudio() ([]string, error) {
	return dbusGetStringArray(p.bus, cmdListAudio)
}

func (p *Player) ListVideo() ([]string, error) {
	return dbusGetStringArray(p.bus, cmdListVideo)
}

func (p *Player) SelectSubtitle(index int32) (bool, error) {
	log.WithFields(log.Fields{
		"path":       cmdSelectSubtitle,
		"paramIndex": index,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSelectSubtitle, 0, index)
	if call.Err != nil {
		return false, call.Err
	}
	return call.Body[0].(bool), nil
}

func (p *Player) SelectAudio(index int32) (bool, error) {
	log.WithFields(log.Fields{
		"path":       cmdSelectAudio,
		"paramIndex": index,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSelectAudio, 0, index)
	if call.Err != nil {
		return false, call.Err
	}
	return call.Body[0].(bool), nil
}

func (p *Player) ShowSubtitles() error {
	return dbusCall(p.bus, cmdShowSubtitles)
}

func (p *Player) HideSubtitles() error {
	return dbusCall(p.bus, cmdHideSubtitles)
}

func (p *Player) Action(action int32) error {
	log.WithFields(log.Fields{
		"path":        cmdAction,
		"paramAction": action,
	}).Debug("omxplayer: dbus call")
	return p.bus.Call(cmdAction, 0, action).Err
}
<commit_msg>Add command and connection to Player struct.<commit_after>package omxplayer

import (
	log "github.com/Sirupsen/logrus"
	"github.com/guelfey/go.dbus"
	"os/exec"
)

const (
	ifaceProps     = "org.freedesktop.DBus.Properties"
	ifaceOmxRoot   = ifaceMpris
	ifaceOmxPlayer = ifaceOmxRoot + ".Player"

	cmdQuit                 = ifaceOmxRoot + ".Quit"
	propCanQuit             = ifaceProps + ".CanQuit"
	propFullscreen          = ifaceProps + ".Fullscreen"
	propCanSetFullscreen    = ifaceProps + ".CanSetFullscreen"
	propCanRaise            = ifaceProps + ".CanRaise"
	propHasTrackList        = ifaceProps + ".HasTrackList"
	propIdentity            = ifaceProps + ".Identity"
	propSupportedUriSchemes = ifaceProps + ".SupportedUriSchemes"
	propSupportedMimeTypes  = ifaceProps + ".SupportedMimeTypes"
	propCanGoNext           = ifaceProps + ".CanGoNext"
	propCanGoPrevious       = ifaceProps + ".CanGoPrevious"
	propCanSeek             = ifaceProps + ".CanSeek"
	propCanControl          = ifaceProps + ".CanControl"
	propCanPlay             = ifaceProps + ".CanPlay"
	propCanPause            = ifaceProps + ".CanPause"
	cmdNext                 = ifaceOmxPlayer + ".Next"
	cmdPrevious             = ifaceOmxPlayer + ".Previous"
	cmdPause                = ifaceOmxPlayer + ".Pause"
	cmdPlayPause            = ifaceOmxPlayer + ".PlayPause"
	cmdStop                 = ifaceOmxPlayer + ".Stop"
	cmdSeek                 = ifaceOmxPlayer + ".Seek"
	cmdSetPosition          = ifaceOmxPlayer + ".SetPosition"
	propPlaybackStatus      = ifaceProps + ".PlaybackStatus"
	cmdVolume               = ifaceProps + ".Volume"
	cmdMute                 = ifaceProps + ".Mute"
	cmdUnmute               = ifaceProps + ".Unmute"
	propPosition            = ifaceProps + ".Position"
	propAspect              = ifaceProps + ".Aspect"
	propVideoStreamCount    = ifaceProps + ".VideoStreamCount"
	propResWidth            = ifaceProps + ".ResWidth"
	propResHeight           = ifaceProps + ".ResHeight"
	propDuration            = ifaceProps + ".Duration"
	propMinimumRate         = ifaceProps + ".MinimumRate"
	propMaximumRate         = ifaceProps + ".MaximumRate"
	cmdListSubtitles        = ifaceOmxPlayer + ".ListSubtitles"
	cmdHideVideo            = ifaceOmxPlayer + ".HideVideo"
	cmdUnHideVideo          = ifaceOmxPlayer + ".UnHideVideo"
	cmdListAudio            = ifaceOmxPlayer + ".ListAudio"
	cmdListVideo            = ifaceOmxPlayer + ".ListVideo"
	cmdSelectSubtitle       = ifaceOmxPlayer + ".SelectSubtitle"
	cmdSelectAudio          = ifaceOmxPlayer + ".SelectAudio"
	cmdShowSubtitles        = ifaceOmxPlayer + ".ShowSubtitles"
	cmdHideSubtitles        = ifaceOmxPlayer + ".HideSubtitles"
	cmdAction               = ifaceOmxPlayer + ".Action"
)

type Player struct {
	command    *exec.Cmd
	connection *dbus.Conn
	bus        *dbus.Object
}

func (p *Player) Quit() error {
	return dbusCall(p.bus, cmdQuit)
}

func (p *Player) CanQuit() (bool, error) {
	return dbusGetBool(p.bus, propCanQuit)
}

func (p *Player) Fullscreen() (bool, error) {
	return dbusGetBool(p.bus, propFullscreen)
}

func (p *Player) CanSetFullscreen() (bool, error) {
	return dbusGetBool(p.bus, propCanSetFullscreen)
}

func (p *Player) CanRaise() (bool, error) {
	return dbusGetBool(p.bus, propCanRaise)
}

func (p *Player) HasTrackList() (bool, error) {
	return dbusGetBool(p.bus, propHasTrackList)
}

func (p *Player) Identity() (string, error) {
	return dbusGetString(p.bus, propIdentity)
}

func (p *Player) SupportedUriSchemes() ([]string, error) {
	return dbusGetStringArray(p.bus, propSupportedUriSchemes)
}

func (p *Player) SupportedMimeTypes() ([]string, error) {
	return dbusGetStringArray(p.bus, propSupportedMimeTypes)
}

func (p *Player) CanGoNext() (bool, error) {
	return dbusGetBool(p.bus, propCanGoNext)
}

func (p *Player) CanGoPrevious() (bool, error) {
	return dbusGetBool(p.bus, propCanGoPrevious)
}

func (p *Player) CanSeek() (bool, error) {
	return dbusGetBool(p.bus, cmdSeek)
}

func (p *Player) CanControl() (bool, error) {
	return dbusGetBool(p.bus, propCanControl)
}

func (p *Player) CanPlay() (bool, error) {
	return dbusGetBool(p.bus, propCanPlay)
}

func (p *Player) CanPause() (bool, error) {
	return dbusGetBool(p.bus, propCanPause)
}

func (p *Player) Next() error {
	return dbusCall(p.bus, cmdNext)
}

func (p *Player) Previous() error {
	return dbusCall(p.bus, cmdPrevious)
}

func (p *Player) Pause() error {
	return dbusCall(p.bus, cmdPause)
}

func (p *Player) PlayPause() error {
	return dbusCall(p.bus, cmdPlayPause)
}

func (p *Player) Stop() error {
	return dbusCall(p.bus, cmdStop)
}

func (p *Player) Seek(amount int64) (int64, error) {
	log.WithFields(log.Fields{
		"path":        cmdSeek,
		"paramAmount": amount,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSeek, 0, amount)
	if call.Err != nil {
		return 0, call.Err
	}
	return call.Body[0].(int64), nil
}

func (p *Player) SetPosition(path string, position int64) (int64, error) {
	log.WithFields(log.Fields{
		"path":          cmdSetPosition,
		"paramPath":     path,
		"paramPosition": position,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSetPosition, 0, path, position)
	if call.Err != nil {
		return 0, call.Err
	}
	return call.Body[0].(int64), nil
}

func (p *Player) PlaybackStatus() (string, error) {
	return dbusGetString(p.bus, propPlaybackStatus)
}

func (p *Player) Volume(volume ...float64) (float64, error) {
	log.WithFields(log.Fields{
		"path":        cmdVolume,
		"paramVolume": volume,
	}).Debug("omxplayer: dbus call")
	if len(volume) == 0 {
		return dbusGetFloat64(p.bus, cmdVolume)
	}
	call := p.bus.Call(cmdVolume, 0, volume[0])
	if call.Err != nil {
		return 0, call.Err
	}
	return call.Body[0].(float64), nil
}

func (p *Player) Mute() error {
	return dbusCall(p.bus, cmdMute)
}

func (p *Player) Unmute() error {
	return dbusCall(p.bus, cmdUnmute)
}

func (p *Player) Position() (int64, error) {
	return dbusGetInt64(p.bus, propPosition)
}

func (p *Player) Aspect() (float64, error) {
	return dbusGetFloat64(p.bus, propAspect)
}

func (p *Player) VideoStreamCount() (int64, error) {
	return dbusGetInt64(p.bus, propVideoStreamCount)
}

func (p *Player) ResWidth() (int64, error) {
	return dbusGetInt64(p.bus, propResWidth)
}

func (p *Player) ResHeight() (int64, error) {
	return dbusGetInt64(p.bus, propResHeight)
}

func (p *Player) Duration() (int64, error) {
	return dbusGetInt64(p.bus, propDuration)
}

func (p *Player) MinimumRate() (float64, error) {
	return dbusGetFloat64(p.bus, propMinimumRate)
}

func (p *Player) MaximumRate() (float64, error) {
	return dbusGetFloat64(p.bus, propMaximumRate)
}

func (p *Player) ListSubtitles() ([]string, error) {
	return dbusGetStringArray(p.bus, cmdListSubtitles)
}

func (p *Player) HideVideo() error {
	return dbusCall(p.bus, cmdHideVideo)
}

func (p *Player) UnHideVideo() error {
	return dbusCall(p.bus, cmdUnHideVideo)
}

func (p *Player) ListAudio() ([]string, error) {
	return dbusGetStringArray(p.bus, cmdListAudio)
}

func (p *Player) ListVideo() ([]string, error) {
	return dbusGetStringArray(p.bus, cmdListVideo)
}

func (p *Player) SelectSubtitle(index int32) (bool, error) {
	log.WithFields(log.Fields{
		"path":       cmdSelectSubtitle,
		"paramIndex": index,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSelectSubtitle, 0, index)
	if call.Err != nil {
		return false, call.Err
	}
	return call.Body[0].(bool), nil
}

func (p *Player) SelectAudio(index int32) (bool, error) {
	log.WithFields(log.Fields{
		"path":       cmdSelectAudio,
		"paramIndex": index,
	}).Debug("omxplayer: dbus call")
	call := p.bus.Call(cmdSelectAudio, 0, index)
	if call.Err != nil {
		return false, call.Err
	}
	return call.Body[0].(bool), nil
}

func (p *Player) ShowSubtitles() error {
	return dbusCall(p.bus, cmdShowSubtitles)
}

func (p *Player) HideSubtitles() error {
	return dbusCall(p.bus, cmdHideSubtitles)
}

func (p *Player) Action(action int32) error {
	log.WithFields(log.Fields{
		"path":        cmdAction,
		"paramAction": action,
	}).Debug("omxplayer: dbus call")
	return p.bus.Call(cmdAction, 0, action).Err
}
<|endoftext|>


<commit_before>package awskms

import (
	"context"
	"os"
	"reflect"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	log "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/helper/logging"
)

func TestAWSKMSSeal(t *testing.T) {
	s := NewSeal(logging.NewVaultLogger(log.Trace))
	s.client = &mockAWSKMSSealClient{
		keyID: aws.String(awsTestKeyID),
	}

	_, err := s.SetConfig(nil)
	if err == nil {
		t.Fatal("expected error when AWSKMSSeal key ID is not provided")
	}

	// Set the key
	os.Setenv(EnvAWSKMSSealKeyID, awsTestKeyID)
	_, err = s.SetConfig(nil)
	if err != nil {
		t.Fatal(err)
	}
}

func TestAWSKMSSeal_Lifecycle(t *testing.T) {
	s := NewSeal(logging.NewVaultLogger(log.Trace))
	s.client = &mockAWSKMSSealClient{
		keyID: aws.String(awsTestKeyID),
	}

	os.Setenv(EnvAWSKMSSealKeyID, awsTestKeyID)
	_, err := s.SetConfig(nil)
	if err != nil {
		t.Fatal(err)
	}

	// Test Encrypt and Decrypt calls
	input := []byte("foo")
	swi, err := s.Encrypt(context.Background(), input)
	if err != nil {
		t.Fatalf("err: %s", err.Error())
	}

	pt, err := s.Decrypt(context.Background(), swi)
	if err != nil {
		t.Fatalf("err: %s", err.Error())
	}

	if !reflect.DeepEqual(input, pt) {
		t.Fatalf("expected %s, got %s", input, pt)
	}
}

func TestAWSKMSSeal_custom_endpoint(t *testing.T) {
	customEndpoint := "https://custom.endpoint"
	customEndpoint2 := "https://custom.endpoint.2"
	endpointENV := "AWS_KMS_ENDPOINT"

	// unset at end of test
	os.Setenv(EnvAWSKMSSealKeyID, awsTestKeyID)
	defer func() {
		if err := os.Unsetenv(EnvAWSKMSSealKeyID); err != nil {
			t.Fatal(err)
		}
	}()

	cfg := make(map[string]string)
	cfg["endpoint"] = customEndpoint

	testCases := []struct {
		Title    string
		Env      string
		Config   map[string]string
		Expected *string
	}{
		{
			// Default will have nil for the config endpoint, and be looked up
			// dynamically by the SDK
			Title: "Default",
		},
		{
			Title:    "Environment",
			Env:      customEndpoint,
			Expected: aws.String(customEndpoint),
		},
		{
			Title:    "Config",
			Config:   cfg,
			Expected: aws.String(customEndpoint),
		},
		{
			// Expect environment to take precedence over configuration
			Title:    "Env-Config",
			Env:      customEndpoint2,
			Config:   cfg,
			Expected: aws.String(customEndpoint2),
		},
	}

	for _, tc := range testCases {
		t.Run(tc.Title, func(t *testing.T) {
			s := NewSeal(logging.NewVaultLogger(log.Trace))

			s.client = &mockAWSKMSSealClient{
				keyID: aws.String(awsTestKeyID),
			}

			if tc.Env != "" {
				if err := os.Setenv(endpointENV, tc.Env); err != nil {
					t.Fatal(err)
				}
			}

			// cfg starts as nil, and takes a test case value if given. If not,
			// SetConfig is called with nil and creates it's own config
			var cfg map[string]string
			if tc.Config != nil {
				cfg = tc.Config
			}
			if _, err := s.SetConfig(cfg); err != nil {
				t.Fatalf("error setting config: %s", err)
			}

			// call getAWSKMSClient() to get the configured client and verify it's
			// endpoint
			k, err := s.getAWSKMSClient()
			if err != nil {
				t.Fatal(err)
			}

			if tc.Expected == nil && k.Config.Endpoint != nil {
				t.Fatalf("Expected nil endpoint, got: (%s)", *k.Config.Endpoint)
			}

			if tc.Expected != nil {
				if k.Config.Endpoint == nil {
					t.Fatal("expected custom endpoint, but config was nil")
				}
				if *k.Config.Endpoint != *tc.Expected {
					t.Fatalf("expected custom endpoint (%s), got: (%s)", *tc.Expected, *k.Config.Endpoint)
				}
			}

			// clear endpoint env after each test
			if err := os.Unsetenv(endpointENV); err != nil {
				t.Fatal(err)
			}
		})
	}

}
<commit_msg>AWS auto-unseal acceptance test (#5739)<commit_after>package awskms

import (
	"context"
	"os"
	"reflect"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	log "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/helper/logging"
)

func TestAWSKMSSeal(t *testing.T) {
	s := NewSeal(logging.NewVaultLogger(log.Trace))
	s.client = &mockAWSKMSSealClient{
		keyID: aws.String(awsTestKeyID),
	}

	_, err := s.SetConfig(nil)
	if err == nil {
		t.Fatal("expected error when AWSKMSSeal key ID is not provided")
	}

	// Set the key
	os.Setenv(EnvAWSKMSSealKeyID, awsTestKeyID)
	_, err = s.SetConfig(nil)
	if err != nil {
		t.Fatal(err)
	}
}

func TestAWSKMSSeal_Lifecycle(t *testing.T) {
	s := NewSeal(logging.NewVaultLogger(log.Trace))
	s.client = &mockAWSKMSSealClient{
		keyID: aws.String(awsTestKeyID),
	}
	os.Setenv(EnvAWSKMSSealKeyID, awsTestKeyID)
	testEncryptionRoundTrip(t, s)
}

// This test executes real calls. The calls themselves should be free,
// but the KMS key used is generally not free. AWS charges about $1/month
// per key.
//
// To run this test, the following env variables need to be set:
//   - VAULT_AWSKMS_SEAL_KEY_ID
//   - AWS_REGION
//   - AWS_ACCESS_KEY_ID
//   - AWS_SECRET_ACCESS_KEY
func TestAccAWSKMSSeal_Lifecycle(t *testing.T) {
	if os.Getenv(EnvAWSKMSSealKeyID) == "" {
		t.SkipNow()
	}
	s := NewSeal(logging.NewVaultLogger(log.Trace))
	testEncryptionRoundTrip(t, s)
}

func testEncryptionRoundTrip(t *testing.T, seal *AWSKMSSeal) {
	seal.SetConfig(nil)
	input := []byte("foo")
	swi, err := seal.Encrypt(context.Background(), input)
	if err != nil {
		t.Fatalf("err: %s", err.Error())
	}

	pt, err := seal.Decrypt(context.Background(), swi)
	if err != nil {
		t.Fatalf("err: %s", err.Error())
	}

	if !reflect.DeepEqual(input, pt) {
		t.Fatalf("expected %s, got %s", input, pt)
	}
}

func TestAWSKMSSeal_custom_endpoint(t *testing.T) {
	customEndpoint := "https://custom.endpoint"
	customEndpoint2 := "https://custom.endpoint.2"
	endpointENV := "AWS_KMS_ENDPOINT"

	// unset at end of test
	os.Setenv(EnvAWSKMSSealKeyID, awsTestKeyID)
	defer func() {
		if err := os.Unsetenv(EnvAWSKMSSealKeyID); err != nil {
			t.Fatal(err)
		}
	}()

	cfg := make(map[string]string)
	cfg["endpoint"] = customEndpoint

	testCases := []struct {
		Title    string
		Env      string
		Config   map[string]string
		Expected *string
	}{
		{
			// Default will have nil for the config endpoint, and be looked up
			// dynamically by the SDK
			Title: "Default",
		},
		{
			Title:    "Environment",
			Env:      customEndpoint,
			Expected: aws.String(customEndpoint),
		},
		{
			Title:    "Config",
			Config:   cfg,
			Expected: aws.String(customEndpoint),
		},
		{
			// Expect environment to take precedence over configuration
			Title:    "Env-Config",
			Env:      customEndpoint2,
			Config:   cfg,
			Expected: aws.String(customEndpoint2),
		},
	}

	for _, tc := range testCases {
		t.Run(tc.Title, func(t *testing.T) {
			s := NewSeal(logging.NewVaultLogger(log.Trace))

			s.client = &mockAWSKMSSealClient{
				keyID: aws.String(awsTestKeyID),
			}

			if tc.Env != "" {
				if err := os.Setenv(endpointENV, tc.Env); err != nil {
					t.Fatal(err)
				}
			}

			// cfg starts as nil, and takes a test case value if given. If not,
			// SetConfig is called with nil and creates it's own config
			var cfg map[string]string
			if tc.Config != nil {
				cfg = tc.Config
			}
			if _, err := s.SetConfig(cfg); err != nil {
				t.Fatalf("error setting config: %s", err)
			}

			// call getAWSKMSClient() to get the configured client and verify it's
			// endpoint
			k, err := s.getAWSKMSClient()
			if err != nil {
				t.Fatal(err)
			}

			if tc.Expected == nil && k.Config.Endpoint != nil {
				t.Fatalf("Expected nil endpoint, got: (%s)", *k.Config.Endpoint)
			}

			if tc.Expected != nil {
				if k.Config.Endpoint == nil {
					t.Fatal("expected custom endpoint, but config was nil")
				}
				if *k.Config.Endpoint != *tc.Expected {
					t.Fatalf("expected custom endpoint (%s), got: (%s)", *tc.Expected, *k.Config.Endpoint)
				}
			}

			// clear endpoint env after each test
			if err := os.Unsetenv(endpointENV); err != nil {
				t.Fatal(err)
			}
		})
	}

}
<|endoftext|>


<commit_before>/*

Copyright (c) 2010 Andrea Fazzi

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

package spectrum

import "sync"

type Keyboard struct {
	keyStates [8]byte
	mutex     sync.RWMutex
}

func NewKeyboard() *Keyboard {
	k := &Keyboard{}

	// Initialize keyStates
	var row uint
	for row = 0; row < 8; row++ {
		k.SetKeyState(row, 0xff)
	}

	return k
}

func (keyboard *Keyboard) GetKeyState(row uint) byte {
	keyboard.mutex.RLock()
	keyState := keyboard.keyStates[row]
	keyboard.mutex.RUnlock()
	return keyState
}

func (keyboard *Keyboard) SetKeyState(row uint, state byte) {
	keyboard.mutex.Lock()
	keyboard.keyStates[row] = state
	keyboard.mutex.Unlock()
}

func (keyboard *Keyboard) KeyDown(keySym uint) {
	keyCode, ok := keyCodes[keySym]

	if ok {
		keyboard.mutex.Lock()
		keyboard.keyStates[keyCode.row] &= ^(keyCode.mask)
		keyboard.mutex.Unlock()
	}
}

func (keyboard *Keyboard) KeyUp(keySym uint) {
	keyCode, ok := keyCodes[keySym]

	if ok {
		keyboard.mutex.Lock()
		keyboard.keyStates[keyCode.row] |= (keyCode.mask)
		keyboard.mutex.Unlock()
	}
}

type keyCell struct {
	row, mask byte
}

var keyCodes = map[uint]keyCell{
	49: keyCell{row: 3, mask: 0x01}, /* 1 */
	50: keyCell{row: 3, mask: 0x02}, /* 2 */
	51: keyCell{row: 3, mask: 0x04}, /* 3 */
	52: keyCell{row: 3, mask: 0x08}, /* 4 */
	53: keyCell{row: 3, mask: 0x10}, /* 5 */
	54: keyCell{row: 4, mask: 0x10}, /* 6 */
	55: keyCell{row: 4, mask: 0x08}, /* 7 */
	56: keyCell{row: 4, mask: 0x04}, /* 8 */
	57: keyCell{row: 4, mask: 0x02}, /* 9 */
	48: keyCell{row: 4, mask: 0x01}, /* 0 */

	113: keyCell{row: 2, mask: 0x01}, /* Q */
	119: keyCell{row: 2, mask: 0x02}, /* W */
	101: keyCell{row: 2, mask: 0x04}, /* E */
	114: keyCell{row: 2, mask: 0x08}, /* R */
	116: keyCell{row: 2, mask: 0x10}, /* T */
	121: keyCell{row: 5, mask: 0x10}, /* Y */
	117: keyCell{row: 5, mask: 0x08}, /* U */
	105: keyCell{row: 5, mask: 0x04}, /* I */
	111: keyCell{row: 5, mask: 0x02}, /* O */
	112: keyCell{row: 5, mask: 0x01}, /* P */

	97:  keyCell{row: 1, mask: 0x01}, /* A */
	115: keyCell{row: 1, mask: 0x02}, /* S */
	100: keyCell{row: 1, mask: 0x04}, /* D */
	102: keyCell{row: 1, mask: 0x08}, /* F */
	103: keyCell{row: 1, mask: 0x10}, /* G */
	104: keyCell{row: 6, mask: 0x10}, /* H */
	106: keyCell{row: 6, mask: 0x08}, /* J */
	107: keyCell{row: 6, mask: 0x04}, /* K */
	108: keyCell{row: 6, mask: 0x02}, /* L */
	13:  keyCell{row: 6, mask: 0x01}, /* enter */

	304: keyCell{row: 0, mask: 0x01}, /* caps */
	122: keyCell{row: 0, mask: 0x02}, /* Z */
	120: keyCell{row: 0, mask: 0x04}, /* X */
	99:  keyCell{row: 0, mask: 0x08}, /* C */
	118: keyCell{row: 0, mask: 0x10}, /* V */
	98:  keyCell{row: 7, mask: 0x10}, /* B */
	110: keyCell{row: 7, mask: 0x08}, /* N */
	109: keyCell{row: 7, mask: 0x04}, /* M */
	306: keyCell{row: 7, mask: 0x02}, /* sym - gah, firefox screws up ctrl+key too */
	32:  keyCell{row: 7, mask: 0x01} /* space */}
<commit_msg>Add a final comma in the keysym hash<commit_after>/*

Copyright (c) 2010 Andrea Fazzi

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

package spectrum

import "sync"

type Keyboard struct {
	keyStates [8]byte
	mutex     sync.RWMutex
}

func NewKeyboard() *Keyboard {
	k := &Keyboard{}

	// Initialize keyStates
	var row uint
	for row = 0; row < 8; row++ {
		k.SetKeyState(row, 0xff)
	}

	return k
}

func (keyboard *Keyboard) GetKeyState(row uint) byte {
	keyboard.mutex.RLock()
	keyState := keyboard.keyStates[row]
	keyboard.mutex.RUnlock()
	return keyState
}

func (keyboard *Keyboard) SetKeyState(row uint, state byte) {
	keyboard.mutex.Lock()
	keyboard.keyStates[row] = state
	keyboard.mutex.Unlock()
}

func (keyboard *Keyboard) KeyDown(keySym uint) {
	keyCode, ok := keyCodes[keySym]

	if ok {
		keyboard.mutex.Lock()
		keyboard.keyStates[keyCode.row] &= ^(keyCode.mask)
		keyboard.mutex.Unlock()
	}
}

func (keyboard *Keyboard) KeyUp(keySym uint) {
	keyCode, ok := keyCodes[keySym]

	if ok {
		keyboard.mutex.Lock()
		keyboard.keyStates[keyCode.row] |= (keyCode.mask)
		keyboard.mutex.Unlock()
	}
}

type keyCell struct {
	row, mask byte
}

var keyCodes = map[uint]keyCell{
	49: keyCell{row: 3, mask: 0x01}, /* 1 */
	50: keyCell{row: 3, mask: 0x02}, /* 2 */
	51: keyCell{row: 3, mask: 0x04}, /* 3 */
	52: keyCell{row: 3, mask: 0x08}, /* 4 */
	53: keyCell{row: 3, mask: 0x10}, /* 5 */
	54: keyCell{row: 4, mask: 0x10}, /* 6 */
	55: keyCell{row: 4, mask: 0x08}, /* 7 */
	56: keyCell{row: 4, mask: 0x04}, /* 8 */
	57: keyCell{row: 4, mask: 0x02}, /* 9 */
	48: keyCell{row: 4, mask: 0x01}, /* 0 */

	113: keyCell{row: 2, mask: 0x01}, /* Q */
	119: keyCell{row: 2, mask: 0x02}, /* W */
	101: keyCell{row: 2, mask: 0x04}, /* E */
	114: keyCell{row: 2, mask: 0x08}, /* R */
	116: keyCell{row: 2, mask: 0x10}, /* T */
	121: keyCell{row: 5, mask: 0x10}, /* Y */
	117: keyCell{row: 5, mask: 0x08}, /* U */
	105: keyCell{row: 5, mask: 0x04}, /* I */
	111: keyCell{row: 5, mask: 0x02}, /* O */
	112: keyCell{row: 5, mask: 0x01}, /* P */

	97:  keyCell{row: 1, mask: 0x01}, /* A */
	115: keyCell{row: 1, mask: 0x02}, /* S */
	100: keyCell{row: 1, mask: 0x04}, /* D */
	102: keyCell{row: 1, mask: 0x08}, /* F */
	103: keyCell{row: 1, mask: 0x10}, /* G */
	104: keyCell{row: 6, mask: 0x10}, /* H */
	106: keyCell{row: 6, mask: 0x08}, /* J */
	107: keyCell{row: 6, mask: 0x04}, /* K */
	108: keyCell{row: 6, mask: 0x02}, /* L */
	13:  keyCell{row: 6, mask: 0x01}, /* enter */

	304: keyCell{row: 0, mask: 0x01}, /* caps */
	122: keyCell{row: 0, mask: 0x02}, /* Z */
	120: keyCell{row: 0, mask: 0x04}, /* X */
	99:  keyCell{row: 0, mask: 0x08}, /* C */
	118: keyCell{row: 0, mask: 0x10}, /* V */
	98:  keyCell{row: 7, mask: 0x10}, /* B */
	110: keyCell{row: 7, mask: 0x08}, /* N */
	109: keyCell{row: 7, mask: 0x04}, /* M */
	306: keyCell{row: 7, mask: 0x02}, /* sym - gah, firefox screws up ctrl+key too */
	32:  keyCell{row: 7, mask: 0x01},/* space */
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls

import (
	"fmt"
	"net"
	"time"

	"github.com/ligato/cn-infra/logging"
	l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2"
)

// FibLogicalReq groups multiple fields so that all of them do
// not enumerate in one function call (request, reply/callback).
type FibLogicalReq struct {
	IsAdd    bool
	MAC      string
	BDIdx    uint32
	SwIfIdx  uint32
	BVI      bool
	Static   bool
	callback func(error)
}

// Add implements fib handler.
func (handler *FibVppHandler) Add(mac string, bdID uint32, ifIdx uint32, bvi bool, static bool, callback func(error)) error {
	handler.log.Debug("Adding L2 FIB table entry, mac: ", mac)

	handler.requestChan <- &FibLogicalReq{
		IsAdd:    true,
		MAC:      mac,
		BDIdx:    bdID,
		SwIfIdx:  ifIdx,
		BVI:      bvi,
		Static:   static,
		callback: callback,
	}
	return nil
}

// Delete implements fib handler.
func (handler *FibVppHandler) Delete(mac string, bdID uint32, ifIdx uint32, callback func(error)) error {
	handler.log.Debug("Removing L2 fib table entry, mac: ", mac)

	handler.requestChan <- &FibLogicalReq{
		IsAdd:    false,
		MAC:      mac,
		BDIdx:    bdID,
		SwIfIdx:  ifIdx,
		callback: callback,
	}
	return nil
}

// WatchFIBReplies implements fib handler.
func (handler *FibVppHandler) WatchFIBReplies() {
	for {
		select {
		case r := <-handler.requestChan:
			handler.log.Debug("VPP L2FIB request: ", r)
			err := handler.l2fibAddDel(r.MAC, r.BDIdx, r.SwIfIdx, r.BVI, r.Static, r.IsAdd)
			if err != nil {
				handler.log.WithFields(logging.Fields{"mac": r.MAC, "bdIdx": r.BDIdx}).
					Error("Static fib entry add/delete failed:", err)
			} else {
				handler.log.WithFields(logging.Fields{"mac": r.MAC, "bdIdx": r.BDIdx}).
					Debug("Static fib entry added/deleted.")
			}
			r.callback(err)
		}
	}
}

func (handler *FibVppHandler) l2fibAddDel(macstr string, bdIdx, swIfIdx uint32, bvi, static, isAdd bool) (err error) {
	defer func(t time.Time) {
		handler.stopwatch.TimeLog(l2ba.L2fibAddDel{}).LogTimeEntry(time.Since(t))
	}(time.Now())

	var mac []byte
	if macstr != "" {
		mac, err = net.ParseMAC(macstr)
		if err != nil {
			return err
		}
	}

	req := &l2ba.L2fibAddDel{
		IsAdd:     boolToUint(isAdd),
		Mac:       mac,
		BdID:      bdIdx,
		SwIfIndex: swIfIdx,
		BviMac:    boolToUint(bvi),
		StaticMac: boolToUint(static),
	}
	reply := &l2ba.L2fibAddDelReply{}

	if err := handler.asyncCallsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
		return err
	} else if reply.Retval != 0 {
		return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval)
	}

	return nil
}
<commit_msg>added ifIdx to log in fib vppcalls<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls

import (
	"fmt"
	"net"
	"time"

	"github.com/ligato/cn-infra/logging"
	l2ba "github.com/ligato/vpp-agent/plugins/vpp/binapi/l2"
)

// FibLogicalReq groups multiple fields so that all of them do
// not enumerate in one function call (request, reply/callback).
type FibLogicalReq struct {
	IsAdd    bool
	MAC      string
	BDIdx    uint32
	SwIfIdx  uint32
	BVI      bool
	Static   bool
	callback func(error)
}

// Add implements fib handler.
func (handler *FibVppHandler) Add(mac string, bdID uint32, ifIdx uint32, bvi bool, static bool, callback func(error)) error {
	handler.log.Debug("Adding L2 FIB table entry, mac: ", mac)

	handler.requestChan <- &FibLogicalReq{
		IsAdd:    true,
		MAC:      mac,
		BDIdx:    bdID,
		SwIfIdx:  ifIdx,
		BVI:      bvi,
		Static:   static,
		callback: callback,
	}
	return nil
}

// Delete implements fib handler.
func (handler *FibVppHandler) Delete(mac string, bdID uint32, ifIdx uint32, callback func(error)) error {
	handler.log.Debug("Removing L2 fib table entry, mac: ", mac)

	handler.requestChan <- &FibLogicalReq{
		IsAdd:    false,
		MAC:      mac,
		BDIdx:    bdID,
		SwIfIdx:  ifIdx,
		callback: callback,
	}
	return nil
}

// WatchFIBReplies implements fib handler.
func (handler *FibVppHandler) WatchFIBReplies() {
	for {
		select {
		case r := <-handler.requestChan:
			handler.log.Debug("VPP L2FIB request: ", r)
			err := handler.l2fibAddDel(r.MAC, r.BDIdx, r.SwIfIdx, r.BVI, r.Static, r.IsAdd)
			if err != nil {
				handler.log.WithFields(logging.Fields{"mac": r.MAC, "ifIdx": r.SwIfIdx, "bdIdx": r.BDIdx}).
					Error("Static fib entry add/delete failed:", err)
			} else {
				handler.log.WithFields(logging.Fields{"mac": r.MAC, "ifIdx": r.SwIfIdx, "bdIdx": r.BDIdx}).
					Debug("Static fib entry added/deleted.")
			}
			r.callback(err)
		}
	}
}

func (handler *FibVppHandler) l2fibAddDel(macstr string, bdIdx, swIfIdx uint32, bvi, static, isAdd bool) (err error) {
	defer func(t time.Time) {
		handler.stopwatch.TimeLog(l2ba.L2fibAddDel{}).LogTimeEntry(time.Since(t))
	}(time.Now())

	var mac []byte
	if macstr != "" {
		mac, err = net.ParseMAC(macstr)
		if err != nil {
			return err
		}
	}

	req := &l2ba.L2fibAddDel{
		IsAdd:     boolToUint(isAdd),
		Mac:       mac,
		BdID:      bdIdx,
		SwIfIndex: swIfIdx,
		BviMac:    boolToUint(bvi),
		StaticMac: boolToUint(static),
	}
	reply := &l2ba.L2fibAddDelReply{}

	if err := handler.asyncCallsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
		return err
	} else if reply.Retval != 0 {
		return fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval)
	}

	return nil
}
<|endoftext|>


<commit_before>package rpm

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// A PackageFile is an RPM package definition loaded directly from the pacakge
// file itself.
type PackageFile struct {
	Lead    Lead
	Headers Headers

	path     string
	fileSize uint64
	fileTime time.Time
}

// ReadPackageFile reads a rpm package file from a stream and returns a pointer
// to it.
func ReadPackageFile(r io.Reader) (*PackageFile, error) {
	// See: http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html
	p := &PackageFile{}

	// read the deprecated "lead"
	lead, err := ReadPackageLead(r)
	if err != nil {
		return nil, err
	}

	p.Lead = *lead

	// read signature and header headers
	offset := 96
	p.Headers = make(Headers, 2)
	for i := 0; i < 2; i++ {
		// parse header
		h, err := ReadPackageHeader(r)
		if err != nil {
			return nil, fmt.Errorf("%v (v%d.%d)", err, lead.VersionMajor, lead.VersionMinor)
		}

		// set start and end offsets
		h.Start = offset
		h.End = h.Start + 16 + (16 * h.IndexCount) + h.Length
		offset = h.End

		// calculate location of the end of the header by padding to a multiple of 8
		pad := 8 - int(math.Mod(float64(h.Length), 8))
		if pad < 8 {
			offset += pad
		}

		// append
		p.Headers[i] = *h
	}

	return p, nil
}

// OpenPackageFile reads a rpm package from the file systems and returns a pointer
// to it.
func OpenPackageFile(path string) (*PackageFile, error) {
	// stat file
	fi, err := os.Stat(path)
	if err != nil {
		return nil, err
	}

	// open file
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("Error opening RPM file: %s", err)
	}
	defer f.Close()

	// read package content
	p, err := ReadPackageFile(f)
	if err == nil {
		// set file path
		p.path = path
	}

	// set file stats
	p.fileSize = uint64(fi.Size())
	p.fileTime = fi.ModTime()

	return p, err
}

// OpenPackageFiles reads all rpm packages with the .rpm suffix from the given
// directory on the file systems and returns a slice of pointers to the loaded
// packages.
func OpenPackageFiles(path string) ([]*PackageFile, error) {
	// read directory
	dir, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}

	// list *.rpm files
	files := make([]string, 0)
	for _, f := range dir {
		if strings.HasSuffix(f.Name(), ".rpm") {
			files = append(files, filepath.Join(path, f.Name()))
		}
	}

	// read packages
	packages := make([]*PackageFile, len(files))
	for i, f := range files {
		p, err := OpenPackageFile(f)
		if err != nil {
			return nil, err
		}

		packages[i] = p
	}

	return packages, nil
}

// dependencies translates the given tag values into a slice of package
// relationships such as provides, conflicts, obsoletes and requires.
func (c *PackageFile) dependencies(nevrsTagId, flagsTagId, namesTagId, versionsTagId int) Dependencies {
	// TODO: Implement NEVRS tags

	flgs := c.Headers[1].Indexes.IntsByTag(flagsTagId)
	names := c.Headers[1].Indexes.StringsByTag(namesTagId)
	vers := c.Headers[1].Indexes.StringsByTag(versionsTagId)

	deps := make(Dependencies, len(names))
	for i := 0; i < len(names); i++ {
		deps[i] = NewDependency(int(flgs[i]), names[i], 0, vers[i], "")
	}

	return deps
}

// String returns the package identifier in the form
// '[name]-[version]-[release].[architecture]'.
func (c *PackageFile) String() string {
	return fmt.Sprintf("%s-%s-%s.%s", c.Name(), c.Version(), c.Release(), c.Architecture())
}

// Path returns the path which was given to open a package file if it was opened
// with OpenPackageFile.
func (c *PackageFile) Path() string {
	return c.path
}

// FileTime returns the time at which the RPM was last modified if known.
func (c *PackageFile) FileTime() time.Time {
	return c.fileTime
}

// FileSize returns the size of the package file in bytes.
func (c *PackageFile) FileSize() uint64 {
	return c.fileSize
}

// Checksum computes and returns the SHA256 checksum (encoded in hexidecimal) of
// the package file.
func (c *PackageFile) Checksum() (string, error) {
	if c.Path() == "" {
		return "", fmt.Errorf("File not found")
	}

	if f, err := os.Open(c.Path()); err != nil {
		return "", err
	} else {
		defer f.Close()

		s := sha256.New()
		if _, err := io.Copy(s, f); err != nil {
			return "", err
		}

		return hex.EncodeToString(s.Sum(nil)), nil
	}
}

// ChecksumType returns "sha256"
func (c *PackageFile) ChecksumType() string {
	return "sha256"
}

func (c *PackageFile) HeaderStart() uint64 {
	return uint64(c.Headers[1].Start)
}

func (c *PackageFile) HeaderEnd() uint64 {
	return uint64(c.Headers[1].End)
}

// For tag definitions, see:
// https://github.com/rpm-software-management/rpm/blob/master/lib/rpmtag.h#L61

func (c *PackageFile) Name() string {
	return c.Headers[1].Indexes.StringByTag(1000)
}

func (c *PackageFile) Version() string {
	return c.Headers[1].Indexes.StringByTag(1001)
}

func (c *PackageFile) Release() string {
	return c.Headers[1].Indexes.StringByTag(1002)
}

func (c *PackageFile) Epoch() int {
	return int(c.Headers[1].Indexes.IntByTag(1003))
}

func (c *PackageFile) Requires() Dependencies {
	return c.dependencies(5041, 1048, 1049, 1050)
}

func (c *PackageFile) Provides() Dependencies {
	return c.dependencies(5042, 1112, 1047, 1113)
}

func (c *PackageFile) Conflicts() Dependencies {
	return c.dependencies(5044, 1053, 1054, 1055)
}

func (c *PackageFile) Obsoletes() Dependencies {
	return c.dependencies(5043, 1114, 1090, 1115)
}

func (c *PackageFile) Files() []string {
	ixs := c.Headers[1].Indexes.IntsByTag(1116)
	names := c.Headers[1].Indexes.StringsByTag(1117)
	dirs := c.Headers[1].Indexes.StringsByTag(1118)

	files := make([]string, len(names))
	for i := 0; i < len(names); i++ {
		files[i] = dirs[ixs[i]] + names[i]
	}

	return files
}

func (c *PackageFile) Summary() string {
	return strings.Join(c.Headers[1].Indexes.StringsByTag(1004), "\n")
}

func (c *PackageFile) Description() string {
	return strings.Join(c.Headers[1].Indexes.StringsByTag(1005), "\n")
}

func (c *PackageFile) BuildTime() time.Time {
	return c.Headers[1].Indexes.TimeByTag(1006)
}

func (c *PackageFile) BuildHost() string {
	return c.Headers[1].Indexes.StringByTag(1007)
}

func (c *PackageFile) InstallTime() time.Time {
	return c.Headers[1].Indexes.TimeByTag(1008)
}

func (c *PackageFile) Size() uint64 {
	return uint64(c.Headers[1].Indexes.IntByTag(1009))
}

func (c *PackageFile) ArchiveSize() uint64 {
	return uint64(c.Headers[1].Indexes.IntByTag(1046))
}

func (c *PackageFile) Distribution() string {
	return c.Headers[1].Indexes.StringByTag(1010)
}

func (c *PackageFile) Vendor() string {
	return c.Headers[1].Indexes.StringByTag(1011)
}

func (c *PackageFile) GIFImage() []byte {
	return c.Headers[1].Indexes.BytesByTag(1012)
}

func (c *PackageFile) XPMImage() []byte {
	return c.Headers[1].Indexes.BytesByTag(1013)
}

func (c *PackageFile) License() string {
	return c.Headers[1].Indexes.StringByTag(1014)
}

func (c *PackageFile) Packager() string {
	return c.Headers[1].Indexes.StringByTag(1015)
}

func (c *PackageFile) Groups() []string {
	return c.Headers[1].Indexes.StringsByTag(1016)
}

func (c *PackageFile) ChangeLog() []string {
	return c.Headers[1].Indexes.StringsByTag(1017)
}

func (c *PackageFile) Source() []string {
	return c.Headers[1].Indexes.StringsByTag(1018)
}

func (c *PackageFile) Patch() []string {
	return c.Headers[1].Indexes.StringsByTag(1019)
}

func (c *PackageFile) URL() string {
	return c.Headers[1].Indexes.StringByTag(1020)
}

func (c *PackageFile) OperatingSystem() string {
	return c.Headers[1].Indexes.StringByTag(1021)
}

func (c *PackageFile) Architecture() string {
	return c.Headers[1].Indexes.StringByTag(1022)
}

func (c *PackageFile) PreInstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1023)
}

func (c *PackageFile) PostInstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1024)
}

func (c *PackageFile) PreUninstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1025)
}

func (c *PackageFile) PostUninstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1026)
}

func (c *PackageFile) OldFilenames() []string {
	return c.Headers[1].Indexes.StringsByTag(1027)
}

func (c *PackageFile) Icon() []byte {
	return c.Headers[1].Indexes.BytesByTag(1043)
}

func (c *PackageFile) SourceRPM() string {
	return c.Headers[1].Indexes.StringByTag(1044)
}

func (c *PackageFile) RPMVersion() string {
	return c.Headers[1].Indexes.StringByTag(1064)
}

func (c *PackageFile) Platform() string {
	return c.Headers[1].Indexes.StringByTag(1132)
}
<commit_msg>Fixed PackageFile.ArhciveSize()<commit_after>package rpm

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// A PackageFile is an RPM package definition loaded directly from the pacakge
// file itself.
type PackageFile struct {
	Lead    Lead
	Headers Headers

	path     string
	fileSize uint64
	fileTime time.Time
}

// ReadPackageFile reads a rpm package file from a stream and returns a pointer
// to it.
func ReadPackageFile(r io.Reader) (*PackageFile, error) {
	// See: http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html
	p := &PackageFile{}

	// read the deprecated "lead"
	lead, err := ReadPackageLead(r)
	if err != nil {
		return nil, err
	}

	p.Lead = *lead

	// read signature and header headers
	offset := 96
	p.Headers = make(Headers, 2)
	for i := 0; i < 2; i++ {
		// parse header
		h, err := ReadPackageHeader(r)
		if err != nil {
			return nil, fmt.Errorf("%v (v%d.%d)", err, lead.VersionMajor, lead.VersionMinor)
		}

		// set start and end offsets
		h.Start = offset
		h.End = h.Start + 16 + (16 * h.IndexCount) + h.Length
		offset = h.End

		// calculate location of the end of the header by padding to a multiple of 8
		pad := 8 - int(math.Mod(float64(h.Length), 8))
		if pad < 8 {
			offset += pad
		}

		// append
		p.Headers[i] = *h
	}

	return p, nil
}

// OpenPackageFile reads a rpm package from the file systems and returns a pointer
// to it.
func OpenPackageFile(path string) (*PackageFile, error) {
	// stat file
	fi, err := os.Stat(path)
	if err != nil {
		return nil, err
	}

	// open file
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("Error opening RPM file: %s", err)
	}
	defer f.Close()

	// read package content
	p, err := ReadPackageFile(f)
	if err == nil {
		// set file path
		p.path = path
	}

	// set file stats
	p.fileSize = uint64(fi.Size())
	p.fileTime = fi.ModTime()

	return p, err
}

// OpenPackageFiles reads all rpm packages with the .rpm suffix from the given
// directory on the file systems and returns a slice of pointers to the loaded
// packages.
func OpenPackageFiles(path string) ([]*PackageFile, error) {
	// read directory
	dir, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}

	// list *.rpm files
	files := make([]string, 0)
	for _, f := range dir {
		if strings.HasSuffix(f.Name(), ".rpm") {
			files = append(files, filepath.Join(path, f.Name()))
		}
	}

	// read packages
	packages := make([]*PackageFile, len(files))
	for i, f := range files {
		p, err := OpenPackageFile(f)
		if err != nil {
			return nil, err
		}

		packages[i] = p
	}

	return packages, nil
}

// dependencies translates the given tag values into a slice of package
// relationships such as provides, conflicts, obsoletes and requires.
func (c *PackageFile) dependencies(nevrsTagId, flagsTagId, namesTagId, versionsTagId int) Dependencies {
	// TODO: Implement NEVRS tags

	flgs := c.Headers[1].Indexes.IntsByTag(flagsTagId)
	names := c.Headers[1].Indexes.StringsByTag(namesTagId)
	vers := c.Headers[1].Indexes.StringsByTag(versionsTagId)

	deps := make(Dependencies, len(names))
	for i := 0; i < len(names); i++ {
		deps[i] = NewDependency(int(flgs[i]), names[i], 0, vers[i], "")
	}

	return deps
}

// String returns the package identifier in the form
// '[name]-[version]-[release].[architecture]'.
func (c *PackageFile) String() string {
	return fmt.Sprintf("%s-%s-%s.%s", c.Name(), c.Version(), c.Release(), c.Architecture())
}

// Path returns the path which was given to open a package file if it was opened
// with OpenPackageFile.
func (c *PackageFile) Path() string {
	return c.path
}

// FileTime returns the time at which the RPM was last modified if known.
func (c *PackageFile) FileTime() time.Time {
	return c.fileTime
}

// FileSize returns the size of the package file in bytes.
func (c *PackageFile) FileSize() uint64 {
	return c.fileSize
}

// Checksum computes and returns the SHA256 checksum (encoded in hexidecimal) of
// the package file.
func (c *PackageFile) Checksum() (string, error) {
	if c.Path() == "" {
		return "", fmt.Errorf("File not found")
	}

	if f, err := os.Open(c.Path()); err != nil {
		return "", err
	} else {
		defer f.Close()

		s := sha256.New()
		if _, err := io.Copy(s, f); err != nil {
			return "", err
		}

		return hex.EncodeToString(s.Sum(nil)), nil
	}
}

// ChecksumType returns "sha256"
func (c *PackageFile) ChecksumType() string {
	return "sha256"
}

func (c *PackageFile) HeaderStart() uint64 {
	return uint64(c.Headers[1].Start)
}

func (c *PackageFile) HeaderEnd() uint64 {
	return uint64(c.Headers[1].End)
}

// For tag definitions, see:
// https://github.com/rpm-software-management/rpm/blob/master/lib/rpmtag.h#L61

func (c *PackageFile) Name() string {
	return c.Headers[1].Indexes.StringByTag(1000)
}

func (c *PackageFile) Version() string {
	return c.Headers[1].Indexes.StringByTag(1001)
}

func (c *PackageFile) Release() string {
	return c.Headers[1].Indexes.StringByTag(1002)
}

func (c *PackageFile) Epoch() int {
	return int(c.Headers[1].Indexes.IntByTag(1003))
}

func (c *PackageFile) Requires() Dependencies {
	return c.dependencies(5041, 1048, 1049, 1050)
}

func (c *PackageFile) Provides() Dependencies {
	return c.dependencies(5042, 1112, 1047, 1113)
}

func (c *PackageFile) Conflicts() Dependencies {
	return c.dependencies(5044, 1053, 1054, 1055)
}

func (c *PackageFile) Obsoletes() Dependencies {
	return c.dependencies(5043, 1114, 1090, 1115)
}

func (c *PackageFile) Files() []string {
	ixs := c.Headers[1].Indexes.IntsByTag(1116)
	names := c.Headers[1].Indexes.StringsByTag(1117)
	dirs := c.Headers[1].Indexes.StringsByTag(1118)

	files := make([]string, len(names))
	for i := 0; i < len(names); i++ {
		files[i] = dirs[ixs[i]] + names[i]
	}

	return files
}

func (c *PackageFile) Summary() string {
	return strings.Join(c.Headers[1].Indexes.StringsByTag(1004), "\n")
}

func (c *PackageFile) Description() string {
	return strings.Join(c.Headers[1].Indexes.StringsByTag(1005), "\n")
}

func (c *PackageFile) BuildTime() time.Time {
	return c.Headers[1].Indexes.TimeByTag(1006)
}

func (c *PackageFile) BuildHost() string {
	return c.Headers[1].Indexes.StringByTag(1007)
}

func (c *PackageFile) InstallTime() time.Time {
	return c.Headers[1].Indexes.TimeByTag(1008)
}

// Size specifies the disk space consumed by installation of the package.
func (c *PackageFile) Size() uint64 {
	return uint64(c.Headers[1].Indexes.IntByTag(1009))
}

// ArchiveSize specifies the size of the archived payload of the package in
// bytes.
func (c *PackageFile) ArchiveSize() uint64 {
	if i := uint64(c.Headers[0].Indexes.IntByTag(1007)); i > 0 {
		return i
	}

	return uint64(c.Headers[1].Indexes.IntByTag(1046))
}

func (c *PackageFile) Distribution() string {
	return c.Headers[1].Indexes.StringByTag(1010)
}

func (c *PackageFile) Vendor() string {
	return c.Headers[1].Indexes.StringByTag(1011)
}

func (c *PackageFile) GIFImage() []byte {
	return c.Headers[1].Indexes.BytesByTag(1012)
}

func (c *PackageFile) XPMImage() []byte {
	return c.Headers[1].Indexes.BytesByTag(1013)
}

func (c *PackageFile) License() string {
	return c.Headers[1].Indexes.StringByTag(1014)
}

func (c *PackageFile) Packager() string {
	return c.Headers[1].Indexes.StringByTag(1015)
}

func (c *PackageFile) Groups() []string {
	return c.Headers[1].Indexes.StringsByTag(1016)
}

func (c *PackageFile) ChangeLog() []string {
	return c.Headers[1].Indexes.StringsByTag(1017)
}

func (c *PackageFile) Source() []string {
	return c.Headers[1].Indexes.StringsByTag(1018)
}

func (c *PackageFile) Patch() []string {
	return c.Headers[1].Indexes.StringsByTag(1019)
}

func (c *PackageFile) URL() string {
	return c.Headers[1].Indexes.StringByTag(1020)
}

func (c *PackageFile) OperatingSystem() string {
	return c.Headers[1].Indexes.StringByTag(1021)
}

func (c *PackageFile) Architecture() string {
	return c.Headers[1].Indexes.StringByTag(1022)
}

func (c *PackageFile) PreInstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1023)
}

func (c *PackageFile) PostInstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1024)
}

func (c *PackageFile) PreUninstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1025)
}

func (c *PackageFile) PostUninstallScript() string {
	return c.Headers[1].Indexes.StringByTag(1026)
}

func (c *PackageFile) OldFilenames() []string {
	return c.Headers[1].Indexes.StringsByTag(1027)
}

func (c *PackageFile) Icon() []byte {
	return c.Headers[1].Indexes.BytesByTag(1043)
}

func (c *PackageFile) SourceRPM() string {
	return c.Headers[1].Indexes.StringByTag(1044)
}

func (c *PackageFile) RPMVersion() string {
	return c.Headers[1].Indexes.StringByTag(1064)
}

func (c *PackageFile) Platform() string {
	return c.Headers[1].Indexes.StringByTag(1132)
}
<|endoftext|>


<commit_before>package marionette_client

type Capabilities struct {
	BrowserName                   string
	BrowserVersion                string
	PlatformName                  string
	PlatformVersion               string
	SpecificationLevel            string
	RaisesAccessibilityExceptions bool
	Rotatable                     bool
	AcceptSslCerts                bool
	TakesElementScreenshot        bool
	TakesScreenshot               bool
	Proxy                         interface{}
	Platform                      string
	XULappId                      string
	AppBuildId                    string
	Device                        string
	Version                       string
	Command_id                    uint32
}
<commit_msg>fixed Capabilities struct specificationLevel data type for ff 53.0.3<commit_after>package marionette_client

type Capabilities struct {
	BrowserName                   string
	BrowserVersion                string
	PlatformName                  string
	PlatformVersion               string
	SpecificationLevel            uint
	RaisesAccessibilityExceptions bool
	Rotatable                     bool
	AcceptSslCerts                bool
	TakesElementScreenshot        bool
	TakesScreenshot               bool
	Proxy                         interface{}
	Platform                      string
	XULappId                      string
	AppBuildId                    string
	Device                        string
	Version                       string
	Command_id                    uint32
}

/*
{"capabilities":
  {
	"browserName":"firefox",
	"browserVersion":"53.0.3","platformName":"linux",
	"platformVersion":"4.8.12-040812-generic",
	"pageLoadStrategy":"normal",
	"acceptInsecureCerts":false,
	"timeouts":{
		"implicit":0,
		"pageLoad":300000,
		"script":30000
	},
	"rotatable":false,
	"specificationLevel":0,
	"moz:processID":2004,
	"moz:profile":"/home/travis/.mozilla/firefox/594k4686.default",
	"moz:accessibilityChecks":false
  }
}**/
<|endoftext|>


<commit_before>package leaderboard

import (
	"superstellar/backend/pb"
	"superstellar/backend/state"
	"sort"
)

const LeaderboardLength = 10

type Leaderboard struct {
	ranks []Rank
}

func LeaderboardFromSpace(space *state.Space) *Leaderboard{
	size := len(space.Spaceships)
	ranks := make([]Rank, 0, size)
	for _, stateship := range space.Spaceships {
		// TODO: change to MaxHP?
		ranks = append(ranks, Rank{stateship.ID, stateship.HP})
	}
	sort.Stable(sort.Reverse(SortableByScore(ranks)))
	return &Leaderboard{ranks: ranks}
}

// ToProto returns protobuf representation
func (leaderboard *Leaderboard) ToProto() *pb.Leaderboard {
	ranks := make([]*pb.Rank, 0, len(leaderboard.ranks))
	for _, rank := range leaderboard.ranks {
		ranks = append(ranks, rank.ToProto())
	}

	return &pb.Leaderboard{Ranks: ranks}
}

// ToMessage returns protobuffer Message object with Leaderboard containing ordered Ranks.
func (leaderboard *Leaderboard) ToMessage() *pb.Message {
	return &pb.Message{
		Content: &pb.Message_Leaderboard{
			Leaderboard: leaderboard.ToProto(),
		},
	}
}
<commit_msg>Use MaxHP as Score<commit_after>package leaderboard

import (
	"superstellar/backend/pb"
	"superstellar/backend/state"
	"sort"
)

const LeaderboardLength = 10

type Leaderboard struct {
	ranks []Rank
}

func LeaderboardFromSpace(space *state.Space) *Leaderboard{
	size := len(space.Spaceships)
	ranks := make([]Rank, 0, size)
	for _, stateship := range space.Spaceships {
		ranks = append(ranks, Rank{stateship.ID, stateship.MaxHP})
	}
	sort.Stable(sort.Reverse(SortableByScore(ranks)))
	return &Leaderboard{ranks: ranks}
}

// ToProto returns protobuf representation
func (leaderboard *Leaderboard) ToProto() *pb.Leaderboard {
	ranks := make([]*pb.Rank, 0, len(leaderboard.ranks))
	for _, rank := range leaderboard.ranks {
		ranks = append(ranks, rank.ToProto())
	}

	return &pb.Leaderboard{Ranks: ranks}
}

// ToMessage returns protobuffer Message object with Leaderboard containing ordered Ranks.
func (leaderboard *Leaderboard) ToMessage() *pb.Message {
	return &pb.Message{
		Content: &pb.Message_Leaderboard{
			Leaderboard: leaderboard.ToProto(),
		},
	}
}
<|endoftext|>