<commit_before>// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// dlp is an example of using the DLP API.
package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	dlp "cloud.google.com/go/dlp/apiv2beta1"
	dlppb "google.golang.org/genproto/googleapis/privacy/dlp/v2beta1"
)

func redact(w io.Writer, client *dlp.Client) {
	rcr := &dlppb.RedactContentRequest{
		InspectConfig: &dlppb.InspectConfig{
			InfoTypes: []*dlppb.InfoType{
				{
					Name: "US_SOCIAL_SECURITY_NUMBER",
				},
			},
			MinLikelihood: dlppb.Likelihood_LIKELIHOOD_UNSPECIFIED,
		},
		ReplaceConfigs: []*dlppb.RedactContentRequest_ReplaceConfig{
			{
				InfoType:    &dlppb.InfoType{Name: "US_SOCIAL_SECURITY_NUMBER"},
				ReplaceWith: "[redacted]",
			},
		},
		Items: []*dlppb.ContentItem{
			{
				Type: "text/plain",
				DataItem: &dlppb.ContentItem_Data{
					Data: []byte("My SSN is 500112233"),
				},
			},
		},
	}
	r, err := client.RedactContent(context.Background(), rcr)
	if err != nil {
		log.Fatal(err)
	}
	i := r.GetItems()[0]
	fmt.Fprint(w, string(i.GetData()))
}

func main() {
	ctx := context.Background()
	client, err := dlp.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	flag.Parse()

	if flag.NArg() == 0 || flag.NArg() > 1 {
		fmt.Fprintf(os.Stderr, "Usage: %s CMD\n", os.Args[0])
		os.Exit(1)
	}
	switch flag.Arg(0) {
	case "redact":
		redact(os.Stdout, client)
	}
}
<commit_msg>dlp: pass in string to analyze<commit_after>// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// dlp is an example of using the DLP API.
package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	dlp "cloud.google.com/go/dlp/apiv2beta1"
	dlppb "google.golang.org/genproto/googleapis/privacy/dlp/v2beta1"
)

func redact(w io.Writer, client *dlp.Client, s string) {
	rcr := &dlppb.RedactContentRequest{
		InspectConfig: &dlppb.InspectConfig{
			InfoTypes: []*dlppb.InfoType{
				{
					Name: "US_SOCIAL_SECURITY_NUMBER",
				},
			},
			MinLikelihood: dlppb.Likelihood_LIKELIHOOD_UNSPECIFIED,
		},
		ReplaceConfigs: []*dlppb.RedactContentRequest_ReplaceConfig{
			{
				InfoType:    &dlppb.InfoType{Name: "US_SOCIAL_SECURITY_NUMBER"},
				ReplaceWith: "[redacted]",
			},
		},
		Items: []*dlppb.ContentItem{
			{
				Type: "text/plain",
				DataItem: &dlppb.ContentItem_Data{
					Data: []byte(s),
				},
			},
		},
	}
	r, err := client.RedactContent(context.Background(), rcr)
	if err != nil {
		log.Fatal(err)
	}
	i := r.GetItems()[0]
	fmt.Fprint(w, string(i.GetData()))
}

func main() {
	ctx := context.Background()
	client, err := dlp.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	flag.Parse()

	if flag.NArg() != 2 {
		fmt.Fprintf(os.Stderr, `Usage: %s CMD "string"\n`, os.Args[0])
		os.Exit(1)
	}
	switch flag.Arg(0) {
	case "redact":
		redact(os.Stdout, client, flag.Arg(1))
	}
}
<|endoftext|>


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

package fmt

/*
	C-like printf, but because of reflection knowledge does not need
	to be told about sizes and signedness (no %llud etc. - just %d).
*/

import (
	"fmt";
	"reflect";
	"os";
)

const Runeself = 0x80
const AllocSize = 32

export type P struct {
	n	int;
	buf	*[]byte;
	fmt	*Fmt;
}

export func Printer() *P {
	p := new(P);
	p.fmt = fmt.New();
	return p;
}

func (p *P) ensure(n int) {
	if p.buf == nil || len(p.buf) < n {
		newn := AllocSize;
		if p.buf != nil {
			newn += len(p.buf);
		}
		if newn < n {
			newn = n + AllocSize
		}
		b := new([]byte, newn);
		for i := 0; i < p.n; i++ {
			b[i] = p.buf[i];
		}
		p.buf = b;
	}
}

func (p *P) addstr(s string) {
	n := len(s);
	p.ensure(p.n + n);
	for i := 0; i < n; i++ {
		p.buf[p.n] = s[i];
		p.n++;
	}
}

func (p *P) addbytes(b *[]byte, start, end int) {
	p.ensure(p.n + end-start);
	for i := start; i < end; i++ {
		p.buf[p.n] = b[i];
		p.n++;
	}
}

func (p *P) add(c int) {
	p.ensure(p.n + 1);
	if c < Runeself {
		p.buf[p.n] = byte(c);
		p.n++;
	} else {
		p.addstr(string(c));
	}
}

func (p *P) reset() {
	p.n = 0;
}

export type Writer interface {
	Write(b *[]byte) (ret int, err *os.Error);
}

func (p *P) doprintf(format string, v reflect.StructValue);
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);

// These routines end in 'f' and take a format string.

func (p *P) fprintf(w Writer, format string, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p.doprintf(format, v);
	n, error = w.Write(p.buf[0:p.n]);
	p.reset();
	return n, error;
}

func (p *P) printf(format string, v ...) (n int, errno *os.Error) {
	n, errno = p.fprintf(os.Stdout, format, v);
	return n, errno;
}

func (p *P) sprintf(format string, v ...) string {
	p.doprintf(format, reflect.NewValue(v).(reflect.StructValue));
	s := string(p.buf)[0 : p.n];
	p.reset();
	return s;
}

// These routines do not take a format string and add spaces only
// when the operand on neither side is a string.

func (p *P) fprint(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p.doprint(v, false, false);
	n, error = w.Write(p.buf[0:p.n]);
	p.reset();
	return n, error;
}

func (p *P) print(v ...) (n int, errno *os.Error) {
	n, errno = p.fprint(os.Stdout, v);
	return n, errno;
}

func (p *P) sprint(v ...) string {
	p.doprint(reflect.NewValue(v).(reflect.StructValue), false, false);
	s := string(p.buf)[0 : p.n];
	p.reset();
	return s;
}

// These routines end in 'ln', do not take a format string,
// always add spaces between operands, and add a newline
// after the last operand.

func (p *P) fprintln(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p.doprint(v, true, true);
	n, error = w.Write(p.buf[0:p.n]);
	p.reset();
	return n, error;
}

func (p *P) println(v ...) (n int, errno *os.Error) {
	n, errno = p.fprintln(os.Stdout, v);
	return n, errno;
}

func (p *P) sprintln(v ...) string {
	p.doprint(reflect.NewValue(v).(reflect.StructValue), true, true);
	s := string(p.buf)[0 : p.n];
	p.reset();
	return s;
}

// Getters for the fields of the argument structure.

func getInt(v reflect.Value) (val int64, signed, ok bool) {
	switch v.Kind() {
	case reflect.IntKind:
		return int64(v.(reflect.IntValue).Get()), true, true;
	case reflect.Int8Kind:
		return int64(v.(reflect.Int8Value).Get()), true, true;
	case reflect.Int16Kind:
		return int64(v.(reflect.Int16Value).Get()), true, true;
	case reflect.Int32Kind:
		return int64(v.(reflect.Int32Value).Get()), true, true;
	case reflect.Int64Kind:
		return int64(v.(reflect.Int64Value).Get()), true, true;
	case reflect.UintKind:
		return int64(v.(reflect.UintValue).Get()), false, true;
	case reflect.Uint8Kind:
		return int64(v.(reflect.Uint8Value).Get()), false, true;
	case reflect.Uint16Kind:
		return int64(v.(reflect.Uint16Value).Get()), false, true;
	case reflect.Uint32Kind:
		return int64(v.(reflect.Uint32Value).Get()), false, true;
	case reflect.Uint64Kind:
		return int64(v.(reflect.Uint64Value).Get()), false, true;
	}
	return 0, false, false;
}

func getString(v reflect.Value) (val string, ok bool) {
	switch v.Kind() {
	case reflect.StringKind:
		return v.(reflect.StringValue).Get(), true;
	}
	return "", false;
}

func getFloat(v reflect.Value) (val float64, ok bool) {
	switch v.Kind() {
	case reflect.FloatKind:
		return float64(v.(reflect.FloatValue).Get()), true;
	case reflect.Float32Kind:
		return float64(v.(reflect.Float32Value).Get()), true;
	case reflect.Float64Kind:
		return float64(v.(reflect.Float64Value).Get()), true;
	case reflect.Float80Kind:
		break;	// TODO: what to do here?
	}
	return 0.0, false;
}

func getPtr(v reflect.Value) (val uint64, ok bool) {
	switch v.Kind() {
	case reflect.PtrKind:
		return v.(reflect.PtrValue).Get(), true;
	}
	return 0, false;
}

// Convert ASCII to integer.

func parsenum(s string, start, end int) (n int, got bool, newi int) {
	if start >= end {
		return 0, false, end
	}
	if s[start] == '-' {
		a, b, c := parsenum(s, start+1, end);
		if b {
			return -a, b, c;
		}
	}
	isnum := false;
	num := 0;
	for '0' <= s[start] && s[start] <= '9' {
		num = num*10 + int(s[start] - '0');
		start++;
		isnum = true;
	}
	return num, isnum, start;
}

func (p *P) doprintf(format string, v reflect.StructValue) {
	p.ensure(len(format));	// a good starting size
	end := len(format) - 1;
	fieldnum := 0;	// we process one field per non-trivial format
	for i := 0; i <= end;  {
		c, w := sys.stringtorune(format, i);
		if c != '%' || i == end {
			p.add(c);
			i += w;
			continue;
		}
		var got bool;
		// saw % - do we have %20 (width)?
		w, got, i = parsenum(format, i+1, end);
		if got {
			p.fmt.w(w);
		}
		// do we have %.20 (precision)?
		if i < end && format[i] == '.' {
			w, got, i = parsenum(format, i+1, end);
			if got {
				p.fmt.p(w);
			}
		}
		c, w = sys.stringtorune(format, i);
		i += w;
		// percent is special - absorbs no operand
		if c == '%' {
			p.add('%');	// TODO: should we bother with width & prec?
			continue;
		}
		if fieldnum >= v.Len() {	// out of operands
			p.addstr("???");
			continue;
		}
		field := v.Field(fieldnum);
		fieldnum++;
		s := "";
		switch c {
			// bool
			case 't':
				if field.(reflect.BoolValue).Get() {
					s = "true";
				} else {
					s = "false";
				}

			// int
			case 'b':
				if v, signed, ok := getInt(field); ok {
					s = p.fmt.b64(uint64(v)).str()	// always unsigned
				} else {
					s = "%b%"
				}
			case 'd':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.d64(v).str()
					} else {
						s = p.fmt.ud64(uint64(v)).str()
					}
				} else {
					s = "%d%"
				}
			case 'o':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.o64(v).str()
					} else {
						s = p.fmt.uo64(uint64(v)).str()
					}
				} else {
					s= "%o%"
				}
			case 'x':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.x64(v).str()
					} else {
						s = p.fmt.ux64(uint64(v)).str()
					}
				} else {
					s = "%x%"
				}

			// float
			case 'e':
				if v, ok := getFloat(field); ok {
					s = p.fmt.e64(v).str()
				} else {
					s = "%e%"
				}
			case 'f':
				if v, ok := getFloat(field); ok {
					s = p.fmt.f64(v).str()
				} else {
					s = "%f%";
				}
			case 'g':
				if v, ok := getFloat(field); ok {
					s = p.fmt.g64(v).str()
				} else {
					s = "%g%"
				}

			// string
			case 's':
				if v, ok := getString(field); ok {
					s = p.fmt.s(v).str()
				} else {
					s = "%s%"
				}

			// pointer
			case 'p':
				if v, ok := getPtr(field); ok {
					s = "0x" + p.fmt.uX64(v).str()
				} else {
					s = "%p%"
				}

			default:
				s = "?" + string(c) + "?";
		}
		p.addstr(s);
	}
}

func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
	prev_string := false;
	for fieldnum := 0; fieldnum < v.Len();  fieldnum++ {
		// always add spaces if we're doing println
		field := v.Field(fieldnum);
		s := "";
		if fieldnum > 0 {
			if addspace {
				p.add(' ')
			} else if field.Kind() != reflect.StringKind && !prev_string{
				// if not doing println, add spaces if neither side is a string
				p.add(' ')
			}
		}
		switch field.Kind() {
		case reflect.BoolKind:
			s = p.fmt.boolean(field.(reflect.BoolValue).Get()).str();
		case reflect.IntKind, reflect.Int8Kind, reflect.Int16Kind, reflect.Int32Kind, reflect.Int64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.d64(v).str();
		case reflect.UintKind, reflect.Uint8Kind, reflect.Uint16Kind, reflect.Uint32Kind, reflect.Uint64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.ud64(uint64(v)).str();
		case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind, reflect.Float80Kind:
			v, ok := getFloat(field);
			s = p.fmt.g64(v).str();
		case reflect.StringKind:
			v, ok := getString(field);
			s = p.fmt.s(v).str();
		case reflect.PtrKind:
			v, ok := getPtr(field);
			p.add('0');
			p.add('x');
			s = p.fmt.uX64(v).str();
		case reflect.StructKind:
			p.add('{');
			p.doprint(field, true, false);
			p.add('}');
		default:
			s = "???";
		}
		p.addstr(s);
		prev_string = field.Kind() == reflect.StringKind;
	}
	if addnewline {
		p.add('\n')
	}
}
<commit_msg>prepare for recursive printfs<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fmt

/*
	C-like printf, but because of reflection knowledge does not need
	to be told about sizes and signedness (no %llud etc. - just %d).
*/

import (
	"fmt";
	"reflect";
	"os";
)

const Runeself = 0x80
const AllocSize = 32

type P struct {
	n	int;
	buf	*[]byte;
	fmt	*Fmt;
}

func Printer() *P {
	p := new(P);
	p.fmt = fmt.New();
	return p;
}

func (p *P) ensure(n int) {
	if p.buf == nil || len(p.buf) < n {
		newn := AllocSize;
		if p.buf != nil {
			newn += len(p.buf);
		}
		if newn < n {
			newn = n + AllocSize
		}
		b := new([]byte, newn);
		for i := 0; i < p.n; i++ {
			b[i] = p.buf[i];
		}
		p.buf = b;
	}
}

func (p *P) addstr(s string) {
	n := len(s);
	p.ensure(p.n + n);
	for i := 0; i < n; i++ {
		p.buf[p.n] = s[i];
		p.n++;
	}
}

func (p *P) addbytes(b *[]byte, start, end int) {
	p.ensure(p.n + end-start);
	for i := start; i < end; i++ {
		p.buf[p.n] = b[i];
		p.n++;
	}
}

func (p *P) add(c int) {
	p.ensure(p.n + 1);
	if c < Runeself {
		p.buf[p.n] = byte(c);
		p.n++;
	} else {
		p.addstr(string(c));
	}
}

// Implement Write so we can call fprintf on a P, for
// recursive use in custom verbs.
func (p *P) Write(b *[]byte) (ret int, err *os.Error) {
	p.addbytes(b, 0, len(b));
	return len(b), nil;
}

export type Writer interface {
	Write(b *[]byte) (ret int, err *os.Error);
}

func (p *P) doprintf(format string, v reflect.StructValue);
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);

// These routines end in 'f' and take a format string.

export func fprintf(w Writer, format string, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p := Printer();
	p.doprintf(format, v);
	n, error = w.Write(p.buf[0:p.n]);
	return n, error;
}

export func printf(format string, v ...) (n int, errno *os.Error) {
	n, errno = fprintf(os.Stdout, format, v);
	return n, errno;
}

export func sprintf(format string, v ...) string {
	p := Printer();
	p.doprintf(format, reflect.NewValue(v).(reflect.StructValue));
	s := string(p.buf)[0 : p.n];
	return s;
}

// These routines do not take a format string and add spaces only
// when the operand on neither side is a string.

export func fprint(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p := Printer();
	p.doprint(v, false, false);
	n, error = w.Write(p.buf[0:p.n]);
	return n, error;
}

export func print(v ...) (n int, errno *os.Error) {
	n, errno = fprint(os.Stdout, v);
	return n, errno;
}

export func sprint(v ...) string {
	p := Printer();
	p.doprint(reflect.NewValue(v).(reflect.StructValue), false, false);
	s := string(p.buf)[0 : p.n];
	return s;
}

// These routines end in 'ln', do not take a format string,
// always add spaces between operands, and add a newline
// after the last operand.

export func fprintln(w Writer, a ...) (n int, error *os.Error) {
	v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
	p := Printer();
	p.doprint(v, true, true);
	n, error = w.Write(p.buf[0:p.n]);
	return n, error;
}

export func println(v ...) (n int, errno *os.Error) {
	n, errno = fprintln(os.Stdout, v);
	return n, errno;
}

export func sprintln(v ...) string {
	p := Printer();
	p.doprint(reflect.NewValue(v).(reflect.StructValue), true, true);
	s := string(p.buf)[0 : p.n];
	return s;
}

// Getters for the fields of the argument structure.

func getInt(v reflect.Value) (val int64, signed, ok bool) {
	switch v.Kind() {
	case reflect.IntKind:
		return int64(v.(reflect.IntValue).Get()), true, true;
	case reflect.Int8Kind:
		return int64(v.(reflect.Int8Value).Get()), true, true;
	case reflect.Int16Kind:
		return int64(v.(reflect.Int16Value).Get()), true, true;
	case reflect.Int32Kind:
		return int64(v.(reflect.Int32Value).Get()), true, true;
	case reflect.Int64Kind:
		return int64(v.(reflect.Int64Value).Get()), true, true;
	case reflect.UintKind:
		return int64(v.(reflect.UintValue).Get()), false, true;
	case reflect.Uint8Kind:
		return int64(v.(reflect.Uint8Value).Get()), false, true;
	case reflect.Uint16Kind:
		return int64(v.(reflect.Uint16Value).Get()), false, true;
	case reflect.Uint32Kind:
		return int64(v.(reflect.Uint32Value).Get()), false, true;
	case reflect.Uint64Kind:
		return int64(v.(reflect.Uint64Value).Get()), false, true;
	}
	return 0, false, false;
}

func getString(v reflect.Value) (val string, ok bool) {
	switch v.Kind() {
	case reflect.StringKind:
		return v.(reflect.StringValue).Get(), true;
	}
	return "", false;
}

func getFloat(v reflect.Value) (val float64, ok bool) {
	switch v.Kind() {
	case reflect.FloatKind:
		return float64(v.(reflect.FloatValue).Get()), true;
	case reflect.Float32Kind:
		return float64(v.(reflect.Float32Value).Get()), true;
	case reflect.Float64Kind:
		return float64(v.(reflect.Float64Value).Get()), true;
	case reflect.Float80Kind:
		break;	// TODO: what to do here?
	}
	return 0.0, false;
}

func getPtr(v reflect.Value) (val uint64, ok bool) {
	switch v.Kind() {
	case reflect.PtrKind:
		return v.(reflect.PtrValue).Get(), true;
	}
	return 0, false;
}

// Convert ASCII to integer.

func parsenum(s string, start, end int) (n int, got bool, newi int) {
	if start >= end {
		return 0, false, end
	}
	if s[start] == '-' {
		a, b, c := parsenum(s, start+1, end);
		if b {
			return -a, b, c;
		}
	}
	isnum := false;
	num := 0;
	for '0' <= s[start] && s[start] <= '9' {
		num = num*10 + int(s[start] - '0');
		start++;
		isnum = true;
	}
	return num, isnum, start;
}

func (p *P) doprintf(format string, v reflect.StructValue) {
	p.ensure(len(format));	// a good starting size
	end := len(format) - 1;
	fieldnum := 0;	// we process one field per non-trivial format
	for i := 0; i <= end;  {
		c, w := sys.stringtorune(format, i);
		if c != '%' || i == end {
			p.add(c);
			i += w;
			continue;
		}
		var got bool;
		// saw % - do we have %20 (width)?
		w, got, i = parsenum(format, i+1, end);
		if got {
			p.fmt.w(w);
		}
		// do we have %.20 (precision)?
		if i < end && format[i] == '.' {
			w, got, i = parsenum(format, i+1, end);
			if got {
				p.fmt.p(w);
			}
		}
		c, w = sys.stringtorune(format, i);
		i += w;
		// percent is special - absorbs no operand
		if c == '%' {
			p.add('%');	// TODO: should we bother with width & prec?
			continue;
		}
		if fieldnum >= v.Len() {	// out of operands
			p.addstr("???");
			continue;
		}
		field := v.Field(fieldnum);
		fieldnum++;
		s := "";
		switch c {
			// bool
			case 't':
				if field.(reflect.BoolValue).Get() {
					s = "true";
				} else {
					s = "false";
				}

			// int
			case 'b':
				if v, signed, ok := getInt(field); ok {
					s = p.fmt.b64(uint64(v)).str()	// always unsigned
				} else {
					s = "%b%"
				}
			case 'd':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.d64(v).str()
					} else {
						s = p.fmt.ud64(uint64(v)).str()
					}
				} else {
					s = "%d%"
				}
			case 'o':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.o64(v).str()
					} else {
						s = p.fmt.uo64(uint64(v)).str()
					}
				} else {
					s= "%o%"
				}
			case 'x':
				if v, signed, ok := getInt(field); ok {
					if signed {
						s = p.fmt.x64(v).str()
					} else {
						s = p.fmt.ux64(uint64(v)).str()
					}
				} else {
					s = "%x%"
				}

			// float
			case 'e':
				if v, ok := getFloat(field); ok {
					s = p.fmt.e64(v).str()
				} else {
					s = "%e%"
				}
			case 'f':
				if v, ok := getFloat(field); ok {
					s = p.fmt.f64(v).str()
				} else {
					s = "%f%";
				}
			case 'g':
				if v, ok := getFloat(field); ok {
					s = p.fmt.g64(v).str()
				} else {
					s = "%g%"
				}

			// string
			case 's':
				if v, ok := getString(field); ok {
					s = p.fmt.s(v).str()
				} else {
					s = "%s%"
				}

			// pointer
			case 'p':
				if v, ok := getPtr(field); ok {
					s = "0x" + p.fmt.uX64(v).str()
				} else {
					s = "%p%"
				}

			default:
				s = "?" + string(c) + "?";
		}
		p.addstr(s);
	}
}

func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
	prev_string := false;
	for fieldnum := 0; fieldnum < v.Len();  fieldnum++ {
		// always add spaces if we're doing println
		field := v.Field(fieldnum);
		s := "";
		if fieldnum > 0 {
			if addspace {
				p.add(' ')
			} else if field.Kind() != reflect.StringKind && !prev_string{
				// if not doing println, add spaces if neither side is a string
				p.add(' ')
			}
		}
		switch field.Kind() {
		case reflect.BoolKind:
			s = p.fmt.boolean(field.(reflect.BoolValue).Get()).str();
		case reflect.IntKind, reflect.Int8Kind, reflect.Int16Kind, reflect.Int32Kind, reflect.Int64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.d64(v).str();
		case reflect.UintKind, reflect.Uint8Kind, reflect.Uint16Kind, reflect.Uint32Kind, reflect.Uint64Kind:
			v, signed, ok := getInt(field);
			s = p.fmt.ud64(uint64(v)).str();
		case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind, reflect.Float80Kind:
			v, ok := getFloat(field);
			s = p.fmt.g64(v).str();
		case reflect.StringKind:
			v, ok := getString(field);
			s = p.fmt.s(v).str();
		case reflect.PtrKind:
			v, ok := getPtr(field);
			p.add('0');
			p.add('x');
			s = p.fmt.uX64(v).str();
		case reflect.StructKind:
			p.add('{');
			p.doprint(field, true, false);
			p.add('}');
		default:
			s = "???";
		}
		p.addstr(s);
		prev_string = field.Kind() == reflect.StringKind;
	}
	if addnewline {
		p.add('\n')
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Nan Deng
 *
 * 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 push

import (
	"fmt"
	"time"
)

// PushError is a specialized error. It is used for errors which cause the push backend to take actions.
type PushError interface {
	error
	isPushError() // Placeholder function to distinguish these from error class
}

type implementsPushError struct{}

func (*implementsPushError) isPushError() {}

var _ PushError = &InfoReport{}
var _ PushError = &ErrorReport{}
var _ PushError = &RetryError{}
var _ PushError = &PushServiceProviderUpdate{}
var _ PushError = &DeliveryPointUpdate{}
var _ PushError = &IncompatibleError{}
var _ PushError = &BadDeliveryPoint{}
var _ PushError = &BadPushServiceProvider{}
var _ PushError = &UnsubscribeUpdate{}
var _ PushError = &InvalidRegistrationUpdate{}
var _ PushError = &ConnectionError{}

// This is not an actual error.
// But it is worthy to be reported to the user.
type InfoReport struct {
	implementsPushError
	info string
}

func (e *InfoReport) Error() string {
	return e.info
}

func NewInfo(msg string) *InfoReport {
	return &InfoReport{info: msg}
}

func NewInfof(f string, v ...interface{}) *InfoReport {
	return &InfoReport{info: fmt.Sprintf(f, v...)}
}

// ErrorReport is like InfoReport, but has a higher severity.
type ErrorReport struct {
	implementsPushError
	msg string
}

func (e *ErrorReport) Error() string {
	return e.msg
}

func NewError(msg string) *ErrorReport {
	return &ErrorReport{msg: msg}
}

func NewErrorf(f string, v ...interface{}) *ErrorReport {
	return &ErrorReport{msg: fmt.Sprintf(f, v...)}
}

/*********************/

type RetryError struct {
	implementsPushError
	After       time.Duration
	Provider    *PushServiceProvider
	Destination *DeliveryPoint
	Content     *Notification
	Reason      error
}

func (e *RetryError) Error() string {
	if e.Reason != nil {
		return fmt.Sprintf("Retry (%v)", e.Reason)
	}
	return fmt.Sprintf("Retry")
}

func NewRetryErrorWithReason(psp *PushServiceProvider, dp *DeliveryPoint, notif *Notification, after time.Duration, reason error) *RetryError {
	return &RetryError{
		After:       after,
		Provider:    psp,
		Destination: dp,
		Content:     notif,
		Reason:      reason,
	}
}

func NewRetryError(psp *PushServiceProvider, dp *DeliveryPoint, notif *Notification, after time.Duration) *RetryError {
	return &RetryError{
		After:       after,
		Provider:    psp,
		Destination: dp,
		Content:     notif,
	}
}

/*********************/

type PushServiceProviderUpdate struct {
	implementsPushError
	Provider *PushServiceProvider
}

func (e *PushServiceProviderUpdate) Error() string {
	return fmt.Sprintf("PushServiceProvider=%v Update", e.Provider.Name())
}

func NewPushServiceProviderUpdate(psp *PushServiceProvider) *PushServiceProviderUpdate {
	return &PushServiceProviderUpdate{Provider: psp}
}

/*********************/

type DeliveryPointUpdate struct {
	implementsPushError
	Destination *DeliveryPoint
}

func (e *DeliveryPointUpdate) Error() string {
	return fmt.Sprintf("DeliveryPoint=%v Update", e.Destination.Name())
}

func NewDeliveryPointUpdate(dp *DeliveryPoint) *DeliveryPointUpdate {
	return &DeliveryPointUpdate{Destination: dp}
}

/*********************/

type IncompatibleError struct {
	implementsPushError
}

func (e *IncompatibleError) Error() string {
	return fmt.Sprintf("Incompatible")
}

func NewIncompatibleError() *IncompatibleError {
	return &IncompatibleError{}
}

/*********************/

type BadDeliveryPoint struct {
	implementsPushError
	Destination *DeliveryPoint
	Details     string
}

func (e *BadDeliveryPoint) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("BadDeliveryPoint %v: %v", e.Destination.Name(), e.Details)
	}
	return fmt.Sprintf("BadDeliveryPoint %v", e.Destination.Name())
}

func NewBadDeliveryPoint(dp *DeliveryPoint) *BadDeliveryPoint {
	return &BadDeliveryPoint{Destination: dp, Details: ""}
}

func NewBadDeliveryPointWithDetails(dp *DeliveryPoint, details string) *BadDeliveryPoint {
	return &BadDeliveryPoint{Destination: dp, Details: details}
}

/*********************/

type BadPushServiceProvider struct {
	implementsPushError
	Provider *PushServiceProvider
	Details  string
}

func (e *BadPushServiceProvider) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("BadPushServiceProvider %v: %v", e.Provider.Name(), e.Details)
	}
	return fmt.Sprintf("BadPushServiceProvider %v", e.Provider.Name())
}

func NewBadPushServiceProvider(psp *PushServiceProvider) *BadPushServiceProvider {
	return &BadPushServiceProvider{Provider: psp, Details: ""}
}

func NewBadPushServiceProviderWithDetails(psp *PushServiceProvider, details string) *BadPushServiceProvider {
	return &BadPushServiceProvider{Provider: psp, Details: details}
}

/*********************/

type BadNotification struct {
	implementsPushError
	Details string
}

func (e *BadNotification) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("Bad Notification: %s", e.Details)
	}
	return fmt.Sprintf("Bad Notification")
}

func NewBadNotification() *BadNotification {
	return &BadNotification{Details: ""}
}

func NewBadNotificationWithDetails(details string) *BadNotification {
	return &BadNotification{Details: details}
}

/*********************/

type UnsubscribeUpdate struct {
	implementsPushError
	Provider    *PushServiceProvider
	Destination *DeliveryPoint
}

func (e *UnsubscribeUpdate) Error() string {
	return fmt.Sprintf("RequestUnsubscribe %v", e.Destination.Name())
}

func NewUnsubscribeUpdate(psp *PushServiceProvider, dp *DeliveryPoint) *UnsubscribeUpdate {
	return &UnsubscribeUpdate{
		Provider:    psp,
		Destination: dp,
	}
}

/*********************/

type InvalidRegistrationUpdate struct {
	implementsPushError
	Provider    *PushServiceProvider
	Destination *DeliveryPoint
}

func (e *InvalidRegistrationUpdate) Error() string {
	return fmt.Sprintf("InvalidRegistration dropping %v", e.Destination.Name())
}

func NewInvalidRegistrationUpdate(psp *PushServiceProvider, dp *DeliveryPoint) *InvalidRegistrationUpdate {
	return &InvalidRegistrationUpdate{
		Provider:    psp,
		Destination: dp,
	}
}

/*********************/

type ConnectionError struct {
	implementsPushError
	Err error
}

func (e *ConnectionError) Error() string {
	return fmt.Sprintf("ConnectionError %v", e)
}

func NewConnectionError(err error) *ConnectionError {
	return &ConnectionError{Err: err}
}
<commit_msg>Fix stack overflow in errors<commit_after>/*
 * Copyright 2011 Nan Deng
 *
 * 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 push

import (
	"fmt"
	"time"
)

// PushError is a specialized error. It is used for errors which cause the push backend to take actions.
type PushError interface {
	error
	isPushError() // Placeholder function to distinguish these from error class
}

type implementsPushError struct{}

func (*implementsPushError) isPushError() {}

var _ PushError = &InfoReport{}
var _ PushError = &ErrorReport{}
var _ PushError = &RetryError{}
var _ PushError = &PushServiceProviderUpdate{}
var _ PushError = &DeliveryPointUpdate{}
var _ PushError = &IncompatibleError{}
var _ PushError = &BadDeliveryPoint{}
var _ PushError = &BadPushServiceProvider{}
var _ PushError = &UnsubscribeUpdate{}
var _ PushError = &InvalidRegistrationUpdate{}
var _ PushError = &ConnectionError{}

// This is not an actual error.
// But it is worthy to be reported to the user.
type InfoReport struct {
	implementsPushError
	info string
}

func (e *InfoReport) Error() string {
	return e.info
}

func NewInfo(msg string) *InfoReport {
	return &InfoReport{info: msg}
}

func NewInfof(f string, v ...interface{}) *InfoReport {
	return &InfoReport{info: fmt.Sprintf(f, v...)}
}

// ErrorReport is like InfoReport, but has a higher severity.
type ErrorReport struct {
	implementsPushError
	msg string
}

func (e *ErrorReport) Error() string {
	return e.msg
}

func NewError(msg string) *ErrorReport {
	return &ErrorReport{msg: msg}
}

func NewErrorf(f string, v ...interface{}) *ErrorReport {
	return &ErrorReport{msg: fmt.Sprintf(f, v...)}
}

/*********************/

type RetryError struct {
	implementsPushError
	After       time.Duration
	Provider    *PushServiceProvider
	Destination *DeliveryPoint
	Content     *Notification
	Reason      error
}

func (e *RetryError) Error() string {
	if e.Reason != nil {
		return fmt.Sprintf("Retry (%v)", e.Reason)
	}
	return fmt.Sprintf("Retry")
}

func NewRetryErrorWithReason(psp *PushServiceProvider, dp *DeliveryPoint, notif *Notification, after time.Duration, reason error) *RetryError {
	return &RetryError{
		After:       after,
		Provider:    psp,
		Destination: dp,
		Content:     notif,
		Reason:      reason,
	}
}

func NewRetryError(psp *PushServiceProvider, dp *DeliveryPoint, notif *Notification, after time.Duration) *RetryError {
	return &RetryError{
		After:       after,
		Provider:    psp,
		Destination: dp,
		Content:     notif,
	}
}

/*********************/

type PushServiceProviderUpdate struct {
	implementsPushError
	Provider *PushServiceProvider
}

func (e *PushServiceProviderUpdate) Error() string {
	return fmt.Sprintf("PushServiceProvider=%v Update", e.Provider.Name())
}

func NewPushServiceProviderUpdate(psp *PushServiceProvider) *PushServiceProviderUpdate {
	return &PushServiceProviderUpdate{Provider: psp}
}

/*********************/

type DeliveryPointUpdate struct {
	implementsPushError
	Destination *DeliveryPoint
}

func (e *DeliveryPointUpdate) Error() string {
	return fmt.Sprintf("DeliveryPoint=%v Update", e.Destination.Name())
}

func NewDeliveryPointUpdate(dp *DeliveryPoint) *DeliveryPointUpdate {
	return &DeliveryPointUpdate{Destination: dp}
}

/*********************/

type IncompatibleError struct {
	implementsPushError
}

func (e *IncompatibleError) Error() string {
	return fmt.Sprintf("Incompatible")
}

func NewIncompatibleError() *IncompatibleError {
	return &IncompatibleError{}
}

/*********************/

type BadDeliveryPoint struct {
	implementsPushError
	Destination *DeliveryPoint
	Details     string
}

func (e *BadDeliveryPoint) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("BadDeliveryPoint %v: %v", e.Destination.Name(), e.Details)
	}
	return fmt.Sprintf("BadDeliveryPoint %v", e.Destination.Name())
}

func NewBadDeliveryPoint(dp *DeliveryPoint) *BadDeliveryPoint {
	return &BadDeliveryPoint{Destination: dp, Details: ""}
}

func NewBadDeliveryPointWithDetails(dp *DeliveryPoint, details string) *BadDeliveryPoint {
	return &BadDeliveryPoint{Destination: dp, Details: details}
}

/*********************/

type BadPushServiceProvider struct {
	implementsPushError
	Provider *PushServiceProvider
	Details  string
}

func (e *BadPushServiceProvider) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("BadPushServiceProvider %v: %v", e.Provider.Name(), e.Details)
	}
	return fmt.Sprintf("BadPushServiceProvider %v", e.Provider.Name())
}

func NewBadPushServiceProvider(psp *PushServiceProvider) *BadPushServiceProvider {
	return &BadPushServiceProvider{Provider: psp, Details: ""}
}

func NewBadPushServiceProviderWithDetails(psp *PushServiceProvider, details string) *BadPushServiceProvider {
	return &BadPushServiceProvider{Provider: psp, Details: details}
}

/*********************/

type BadNotification struct {
	implementsPushError
	Details string
}

func (e *BadNotification) Error() string {
	if e.Details != "" {
		return fmt.Sprintf("Bad Notification: %s", e.Details)
	}
	return fmt.Sprintf("Bad Notification")
}

func NewBadNotification() *BadNotification {
	return &BadNotification{Details: ""}
}

func NewBadNotificationWithDetails(details string) *BadNotification {
	return &BadNotification{Details: details}
}

/*********************/

type UnsubscribeUpdate struct {
	implementsPushError
	Provider    *PushServiceProvider
	Destination *DeliveryPoint
}

func (e *UnsubscribeUpdate) Error() string {
	return fmt.Sprintf("RequestUnsubscribe %v", e.Destination.Name())
}

func NewUnsubscribeUpdate(psp *PushServiceProvider, dp *DeliveryPoint) *UnsubscribeUpdate {
	return &UnsubscribeUpdate{
		Provider:    psp,
		Destination: dp,
	}
}

/*********************/

type InvalidRegistrationUpdate struct {
	implementsPushError
	Provider    *PushServiceProvider
	Destination *DeliveryPoint
}

func (e *InvalidRegistrationUpdate) Error() string {
	return fmt.Sprintf("InvalidRegistration dropping %v", e.Destination.Name())
}

func NewInvalidRegistrationUpdate(psp *PushServiceProvider, dp *DeliveryPoint) *InvalidRegistrationUpdate {
	return &InvalidRegistrationUpdate{
		Provider:    psp,
		Destination: dp,
	}
}

/*********************/

type ConnectionError struct {
	implementsPushError
	Err error
}

func (e *ConnectionError) Error() string {
	return fmt.Sprintf("ConnectionError %v", e.Err)
}

func NewConnectionError(err error) *ConnectionError {
	return &ConnectionError{Err: err}
}
<|endoftext|>


<commit_before>package putio

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	defaultUserAgent = "go-putio"
	defaultMediaType = "application/json"
	defaultBaseURL   = "https://api.put.io"
	defaultUploadURL = "https://upload.put.io"
)

// errors
var (
	ErrResourceNotFound = fmt.Errorf("resource does not exist")
	ErrPaymentRequired  = fmt.Errorf("payment required")

	errRedirect   = fmt.Errorf("redirect attempt on a no-redirect client")
	errNegativeID = fmt.Errorf("file id cannot be negative")
)

// Client manages communication with Put.io v2 API.
type Client struct {
	// HTTP client used to communicate with Put.io API
	client *http.Client

	// Base URL for API requests.
	BaseURL *url.URL

	// User agent for client
	UserAgent string

	// Services used for communicating with the API
	Account   *AccountService
	Files     *FilesService
	Transfers *TransfersService
	Zips      *ZipsService
	Friends   *FriendsService
	Events    *EventsService
}

// NewClient returns a new Put.io API client, using the htttpClient, which must
// be a new Oauth2 enabled http.Client. If httpClient is not defined, default
// HTTP client is used.
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	baseURL, _ := url.Parse(defaultBaseURL)
	c := &Client{
		client:    httpClient,
		BaseURL:   baseURL,
		UserAgent: defaultUserAgent,
	}
	c.Account = &AccountService{client: c}
	c.Files = &FilesService{client: c}
	c.Transfers = &TransfersService{client: c}
	c.Zips = &ZipsService{client: c}
	c.Friends = &FriendsService{client: c}
	c.Events = &EventsService{client: c}

	return c
}

// NewRequest creates an API request. A relative URL can be provided via
// relURL, which will be resolved to the BaseURL of the Client.
func (c *Client) NewRequest(method, relURL string, body io.Reader) (*http.Request, error) {
	rel, err := url.Parse(relURL)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)
	req, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Accept", defaultMediaType)
	req.Header.Set("User-Agent", c.UserAgent)

	return req, nil
}

// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred. Response body is closed at all cases except
// v is nil. If v is nil, response body is not closed and the body can be used
// for streaming.
func (c *Client) Do(r *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(r)
	if err != nil {
		return nil, err
	}

	err = checkResponse(resp)
	if err != nil {
		// close the body at all times if there is an http error.
		resp.Body.Close()
		return resp, err
	}

	if v == nil {
		return resp, nil
	}

	// close the body for all cases from here.
	defer resp.Body.Close()

	err = json.NewDecoder(resp.Body).Decode(v)
	if err != nil {
		return resp, err
	}

	return resp, nil
}

// redirectOnceFunc follows the redirect only once, and copies the original
// request headers to the new one.
func redirectOnceFunc(req *http.Request, via []*http.Request) error {
	if len(via) == 0 {
		return nil
	}

	if len(via) > 1 {
		return errRedirect
	}

	// merge headers with request headers
	for header, values := range via[0].Header {
		for _, value := range values {
			req.Header.Add(header, value)
		}
	}
	return nil
}

// ErrorResponse reports the error caused by an API request.
type ErrorResponse struct {
	Response *http.Response `json:"-"`

	Message string `json:"error_message"`
	Type    string `json:"error_type"`
}

func (e *ErrorResponse) Error() string {
	return fmt.Sprintf(
		"Type: %v Message: %q. Original error: %v %v: %v",
		e.Type,
		e.Message,
		e.Response.Request.Method,
		e.Response.Request.URL,
		e.Response.Status,
	)
}

// checkResponse is the entrypoint to reading the API response. If the response
// status code is not in success range, it will try to return a structured
// error.
func checkResponse(r *http.Response) error {
	statusCode := r.StatusCode
	if statusCode >= 200 && statusCode <= 299 {
		return nil
	}

	if statusCode == http.StatusNotFound {
		return ErrResourceNotFound
	}

	if statusCode == http.StatusPaymentRequired {
		return ErrPaymentRequired
	}

	errorResponse := &ErrorResponse{Response: r}
	data, err := ioutil.ReadAll(r.Body)
	if err == nil && len(data) > 0 {
		err = json.Unmarshal(data, errorResponse)
		if err != nil {
			return err
		}
	}
	return errorResponse
}
<commit_msg>putio: remove stale comment<commit_after>package putio

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	defaultUserAgent = "go-putio"
	defaultMediaType = "application/json"
	defaultBaseURL   = "https://api.put.io"
	defaultUploadURL = "https://upload.put.io"
)

var (
	ErrResourceNotFound = fmt.Errorf("resource does not exist")
	ErrPaymentRequired  = fmt.Errorf("payment required")

	errRedirect   = fmt.Errorf("redirect attempt on a no-redirect client")
	errNegativeID = fmt.Errorf("file id cannot be negative")
)

// Client manages communication with Put.io v2 API.
type Client struct {
	// HTTP client used to communicate with Put.io API
	client *http.Client

	// Base URL for API requests.
	BaseURL *url.URL

	// User agent for client
	UserAgent string

	// Services used for communicating with the API
	Account   *AccountService
	Files     *FilesService
	Transfers *TransfersService
	Zips      *ZipsService
	Friends   *FriendsService
	Events    *EventsService
}

// NewClient returns a new Put.io API client, using the htttpClient, which must
// be a new Oauth2 enabled http.Client. If httpClient is not defined, default
// HTTP client is used.
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	baseURL, _ := url.Parse(defaultBaseURL)
	c := &Client{
		client:    httpClient,
		BaseURL:   baseURL,
		UserAgent: defaultUserAgent,
	}
	c.Account = &AccountService{client: c}
	c.Files = &FilesService{client: c}
	c.Transfers = &TransfersService{client: c}
	c.Zips = &ZipsService{client: c}
	c.Friends = &FriendsService{client: c}
	c.Events = &EventsService{client: c}

	return c
}

// NewRequest creates an API request. A relative URL can be provided via
// relURL, which will be resolved to the BaseURL of the Client.
func (c *Client) NewRequest(method, relURL string, body io.Reader) (*http.Request, error) {
	rel, err := url.Parse(relURL)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)
	req, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Accept", defaultMediaType)
	req.Header.Set("User-Agent", c.UserAgent)

	return req, nil
}

// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred. Response body is closed at all cases except
// v is nil. If v is nil, response body is not closed and the body can be used
// for streaming.
func (c *Client) Do(r *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(r)
	if err != nil {
		return nil, err
	}

	err = checkResponse(resp)
	if err != nil {
		// close the body at all times if there is an http error.
		resp.Body.Close()
		return resp, err
	}

	if v == nil {
		return resp, nil
	}

	// close the body for all cases from here.
	defer resp.Body.Close()

	err = json.NewDecoder(resp.Body).Decode(v)
	if err != nil {
		return resp, err
	}

	return resp, nil
}

// redirectOnceFunc follows the redirect only once, and copies the original
// request headers to the new one.
func redirectOnceFunc(req *http.Request, via []*http.Request) error {
	if len(via) == 0 {
		return nil
	}

	if len(via) > 1 {
		return errRedirect
	}

	// merge headers with request headers
	for header, values := range via[0].Header {
		for _, value := range values {
			req.Header.Add(header, value)
		}
	}
	return nil
}

// ErrorResponse reports the error caused by an API request.
type ErrorResponse struct {
	Response *http.Response `json:"-"`

	Message string `json:"error_message"`
	Type    string `json:"error_type"`
}

func (e *ErrorResponse) Error() string {
	return fmt.Sprintf(
		"Type: %v Message: %q. Original error: %v %v: %v",
		e.Type,
		e.Message,
		e.Response.Request.Method,
		e.Response.Request.URL,
		e.Response.Status,
	)
}

// checkResponse is the entrypoint to reading the API response. If the response
// status code is not in success range, it will try to return a structured
// error.
func checkResponse(r *http.Response) error {
	statusCode := r.StatusCode
	if statusCode >= 200 && statusCode <= 299 {
		return nil
	}

	if statusCode == http.StatusNotFound {
		return ErrResourceNotFound
	}

	if statusCode == http.StatusPaymentRequired {
		return ErrPaymentRequired
	}

	errorResponse := &ErrorResponse{Response: r}
	data, err := ioutil.ReadAll(r.Body)
	if err == nil && len(data) > 0 {
		err = json.Unmarshal(data, errorResponse)
		if err != nil {
			return err
		}
	}
	return errorResponse
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"fmt"

	"github.com/pions/webrtc"
)

func main() {
	peerConnection, err := webrtc.New(&webrtc.RTCConfiguration{
		ICEServers: []webrtc.RTCICEServer{
			{
				URLs: []string{"stun:stun.l.google.com:19302"},
			},
		},
	})
	if err != nil {
		panic(err)
	}

	if err := peerConnection.CreateAnswer(); err != nil {
		panic(err)
	}

	localDescriptionStr := peerConnection.LocalDescription.Marshal()
	fmt.Println(base64.StdEncoding.EncodeToString([]byte(localDescriptionStr)))
	select {}
}
<commit_msg>add remote description to STUN example<commit_after>package main

import (
	"bufio"
	"encoding/base64"
	"fmt"
	"os"

	"github.com/pions/webrtc"
	"github.com/pions/webrtc/pkg/ice"
	"github.com/pions/webrtc/pkg/rtp"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	rawSd, err := reader.ReadString('\n')
	if err != nil {
		panic(err)
	}

	fmt.Println("")
	sd, err := base64.StdEncoding.DecodeString(rawSd)
	if err != nil {
		panic(err)
	}

	peerConnection, err := webrtc.New(&webrtc.RTCConfiguration{
		ICEServers: []webrtc.RTCICEServer{
			{
				URLs: []string{"stun:stun.l.google.com:19302"},
			},
		},
	})
	if err != nil {
		panic(err)
	}

	peerConnection.Ontrack = func(mediaType webrtc.TrackType, packets <-chan *rtp.Packet) {
		fmt.Printf("Got a %s track\n", mediaType)
	}

	peerConnection.OnICEConnectionStateChange = func(connectionState ice.ConnectionState) {
		fmt.Printf("Connection State has changed %s \n", connectionState.String())
	}

	if err := peerConnection.SetRemoteDescription(string(sd)); err != nil {
		panic(err)
	}

	if err := peerConnection.CreateAnswer(); err != nil {
		panic(err)
	}

	localDescriptionStr := peerConnection.LocalDescription.Marshal()
	fmt.Println(base64.StdEncoding.EncodeToString([]byte(localDescriptionStr)))
	select {}
}
<|endoftext|>


<commit_before>// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

package postgres

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/gofrs/uuid"
	"github.com/jmoiron/sqlx"
	"github.com/lib/pq" // required for DB access
	"github.com/mainflux/mainflux/consumers"
	"github.com/mainflux/mainflux/pkg/errors"
	mfjson "github.com/mainflux/mainflux/pkg/transformers/json"
	"github.com/mainflux/mainflux/pkg/transformers/senml"
)

const (
	errInvalid        = "invalid_text_representation"
	errUndefinedTable = "undefined_table"
)

var (
	errInvalidMessage = errors.New("invalid message representation")
	errSaveMessage    = errors.New("failed to save message to postgres database")
	errTransRollback  = errors.New("failed to rollback transaction")
	errMessageFormat  = errors.New("invalid message format")
	errNoMessages     = errors.New("empty message")
	errNoTable        = errors.New("relation does not exist")
)

var _ consumers.Consumer = (*postgresRepo)(nil)

type postgresRepo struct {
	db *sqlx.DB
}

// New returns new PostgreSQL writer.
func New(db *sqlx.DB) consumers.Consumer {
	return &postgresRepo{db: db}
}

func (pr postgresRepo) Consume(message interface{}) (err error) {
	switch m := message.(type) {
	case mfjson.Messages:
		return pr.saveJSON(m)
	default:
		return pr.saveSenml(m)
	}
}

func (pr postgresRepo) saveSenml(messages interface{}) error {
	msgs, ok := messages.([]senml.Message)
	if !ok {
		return errSaveMessage
	}
	q := `INSERT INTO messages (id, channel, subtopic, publisher, protocol,
          name, unit, value, string_value, bool_value, data_value, sum,
          time, update_time)
          VALUES (:id, :channel, :subtopic, :publisher, :protocol, :name, :unit,
          :value, :string_value, :bool_value, :data_value, :sum,
          :time, :update_time);`

	tx, err := pr.db.BeginTxx(context.Background(), nil)
	if err != nil {
		return errors.Wrap(errSaveMessage, err)
	}
	defer func() {
		if err != nil {
			if txErr := tx.Rollback(); txErr != nil {
				err = errors.Wrap(err, errors.Wrap(errTransRollback, txErr))
			}
			return
		}

		if err = tx.Commit(); err != nil {
			err = errors.Wrap(errSaveMessage, err)
		}
		return
	}()

	for _, msg := range msgs {
		id, err := uuid.NewV4()
		if err != nil {
			return err
		}
		m := senmlMessage{Message: msg, ID: id.String()}
		if _, err := tx.NamedExec(q, m); err != nil {
			pqErr, ok := err.(*pq.Error)
			if ok {
				switch pqErr.Code.Name() {
				case errInvalid:
					return errors.Wrap(errSaveMessage, errInvalidMessage)
				}
			}

			return errors.Wrap(errSaveMessage, err)
		}
	}
	return err
}

func (pr postgresRepo) saveJSON(msgs mfjson.Messages) error {
	if err := pr.insertJSON(msgs); err != nil {
		if err == errNoTable {
			if err := pr.createTable(msgs.Format); err != nil {
				return err
			}
			return pr.insertJSON(msgs)
		}
		return err
	}
	return nil
}

func (pr postgresRepo) insertJSON(msgs mfjson.Messages) error {
	tx, err := pr.db.BeginTxx(context.Background(), nil)
	if err != nil {
		return errors.Wrap(errSaveMessage, err)
	}
	defer func() {
		if err != nil {
			if txErr := tx.Rollback(); txErr != nil {
				err = errors.Wrap(err, errors.Wrap(errTransRollback, txErr))
			}
			return
		}

		if err = tx.Commit(); err != nil {
			err = errors.Wrap(errSaveMessage, err)
		}
		return
	}()

	q := `INSERT INTO %s (id, channel, created, subtopic, publisher, protocol, payload)
          VALUES (:id, :channel, :created, :subtopic, :publisher, :protocol, :payload);`
	q = fmt.Sprintf(q, msgs.Format)

	for _, m := range msgs.Data {
		var dbmsg jsonMessage
		dbmsg, err = toJSONMessage(m)
		if err != nil {
			return errors.Wrap(errSaveMessage, err)
		}
		if _, err = tx.NamedExec(q, dbmsg); err != nil {
			pqErr, ok := err.(*pq.Error)
			if ok {
				switch pqErr.Code.Name() {
				case errInvalid:
					return errors.Wrap(errSaveMessage, errInvalidMessage)
				case errUndefinedTable:
					return errNoTable
				}
			}
			return err
		}
	}
	return nil
}

func (pr postgresRepo) createTable(name string) error {
	q := `CREATE TABLE IF NOT EXISTS %s (
                        id            UUID,
                        created       BIGINT,
                        channel       VARCHAR(254),
                        subtopic      VARCHAR(254),
                        publisher     VARCHAR(254),
                        protocol      TEXT,
                        payload       JSONB,
                        PRIMARY KEY (id)
                    )`
	q = fmt.Sprintf(q, name)

	_, err := pr.db.Exec(q)
	return err
}

type senmlMessage struct {
	senml.Message
	ID string `db:"id"`
}

type jsonMessage struct {
	ID        string `db:"id"`
	Channel   string `db:"channel"`
	Created   int64  `db:"created"`
	Subtopic  string `db:"subtopic"`
	Publisher string `db:"publisher"`
	Protocol  string `db:"protocol"`
	Payload   []byte `db:"payload"`
}

func toJSONMessage(msg mfjson.Message) (jsonMessage, error) {
	id, err := uuid.NewV4()
	if err != nil {
		return jsonMessage{}, err
	}

	data := []byte("{}")
	if msg.Payload != nil {
		b, err := json.Marshal(msg.Payload)
		if err != nil {
			return jsonMessage{}, errors.Wrap(errSaveMessage, err)
		}
		data = b
	}

	m := jsonMessage{
		ID:        id.String(),
		Channel:   msg.Channel,
		Created:   msg.Created,
		Subtopic:  msg.Subtopic,
		Publisher: msg.Publisher,
		Protocol:  msg.Protocol,
		Payload:   data,
	}

	return m, nil
}
<commit_msg>Fix Postgres writer transaction handling (#1335)<commit_after>// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

package postgres

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/gofrs/uuid"
	"github.com/jmoiron/sqlx"
	"github.com/lib/pq" // required for DB access
	"github.com/mainflux/mainflux/consumers"
	"github.com/mainflux/mainflux/pkg/errors"
	mfjson "github.com/mainflux/mainflux/pkg/transformers/json"
	"github.com/mainflux/mainflux/pkg/transformers/senml"
)

const (
	errInvalid        = "invalid_text_representation"
	errUndefinedTable = "undefined_table"
)

var (
	errInvalidMessage = errors.New("invalid message representation")
	errSaveMessage    = errors.New("failed to save message to postgres database")
	errTransRollback  = errors.New("failed to rollback transaction")
	errMessageFormat  = errors.New("invalid message format")
	errNoMessages     = errors.New("empty message")
	errNoTable        = errors.New("relation does not exist")
)

var _ consumers.Consumer = (*postgresRepo)(nil)

type postgresRepo struct {
	db *sqlx.DB
}

// New returns new PostgreSQL writer.
func New(db *sqlx.DB) consumers.Consumer {
	return &postgresRepo{db: db}
}

func (pr postgresRepo) Consume(message interface{}) (err error) {
	switch m := message.(type) {
	case mfjson.Messages:
		return pr.saveJSON(m)
	default:
		return pr.saveSenml(m)
	}
}

func (pr postgresRepo) saveSenml(messages interface{}) (err error) {
	msgs, ok := messages.([]senml.Message)
	if !ok {
		return errSaveMessage
	}
	q := `INSERT INTO messages (id, channel, subtopic, publisher, protocol,
          name, unit, value, string_value, bool_value, data_value, sum,
          time, update_time)
          VALUES (:id, :channel, :subtopic, :publisher, :protocol, :name, :unit,
          :value, :string_value, :bool_value, :data_value, :sum,
          :time, :update_time);`

	tx, err := pr.db.BeginTxx(context.Background(), nil)
	if err != nil {
		return errors.Wrap(errSaveMessage, err)
	}
	defer func() {
		if err != nil {
			if txErr := tx.Rollback(); txErr != nil {
				err = errors.Wrap(err, errors.Wrap(errTransRollback, txErr))
			}
			return
		}

		if err = tx.Commit(); err != nil {
			err = errors.Wrap(errSaveMessage, err)
		}
		return
	}()

	for _, msg := range msgs {
		id, err := uuid.NewV4()
		if err != nil {
			return err
		}
		m := senmlMessage{Message: msg, ID: id.String()}
		if _, err := tx.NamedExec(q, m); err != nil {
			pqErr, ok := err.(*pq.Error)
			if ok {
				switch pqErr.Code.Name() {
				case errInvalid:
					return errors.Wrap(errSaveMessage, errInvalidMessage)
				}
			}

			return errors.Wrap(errSaveMessage, err)
		}
	}
	return err
}

func (pr postgresRepo) saveJSON(msgs mfjson.Messages) error {
	if err := pr.insertJSON(msgs); err != nil {
		if err == errNoTable {
			if err := pr.createTable(msgs.Format); err != nil {
				return err
			}
			return pr.insertJSON(msgs)
		}
		return err
	}
	return nil
}

func (pr postgresRepo) insertJSON(msgs mfjson.Messages) error {
	tx, err := pr.db.BeginTxx(context.Background(), nil)
	if err != nil {
		return errors.Wrap(errSaveMessage, err)
	}
	defer func() {
		if err != nil {
			if txErr := tx.Rollback(); txErr != nil {
				err = errors.Wrap(err, errors.Wrap(errTransRollback, txErr))
			}
			return
		}

		if err = tx.Commit(); err != nil {
			err = errors.Wrap(errSaveMessage, err)
		}
		return
	}()

	q := `INSERT INTO %s (id, channel, created, subtopic, publisher, protocol, payload)
          VALUES (:id, :channel, :created, :subtopic, :publisher, :protocol, :payload);`
	q = fmt.Sprintf(q, msgs.Format)

	for _, m := range msgs.Data {
		var dbmsg jsonMessage
		dbmsg, err = toJSONMessage(m)
		if err != nil {
			return errors.Wrap(errSaveMessage, err)
		}
		if _, err = tx.NamedExec(q, dbmsg); err != nil {
			pqErr, ok := err.(*pq.Error)
			if ok {
				switch pqErr.Code.Name() {
				case errInvalid:
					return errors.Wrap(errSaveMessage, errInvalidMessage)
				case errUndefinedTable:
					return errNoTable
				}
			}
			return err
		}
	}
	return nil
}

func (pr postgresRepo) createTable(name string) error {
	q := `CREATE TABLE IF NOT EXISTS %s (
                        id            UUID,
                        created       BIGINT,
                        channel       VARCHAR(254),
                        subtopic      VARCHAR(254),
                        publisher     VARCHAR(254),
                        protocol      TEXT,
                        payload       JSONB,
                        PRIMARY KEY (id)
                    )`
	q = fmt.Sprintf(q, name)

	_, err := pr.db.Exec(q)
	return err
}

type senmlMessage struct {
	senml.Message
	ID string `db:"id"`
}

type jsonMessage struct {
	ID        string `db:"id"`
	Channel   string `db:"channel"`
	Created   int64  `db:"created"`
	Subtopic  string `db:"subtopic"`
	Publisher string `db:"publisher"`
	Protocol  string `db:"protocol"`
	Payload   []byte `db:"payload"`
}

func toJSONMessage(msg mfjson.Message) (jsonMessage, error) {
	id, err := uuid.NewV4()
	if err != nil {
		return jsonMessage{}, err
	}

	data := []byte("{}")
	if msg.Payload != nil {
		b, err := json.Marshal(msg.Payload)
		if err != nil {
			return jsonMessage{}, errors.Wrap(errSaveMessage, err)
		}
		data = b
	}

	m := jsonMessage{
		ID:        id.String(),
		Channel:   msg.Channel,
		Created:   msg.Created,
		Subtopic:  msg.Subtopic,
		Publisher: msg.Publisher,
		Protocol:  msg.Protocol,
		Payload:   data,
	}

	return m, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Kubernetes Authors.

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

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

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

package testutil

import (
	"fmt"
	"io"
	"strings"

	"github.com/prometheus/client_golang/prometheus/testutil/promlint"
)

// exceptionMetrics is an exception list of metrics which violates promlint rules.
//
// The original entries come from the existing metrics when we introduce promlint.
// We setup this list for allow and not fail on the current violations.
// Generally speaking, you need to fix the problem for a new metric rather than add it into the list.
var exceptionMetrics = []string{
	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/egressselector
	"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/healthz
	"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/filters
	"authenticated_user_requests", // counter metrics should have "_total" suffix
	"authentication_attempts",     // counter metrics should have "_total" suffix

	// kube-apiserver
	"aggregator_openapi_v2_regeneration_count",
	"apiserver_admission_step_admission_duration_seconds_summary",
	"apiserver_current_inflight_requests",
	"apiserver_longrunning_gauge",
	"get_token_count",
	"get_token_fail_count",
	"ssh_tunnel_open_count",
	"ssh_tunnel_open_fail_count",

	// kube-controller-manager
	"attachdetach_controller_forced_detaches",
	"authenticated_user_requests",
	"authentication_attempts",
	"get_token_count",
	"get_token_fail_count",
	"node_collector_evictions_number",

	// k8s.io/kubernetes/pkg/kubelet/server/stats
	// The two metrics have been deprecated and will be removed in release v1.20+.
	"container_cpu_usage_seconds_total", // non-counter metrics should not have "_total" suffix
	"node_cpu_usage_seconds_total",      // non-counter metrics should not have "_total" suffix
}

// A Problem is an issue detected by a Linter.
type Problem promlint.Problem

func (p *Problem) String() string {
	return fmt.Sprintf("%s:%s", p.Metric, p.Text)
}

// A Linter is a Prometheus metrics linter.  It identifies issues with metric
// names, types, and metadata, and reports them to the caller.
type Linter struct {
	promLinter *promlint.Linter
}

// Lint performs a linting pass, returning a slice of Problems indicating any
// issues found in the metrics stream.  The slice is sorted by metric name
// and issue description.
func (l *Linter) Lint() ([]Problem, error) {
	promProblems, err := l.promLinter.Lint()
	if err != nil {
		return nil, err
	}

	// Ignore problems those in exception list
	problems := make([]Problem, 0, len(promProblems))
	for i := range promProblems {
		if !l.shouldIgnore(promProblems[i].Metric) {
			problems = append(problems, Problem(promProblems[i]))
		}
	}

	return problems, nil
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func (l *Linter) shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// NewPromLinter creates a new Linter that reads an input stream of Prometheus metrics.
// Only the text exposition format is supported.
func NewPromLinter(r io.Reader) *Linter {
	return &Linter{
		promLinter: promlint.New(r),
	}
}

func mergeProblems(problems []Problem) string {
	var problemsMsg []string

	for index := range problems {
		problemsMsg = append(problemsMsg, problems[index].String())
	}

	return strings.Join(problemsMsg, ",")
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// getLintError will ignore the metrics in exception list and converts lint problem to error.
func getLintError(problems []promlint.Problem) error {
	var filteredProblems []Problem
	for _, problem := range problems {
		if shouldIgnore(problem.Metric) {
			continue
		}

		filteredProblems = append(filteredProblems, Problem(problem))
	}

	if len(filteredProblems) == 0 {
		return nil
	}

	return fmt.Errorf("lint error: %s", mergeProblems(filteredProblems))
}
<commit_msg>Remove two metrics that have been deprecated<commit_after>/*
Copyright 2020 The Kubernetes Authors.

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

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

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

package testutil

import (
	"fmt"
	"io"
	"strings"

	"github.com/prometheus/client_golang/prometheus/testutil/promlint"
)

// exceptionMetrics is an exception list of metrics which violates promlint rules.
//
// The original entries come from the existing metrics when we introduce promlint.
// We setup this list for allow and not fail on the current violations.
// Generally speaking, you need to fix the problem for a new metric rather than add it into the list.
var exceptionMetrics = []string{
	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/egressselector
	"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/server/healthz
	"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'

	// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/filters
	"authenticated_user_requests", // counter metrics should have "_total" suffix
	"authentication_attempts",     // counter metrics should have "_total" suffix

	// kube-apiserver
	"aggregator_openapi_v2_regeneration_count",
	"apiserver_admission_step_admission_duration_seconds_summary",
	"apiserver_current_inflight_requests",
	"apiserver_longrunning_gauge",
	"get_token_count",
	"get_token_fail_count",
	"ssh_tunnel_open_count",
	"ssh_tunnel_open_fail_count",

	// kube-controller-manager
	"attachdetach_controller_forced_detaches",
	"authenticated_user_requests",
	"authentication_attempts",
	"get_token_count",
	"get_token_fail_count",
	"node_collector_evictions_number",
}

// A Problem is an issue detected by a Linter.
type Problem promlint.Problem

func (p *Problem) String() string {
	return fmt.Sprintf("%s:%s", p.Metric, p.Text)
}

// A Linter is a Prometheus metrics linter.  It identifies issues with metric
// names, types, and metadata, and reports them to the caller.
type Linter struct {
	promLinter *promlint.Linter
}

// Lint performs a linting pass, returning a slice of Problems indicating any
// issues found in the metrics stream.  The slice is sorted by metric name
// and issue description.
func (l *Linter) Lint() ([]Problem, error) {
	promProblems, err := l.promLinter.Lint()
	if err != nil {
		return nil, err
	}

	// Ignore problems those in exception list
	problems := make([]Problem, 0, len(promProblems))
	for i := range promProblems {
		if !l.shouldIgnore(promProblems[i].Metric) {
			problems = append(problems, Problem(promProblems[i]))
		}
	}

	return problems, nil
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func (l *Linter) shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// NewPromLinter creates a new Linter that reads an input stream of Prometheus metrics.
// Only the text exposition format is supported.
func NewPromLinter(r io.Reader) *Linter {
	return &Linter{
		promLinter: promlint.New(r),
	}
}

func mergeProblems(problems []Problem) string {
	var problemsMsg []string

	for index := range problems {
		problemsMsg = append(problemsMsg, problems[index].String())
	}

	return strings.Join(problemsMsg, ",")
}

// shouldIgnore returns true if metric in the exception list, otherwise returns false.
func shouldIgnore(metricName string) bool {
	for i := range exceptionMetrics {
		if metricName == exceptionMetrics[i] {
			return true
		}
	}

	return false
}

// getLintError will ignore the metrics in exception list and converts lint problem to error.
func getLintError(problems []promlint.Problem) error {
	var filteredProblems []Problem
	for _, problem := range problems {
		if shouldIgnore(problem.Metric) {
			continue
		}

		filteredProblems = append(filteredProblems, Problem(problem))
	}

	if len(filteredProblems) == 0 {
		return nil
	}

	return fmt.Errorf("lint error: %s", mergeProblems(filteredProblems))
}
<|endoftext|>


<commit_before>package python

import (
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/toolchain"
)

func runCmdLogError(cmd *exec.Cmd) {
	err := runCmdStderr(cmd)
	if err != nil {
		log.Printf("Error running `%s`: %s", strings.Join(cmd.Args, " "), err)
	}
}

func runCmdStderr(cmd *exec.Cmd) error {
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stderr
	return cmd.Run()
}

func getVENVBinPath() (string, error) {
	if os.Getenv("IN_DOCKER_CONTAINER") == "" {
		tc, err := toolchain.Lookup("sourcegraph.com/sourcegraph/srclib-python")
		if err != nil {
			return "", err
		}
		return filepath.Join(tc.Dir, ".env", "bin"), nil
	}
	return "", nil
}
<commit_msg>Fix `goimports` fail, no idea how it compiles on local machine.<commit_after>package python

import (
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/srclib/toolchain"
)

func runCmdLogError(cmd *exec.Cmd) {
	err := runCmdStderr(cmd)
	if err != nil {
		log.Printf("Error running `%s`: %s", strings.Join(cmd.Args, " "), err)
	}
}

func runCmdStderr(cmd *exec.Cmd) error {
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stderr
	return cmd.Run()
}

func getVENVBinPath() (string, error) {
	if os.Getenv("IN_DOCKER_CONTAINER") == "" {
		tc, err := toolchain.Lookup("sourcegraph.com/sourcegraph/srclib-python")
		if err != nil {
			return "", err
		}
		return filepath.Join(tc.Dir, ".env", "bin"), nil
	}
	return "", nil
}
<|endoftext|>


<commit_before>package qBT

import (
	"encoding/json"
)

// https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-Documentation

type JsonMap map[string]interface{}

type TorrentInfo struct {
	Id             ID      //   Transmission's ID
	Hash           Hash    //	Torrent hash
	Name           string  //	Torrent name
	Size           int64   //	Total size (bytes) of files selected for download
	Total_size     int64   //	Torrent total size (bytes)
	Progress       float64 //	Torrent progress (percentage/100)
	Dlspeed        int     //	Torrent download speed (bytes/s)
	Upspeed        int     //	Torrent upload speed (bytes/s)
	Priority       int     //	Torrent priority. Returns -1 if queuing is disabled or torrent is in seed mode
	Num_seeds      int     //	Number of seeds connected to
	Num_complete   int     //	Number of seeds in the swarm
	Num_leechs     int     //	Number of leechers connected to
	Num_incomplete int     //	Number of leechers in the swarm
	Ratio          float64 //	Torrent share ratio. Max ratio value: 9999.
	Eta            uint64  //	Torrent ETA (seconds)
	State          string  //	Torrent state. See table here below for the possible values
	Seq_dl         bool    //	True if sequential download is enabled
	F_l_piece_prio bool    //	True if first last piece are prioritized
	Label          string  //	Label of the torrent
	Super_seeding  bool    //	True if super seeding is enabled
	Force_start    bool    //	True if force start is enabled for this torrent
	Save_path      string  //	Torrent save path
	Added_on       int64
	Completion_on  int64 //   Torrent completion time
}

type PeerInfo struct {
	Up_speed   int
	Uploaded   int64
	Dl_speed   int
	Port       int
	Downloaded int64
	Client     string
	Country    string
	Flags      string
	IP         string
	Progress   float64 //	Torrent progress (percentage/100)
}

type PropertiesGeneral struct {
	Save_path                string  //	Torrent save path
	Creation_date            int64   //	Torrent creation date (Unix timestamp)
	Piece_size               int     //	Torrent piece size (bytes)
	Comment                  string  //	Torrent comment
	Total_wasted             int64   //	Total data wasted for torrent (bytes)
	Total_uploaded           int64   //	Total data uploaded for torrent (bytes)
	Total_uploaded_session   int64   //	Total data uploaded this session (bytes)
	Total_downloaded         int64   //	Total data uploaded for torrent (bytes)
	Total_downloaded_session int64   //	Total data downloaded this session (bytes)
	Up_limit                 int     //	Torrent upload limit (bytes/s)
	Dl_limit                 int     //	Torrent download limit (bytes/s)
	Time_elapsed             int     //	Torrent elapsed time (seconds)
	Seeding_time             int     //	Torrent elapsed time while complete (seconds)
	Nb_connections           int     //	Torrent connection count
	Nb_connections_limit     int     //	Torrent connection count limit
	Share_ratio              float64 //	Torrent share ratio
	Addition_date            int64   //	When this torrent was added (unix timestamp)
	Completion_date          int64   //	Torrent completion date (unix timestamp)
	Created_by               string  //	Torrent creator
	Dl_speed_avg             int     //	Torrent average download speed (bytes/second)
	Dl_speed                 int     //	Torrent download speed (bytes/second)
	Eta                      uint64  //	Torrent ETA (seconds)
	Last_seen                int64   //	Last seen complete date (unix timestamp)
	Peers                    int     //	Number of peers connected to
	Peers_total              int     //	Number of peers in the swarm
	Pieces_have              int     //	Number of pieces owned
	Pieces_num               int     //	Number of pieces of the torrent
	Reannounce               int64   //	Number of seconds until the next announce
	Seeds                    int     //	Number of seeds connected to
	Seeds_total              int     //	Number of seeds in the swarm
	Total_size               int64   //	Torrent total size (bytes)
	Up_speed_avg             int     //	Torrent average upload speed (bytes/second)
	Up_speed                 int     //	Torrent upload speed (bytes/second)
}

type PropertiesTrackers struct {
	Url       string //	Tracker url
	Status    int    //	Tracker status. See the table below for possible values
	Num_peers int    //	Number of peers for current torrent reported by the tracker
	Msg       string // Tracker message (there is no way of knowing what this message is - it's up to tracker admins)
}

type PropertiesFiles struct {
	Name     string  //	File name (including relative path)
	Size     int64   //	File size (bytes)
	Progress float64 //	File progress (percentage/100)
	Priority int     //	File priority. See possible values here below
	Is_seed  bool    //	True if file is seeding/complete
}

type TransferInfo struct {
	Dl_info_speed     int    //	Global download rate (bytes/s)
	Dl_info_data      int64  //	Data downloaded this session (bytes)
	Up_info_speed     int    //	Global upload rate (bytes/s)
	Up_info_data      int64  //	Data uploaded this session (bytes)
	Dl_rate_limit     int    //	Download rate limit (bytes/s)
	Up_rate_limit     int    //	Upload rate limit (bytes/s)
	Dht_nodes         int    //	DHT nodes connected to
	Connection_status string //	Connection status. See possible values here below
}

type MainData struct {
	Rid                int
	Full_update        bool
	Torrents           *json.RawMessage
	Torrents_removed   []Hash
	Categories         *json.RawMessage
	Categories_removed *json.RawMessage
	Queueing           bool
	Server_state       *TransferInfo
}

type Preferences struct {
	Locale                         string      //	Currently selected language (e.g. en_GB for english)
	Save_path                      string      //	Default save path for torrents, separated by slashes
	Temp_path_enabled              bool        //	True if folder for incomplete torrents is enabled
	Temp_path                      string      //	Path for incomplete torrents, separated by slashes
	Scan_dirs                      interface{} //	List of watch folders to add torrent automatically; slashes are used as path separators; list entries are separated by commas
	Download_in_scan_dirs          []bool      //	True if torrents should be downloaded to watch folder; list entries are separated by commas
	Export_dir_enabled             bool        //	True if .torrent file should be copied to export directory upon adding
	Export_dir                     string      //	Path to directory to copy .torrent files ifexport_dir_enabled is enabled; path is separated by slashes
	Mail_notification_enabled      bool        //	True if e-mail notification should be enabled
	Mail_notification_email        string      //	e-mail to send notifications to
	Mail_notification_smtp         string      //	smtp server for e-mail notifications
	Mail_notification_ssl_enabled  bool        //	True if smtp server requires SSL connection
	Mail_notification_auth_enabled bool        //	True if smtp server requires authentication
	Mail_notification_username     string      //	Username for smtp authentication
	Mail_notification_password     string      //	Password for smtp authentication
	Autorun_enabled                bool        //	True if external program should be run after torrent has finished downloading
	Autorun_program                string      //	Program path/name/arguments to run ifautorun_enabled is enabled; path is separated by slashes; you can use %f and%n arguments, which will be expanded by qBittorent as path_to_torrent_file and torrent_name (from the GUI; not the .torrent file name) respectively
	Preallocate_all                bool        //	True if file preallocation should take place, otherwise sparse files are used
	Queueing_enabled               bool        //	True if torrent queuing is enabled
	Max_active_downloads           int         //	Maximum number of active simultaneous downloads
	Max_active_torrents            int         //	Maximum number of active simultaneous downloads and uploads
	Max_active_uploads             int         //	Maximum number of active simultaneous uploads
	Dont_count_slow_torrents       bool        //	If true torrents w/o any activity (stalled ones) will not be counted towards max_active_*limits; see dont_count_slow_torrents for more information
	Max_ratio_enabled              bool        //	True if share ratio limit is enabled
	Max_ratio                      float64     //	Get the global share ratio limit
	Max_ratio_act                  int         //	Action performed when a torrent reaches the maximum share ratio. See list of possible values here below.
	Incomplete_files_ext           bool        //	If true .!qB extension will be appended to incomplete files
	Listen_port                    int         //	Port for incoming connections
	Upnp                           bool        //	True if UPnP/NAT-PMP is enabled
	Random_port                    bool        //	True if the port is randomly selected
	Dl_limit                       int         //	Global download speed limit in B/s; -1means no limit is applied
	Up_limit                       int         //	Global upload speed limit in B/s; -1means no limit is applied
	Max_connec                     int         //	Maximum global number of simultaneous connections
	Max_connec_per_torrent         int         //	Maximum number of simultaneous connections per torrent
	Max_uploads                    int         //	Maximum number of upload slots
	Max_uploads_per_torrent        int         //	Maximum number of upload slots per torrent
	Enable_utp                     bool        //	True if uTP protocol should be enabled; this option is only available in qBittorent built against libtorrent version 0.16.X and higher
	Limit_utp_rate                 bool        //	True if [du]l_limit should be applied to uTP connections; this option is only available in qBittorent built against libtorrent version 0.16.X and higher
	Limit_tcp_overhead             bool        //	True if [du]l_limit should be applied to estimated TCP overhead (service data: e.g. packet headers)
	Alt_dl_limit                   int         //	Alternative global download speed limit in KiB/s
	Alt_up_limit                   int         //	Alternative global upload speed limit in KiB/s
	Scheduler_enabled              bool        //	True if alternative limits should be applied according to schedule
	Schedule_from_hour             int         //	Scheduler starting hour
	Schedule_from_min              int         //	Scheduler starting minute
	Schedule_to_hour               int         //	Scheduler ending hour
	Schedule_to_min                int         //	Scheduler ending minute
	Scheduler_days                 int         //	Scheduler days. See possible values here below
	Dht                            bool        //	True if DHT is enabled
	DhtSameAsBT                    bool        //	True if DHT port should match TCP port
	Dht_port                       int         //	DHT port if dhtSameAsBT is false
	Pex                            bool        //	True if PeX is enabled
	Lsd                            bool        //	True if LSD is eanbled
	Encryption                     int         //	See list of possible values here below
	Anonymous_mode                 bool        //	If true anonymous mode will be enabled; read more here; this option is only available in qBittorent built against libtorrent version 0.16.X and higher
	Proxy_type                     int         //	See list of possible values here below
	Proxy_ip                       string      //	Proxy Address address or domain name
	Proxy_port                     int         //	Proxy port
	Proxy_peer_connections         bool        //	True if peer and web seed connections should be proxified; this option will have any effect only in qBittorent built against libtorrent version 0.16.X and higher
	Force_proxy                    bool        //	True if the connections not supported by the proxy are disabled
	Proxy_auth_enabled             bool        //	True proxy requires authentication; doesn't apply to SOCKS4 proxies
	Proxy_username                 string      //	Username for proxy authentication
	Proxy_password                 string      //	Password for proxy authentication
	Ip_filter_enabled              bool        //	True if external Address filter should be enabled
	Ip_filter_path                 string      //	Path to Address filter file (.dat, .p2p, .p2b files are supported); path is separated by slashes
	Ip_filter_trackers             bool        //	True if Address filters are applied to trackers
	Web_ui_port                    int         //	WebUI port
	Web_ui_upnp                    bool        //	True if UPnP is used for the WebUI port
	Web_ui_username                string      //	WebUI username
	Web_ui_password                string      //	MD5 hash of WebUI password; hash is generated from the following string:username:Web UI Access:plain_text_web_ui_password
	Bypass_local_auth              bool        //	True if auithetication challenge for loopback address (127.0.0.1) should be disabled
	Use_https                      bool        //	True if WebUI HTTPS access is eanbled
	Ssl_key                        string      //	SSL keyfile contents (this is a not a path)
	Ssl_cert                       string      //	SSL certificate contents (this is a not a path)
	Dyndns_enabled                 bool        //	True if server DNS should be updated dynamically
	Dyndns_service                 int         //	See list of possible values here below
	Dyndns_username                string      //	Username for DDNS service
	Dyndns_password                string      //	Password for DDNS service
	Dyndns_domain                  string      //	Your DDNS domain name
}
<commit_msg>Fixes for qBittorrent 4.2.0<commit_after>package qBT

import (
	"encoding/json"
)

// https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-Documentation

type JsonMap map[string]interface{}

type TorrentInfo struct {
	Id             ID      //   Transmission's ID
	Hash           Hash    //	Torrent hash
	Name           string  //	Torrent name
	Size           int64   //	Total size (bytes) of files selected for download
	Total_size     int64   //	Torrent total size (bytes)
	Progress       float64 //	Torrent progress (percentage/100)
	Dlspeed        int     //	Torrent download speed (bytes/s)
	Upspeed        int     //	Torrent upload speed (bytes/s)
	Priority       int     //	Torrent priority. Returns -1 if queuing is disabled or torrent is in seed mode
	Num_seeds      int     //	Number of seeds connected to
	Num_complete   int     //	Number of seeds in the swarm
	Num_leechs     int     //	Number of leechers connected to
	Num_incomplete int     //	Number of leechers in the swarm
	Ratio          float64 //	Torrent share ratio. Max ratio value: 9999.
	Eta            int64   //	Torrent ETA (seconds)
	State          string  //	Torrent state. See table here below for the possible values
	Seq_dl         bool    //	True if sequential download is enabled
	F_l_piece_prio bool    //	True if first last piece are prioritized
	Label          string  //	Label of the torrent
	Super_seeding  bool    //	True if super seeding is enabled
	Force_start    bool    //	True if force start is enabled for this torrent
	Save_path      string  //	Torrent save path
	Added_on       int64
	Completion_on  int64 //   Torrent completion time
}

type PeerInfo struct {
	Up_speed   int
	Uploaded   int64
	Dl_speed   int
	Port       int
	Downloaded int64
	Client     string
	Country    string
	Flags      string
	IP         string
	Progress   float64 //	Torrent progress (percentage/100)
}

type PropertiesGeneral struct {
	Save_path                string  //	Torrent save path
	Creation_date            int64   //	Torrent creation date (Unix timestamp)
	Piece_size               int     //	Torrent piece size (bytes)
	Comment                  string  //	Torrent comment
	Total_wasted             int64   //	Total data wasted for torrent (bytes)
	Total_uploaded           int64   //	Total data uploaded for torrent (bytes)
	Total_uploaded_session   int64   //	Total data uploaded this session (bytes)
	Total_downloaded         int64   //	Total data uploaded for torrent (bytes)
	Total_downloaded_session int64   //	Total data downloaded this session (bytes)
	Up_limit                 int     //	Torrent upload limit (bytes/s)
	Dl_limit                 int     //	Torrent download limit (bytes/s)
	Time_elapsed             int     //	Torrent elapsed time (seconds)
	Seeding_time             int     //	Torrent elapsed time while complete (seconds)
	Nb_connections           int     //	Torrent connection count
	Nb_connections_limit     int     //	Torrent connection count limit
	Share_ratio              float64 //	Torrent share ratio
	Addition_date            int64   //	When this torrent was added (unix timestamp)
	Completion_date          int64   //	Torrent completion date (unix timestamp)
	Created_by               string  //	Torrent creator
	Dl_speed_avg             int     //	Torrent average download speed (bytes/second)
	Dl_speed                 int     //	Torrent download speed (bytes/second)
	Eta                      int64   //	Torrent ETA (seconds)
	Last_seen                int64   //	Last seen complete date (unix timestamp)
	Peers                    int     //	Number of peers connected to
	Peers_total              int     //	Number of peers in the swarm
	Pieces_have              int     //	Number of pieces owned
	Pieces_num               int     //	Number of pieces of the torrent
	Reannounce               int64   //	Number of seconds until the next announce
	Seeds                    int     //	Number of seeds connected to
	Seeds_total              int     //	Number of seeds in the swarm
	Total_size               int64   //	Torrent total size (bytes)
	Up_speed_avg             int     //	Torrent average upload speed (bytes/second)
	Up_speed                 int     //	Torrent upload speed (bytes/second)
}

type PropertiesTrackers struct {
	Url       string //	Tracker url
	Status    int    //	Tracker status. See the table below for possible values
	Num_peers int    //	Number of peers for current torrent reported by the tracker
	Msg       string // Tracker message (there is no way of knowing what this message is - it's up to tracker admins)
}

type PropertiesFiles struct {
	Name     string  //	File name (including relative path)
	Size     int64   //	File size (bytes)
	Progress float64 //	File progress (percentage/100)
	Priority int     //	File priority. See possible values here below
	Is_seed  bool    //	True if file is seeding/complete
}

type TransferInfo struct {
	Dl_info_speed     int    //	Global download rate (bytes/s)
	Dl_info_data      int64  //	Data downloaded this session (bytes)
	Up_info_speed     int    //	Global upload rate (bytes/s)
	Up_info_data      int64  //	Data uploaded this session (bytes)
	Dl_rate_limit     int    //	Download rate limit (bytes/s)
	Up_rate_limit     int    //	Upload rate limit (bytes/s)
	Dht_nodes         int    //	DHT nodes connected to
	Connection_status string //	Connection status. See possible values here below
}

type MainData struct {
	Rid                int
	Full_update        bool
	Torrents           *json.RawMessage
	Torrents_removed   []Hash
	Categories         *json.RawMessage
	Categories_removed *json.RawMessage
	Queueing           bool
	Server_state       *TransferInfo
}

type Preferences struct {
	Locale                         string      //	Currently selected language (e.g. en_GB for english)
	Save_path                      string      //	Default save path for torrents, separated by slashes
	Temp_path_enabled              bool        //	True if folder for incomplete torrents is enabled
	Temp_path                      string      //	Path for incomplete torrents, separated by slashes
	Scan_dirs                      interface{} //	List of watch folders to add torrent automatically; slashes are used as path separators; list entries are separated by commas
	Download_in_scan_dirs          []bool      //	True if torrents should be downloaded to watch folder; list entries are separated by commas
	Export_dir_enabled             bool        //	True if .torrent file should be copied to export directory upon adding
	Export_dir                     string      //	Path to directory to copy .torrent files ifexport_dir_enabled is enabled; path is separated by slashes
	Mail_notification_enabled      bool        //	True if e-mail notification should be enabled
	Mail_notification_email        string      //	e-mail to send notifications to
	Mail_notification_smtp         string      //	smtp server for e-mail notifications
	Mail_notification_ssl_enabled  bool        //	True if smtp server requires SSL connection
	Mail_notification_auth_enabled bool        //	True if smtp server requires authentication
	Mail_notification_username     string      //	Username for smtp authentication
	Mail_notification_password     string      //	Password for smtp authentication
	Autorun_enabled                bool        //	True if external program should be run after torrent has finished downloading
	Autorun_program                string      //	Program path/name/arguments to run ifautorun_enabled is enabled; path is separated by slashes; you can use %f and%n arguments, which will be expanded by qBittorent as path_to_torrent_file and torrent_name (from the GUI; not the .torrent file name) respectively
	Preallocate_all                bool        //	True if file preallocation should take place, otherwise sparse files are used
	Queueing_enabled               bool        //	True if torrent queuing is enabled
	Max_active_downloads           int         //	Maximum number of active simultaneous downloads
	Max_active_torrents            int         //	Maximum number of active simultaneous downloads and uploads
	Max_active_uploads             int         //	Maximum number of active simultaneous uploads
	Dont_count_slow_torrents       bool        //	If true torrents w/o any activity (stalled ones) will not be counted towards max_active_*limits; see dont_count_slow_torrents for more information
	Max_ratio_enabled              bool        //	True if share ratio limit is enabled
	Max_ratio                      float64     //	Get the global share ratio limit
	Max_ratio_act                  int         //	Action performed when a torrent reaches the maximum share ratio. See list of possible values here below.
	Incomplete_files_ext           bool        //	If true .!qB extension will be appended to incomplete files
	Listen_port                    int         //	Port for incoming connections
	Upnp                           bool        //	True if UPnP/NAT-PMP is enabled
	Random_port                    bool        //	True if the port is randomly selected
	Dl_limit                       int         //	Global download speed limit in B/s; -1means no limit is applied
	Up_limit                       int         //	Global upload speed limit in B/s; -1means no limit is applied
	Max_connec                     int         //	Maximum global number of simultaneous connections
	Max_connec_per_torrent         int         //	Maximum number of simultaneous connections per torrent
	Max_uploads                    int         //	Maximum number of upload slots
	Max_uploads_per_torrent        int         //	Maximum number of upload slots per torrent
	Enable_utp                     bool        //	True if uTP protocol should be enabled; this option is only available in qBittorent built against libtorrent version 0.16.X and higher
	Limit_utp_rate                 bool        //	True if [du]l_limit should be applied to uTP connections; this option is only available in qBittorent built against libtorrent version 0.16.X and higher
	Limit_tcp_overhead             bool        //	True if [du]l_limit should be applied to estimated TCP overhead (service data: e.g. packet headers)
	Alt_dl_limit                   int         //	Alternative global download speed limit in KiB/s
	Alt_up_limit                   int         //	Alternative global upload speed limit in KiB/s
	Scheduler_enabled              bool        //	True if alternative limits should be applied according to schedule
	Schedule_from_hour             int         //	Scheduler starting hour
	Schedule_from_min              int         //	Scheduler starting minute
	Schedule_to_hour               int         //	Scheduler ending hour
	Schedule_to_min                int         //	Scheduler ending minute
	Scheduler_days                 int         //	Scheduler days. See possible values here below
	Dht                            bool        //	True if DHT is enabled
	DhtSameAsBT                    bool        //	True if DHT port should match TCP port
	Dht_port                       int         //	DHT port if dhtSameAsBT is false
	Pex                            bool        //	True if PeX is enabled
	Lsd                            bool        //	True if LSD is eanbled
	Encryption                     int         //	See list of possible values here below
	Anonymous_mode                 bool        //	If true anonymous mode will be enabled; read more here; this option is only available in qBittorent built against libtorrent version 0.16.X and higher
	Proxy_type                     int         //	See list of possible values here below
	Proxy_ip                       string      //	Proxy Address address or domain name
	Proxy_port                     int         //	Proxy port
	Proxy_peer_connections         bool        //	True if peer and web seed connections should be proxified; this option will have any effect only in qBittorent built against libtorrent version 0.16.X and higher
	Force_proxy                    bool        //	True if the connections not supported by the proxy are disabled
	Proxy_auth_enabled             bool        //	True proxy requires authentication; doesn't apply to SOCKS4 proxies
	Proxy_username                 string      //	Username for proxy authentication
	Proxy_password                 string      //	Password for proxy authentication
	Ip_filter_enabled              bool        //	True if external Address filter should be enabled
	Ip_filter_path                 string      //	Path to Address filter file (.dat, .p2p, .p2b files are supported); path is separated by slashes
	Ip_filter_trackers             bool        //	True if Address filters are applied to trackers
	Web_ui_port                    int         //	WebUI port
	Web_ui_upnp                    bool        //	True if UPnP is used for the WebUI port
	Web_ui_username                string      //	WebUI username
	Web_ui_password                string      //	MD5 hash of WebUI password; hash is generated from the following string:username:Web UI Access:plain_text_web_ui_password
	Bypass_local_auth              bool        //	True if auithetication challenge for loopback address (127.0.0.1) should be disabled
	Use_https                      bool        //	True if WebUI HTTPS access is eanbled
	Ssl_key                        string      //	SSL keyfile contents (this is a not a path)
	Ssl_cert                       string      //	SSL certificate contents (this is a not a path)
	Dyndns_enabled                 bool        //	True if server DNS should be updated dynamically
	Dyndns_service                 int         //	See list of possible values here below
	Dyndns_username                string      //	Username for DDNS service
	Dyndns_password                string      //	Password for DDNS service
	Dyndns_domain                  string      //	Your DDNS domain name
}
<|endoftext|>