Saving Images in Golang from Base64 String - base64

I am using a Wacom signature set to capture a signature in JS as a Base64 string. Then I send this Base64 string to my Golang server and save it into DB.
When I then want to save this Base64 String as an image I always get an error "Bad png".
All converters can open the Base64 Strings without problems.
Here is my function and Base64 String as an example.
func saveImageTest()
{
im1 := "" //Link to the string is below
idx := strings.Index(im1, ";base64,")
if idx < 0 {
fmt.Println("InvalidImage")
}
ImageType := im1[11:idx]
fmt.Println(ImageType)
unbased, err := base64.StdEncoding.DecodeString(im1)
if err != nil {
log.Println("Cannot decode b64")
}
r := bytes.NewReader(unbased)
im, err := png.Decode(r)
if err != nil {
log.Println("Bad png")
}
f, err := os.OpenFile("example.png", os.O_WRONLY|os.O_CREATE, 0777)
if err != nil {
log.Println("Cannot open file")
}
png.Encode(f, im)
}
Link to the Base64 String
Test signature

You must start DecodeString at idx + 8 (after ";base64,").

Related

How to convert a string value to the correct reflect.Kind in go?

Is there a generic helper method in Go to convert a string to the correct value based on reflect.Kind?
Or do I need to implement the switch over all kinds myself?
I have a value like "143" as a string and a reflect.Value with kind "UInt16" and like to convert that string value and set it into the UInt16 value of my struct.
My current code looks like:
func setValueFromString(v reflect.Value, strVal string) error {
switch v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
val, err := strconv.ParseInt(strVal, 0, 64)
if err != nil {
return err
}
if v.OverflowInt(val) {
return errors.New("Int value too big: " + strVal)
}
v.SetInt(val)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
val, err := strconv.ParseUint(strVal, 0, 64)
if err != nil {
return err
}
if v.OverflowUint(val) {
return errors.New("UInt value too big: " + strVal)
}
v.SetUint(val)
case reflect.Float32:
val, err := strconv.ParseFloat(strVal, 32)
if err != nil {
return err
}
v.SetFloat(val)
case reflect.Float64:
val, err := strconv.ParseFloat(strVal, 64)
if err != nil {
return err
}
v.SetFloat(val)
case reflect.String:
v.SetString(strVal)
case reflect.Bool:
val, err := strconv.ParseBool(strVal)
if err != nil {
return err
}
v.SetBool(val)
default:
return errors.New("Unsupported kind: " + v.Kind().String())
}
return nil
}
This works already, but I wonder if this is already implemented somewhere else.
Edit: Answer to the original question ("how to obtain a reflect.Kind from its string representation") is at the end. Answer to your edited question follows:
What you're doing is the fastest and "safest". If you don't want to hassle with that big switch, you may take advantage of e.g. the json package which already contains this switch to decode values from JSON string (in encoding/json/decode.go, unexported function literalStore()).
Your decoding function could look like this:
func Set(v interface{}, s string) error {
return json.Unmarshal([]byte(s), v)
}
A simple call to json.Unmarshal(). Using / testing it:
{
var v int
err := Set(&v, "1")
fmt.Println(v, err)
}
{
var v int
err := Set(&v, "d")
fmt.Println(v, err)
}
{
var v uint32
err := Set(&v, "3")
fmt.Println(v, err)
}
{
var v bool
err := Set(&v, "true")
fmt.Println(v, err)
}
{
var v float32
err := Set(&v, `5.1`)
fmt.Println(v, err)
}
{
var v string
err := Set(&v, strconv.Quote("abc"))
fmt.Println(v, err)
}
One thing to note: when you want to pass a string, that must be quoted, e.g. with strconv.Quote(). Output (try it on the Go Playground):
1 <nil>
0 invalid character 'd' looking for beginning of value
3 <nil>
true <nil>
5.1 <nil>
abc <nil>
If you don't want to require quoted strings (which just complicates things), you may build it into the Set() function:
func Set(v interface{}, s string) error {
if t := reflect.TypeOf(v); t.Kind() == reflect.Ptr &&
t.Elem().Kind() == reflect.String {
s = strconv.Quote(s)
}
return json.Unmarshal([]byte(s), v)
}
And then you may call it with the address of a string variable and a string value unquoted:
var v string
err := Set(&v, "abc")
fmt.Println(v, err)
Try this variant on the Go Playground.
Answer to the original question: how to obtain a reflect.Kind from its string representation:
Declaration of reflect.Kind:
type Kind uint
The different values of reflect.Kinds are constants:
const (
Invalid Kind = iota
Bool
Int
Int8
// ...
Struct
UnsafePointer
)
And the reflect package provides only a single method for the reflect.Kind() type:
func (k Kind) String() string
So as it stands, you cannot obtain a reflect.Kind from its string representation (only the reverse direction is possible by using the Kind.String() method). But it's not that hard to provide this functionality.
What we'll do is we build a map from all the kinds:
var strKindMap = map[string]reflect.Kind{}
We init it like this:
func init() {
for k := reflect.Invalid; k <= reflect.UnsafePointer; k++ {
strKindMap[k.String()] = k
}
}
This is possible and correct because constants are initialized using iota which evaluates to successive untyped integer constants, and the first value is reflect.Invalid and the last is reflect.UnsafePointer.
And now you can obtain reflect.Kind from its string representation by simply indexing this map. A helper function which does that:
func strToKind(s string) reflect.Kind {
k, ok := strKindMap[s]
if !ok {
return reflect.Invalid
}
return k
}
And we're done. Testing / using it:
fmt.Printf("All: %#v\n", strKindMap)
for _, v := range []string{"Hey", "uint8", "ptr", "func", "chan", "interface"} {
fmt.Printf("String: %q, Kind: %v (%#v)\n", v, strToKind(v), strToKind(v))
}
Output (try it on the Go Playground):
All: map[string]reflect.Kind{"int64":0x6, "uint8":0x8, "uint64":0xb, "slice":0x17, "uintptr":0xc, "int8":0x3, "array":0x11, "interface":0x14, "unsafe.Pointer":0x1a, "complex64":0xf, "complex128":0x10, "int":0x2, "uint":0x7, "int16":0x4, "uint16":0x9, "map":0x15, "bool":0x1, "int32":0x5, "ptr":0x16, "string":0x18, "func":0x13, "struct":0x19, "invalid":0x0, "uint32":0xa, "float32":0xd, "float64":0xe, "chan":0x12}
String: "Hey", Kind: invalid (0x0)
String: "uint8", Kind: uint8 (0x8)
String: "ptr", Kind: ptr (0x16)
String: "func", Kind: func (0x13)
String: "chan", Kind: chan (0x12)
String: "interface", Kind: interface (0x14)

How do I get a network client's IP converted to a string in Golang?

I'm trying to get a client IP when a connection is made to a server. Trying to use RemoteAddr() returns an addr-type, and while I can print to the console using fmt.Println, I'm trying to assign the value to a string variable.
Is this possible? Or is there a better way to pull a connected client's IP address?
Sample of the function I'm working on (the strRemoteAddr assignment is the problem part, but I left it in as a placeholder...):
func GrabInput(conn net.Conn, strFromListenerNumber string) {
var strMessage string
var strRemoteAddr string
bufIncoming := make([]byte, 1024)
strRemoteAddr = conn.RemoteAddr()
for {
bytesRead, err := conn.Read(bufIncoming)
if err != nil {
LogEvent(strFromListenerNumber, err.Error())
return
}
strMessage = string(bufIncoming[0 : bytesRead-1])
LogEvent(strFromListenerNumber+": "+strRemoteAddr, strMessage)
}
}
Convert it to *net.TCPAddr
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
fmt.Println(addr.IP.String())
}
Seems just
strRemoteAddr = conn.RemoteAddr().String()
can do, net.Addr type has method String() for string representation.

Convert port to :port of type string in Golang

How do you convert a port inputted as a int by the user to a string of type ":port" (ie, it should have a ':' in front of it and should be converted to string). The output has to be feed to http.ListenAndServe().
You could (ought to?) use net.JoinHostPort(host, port string).
Convert port to a string with strconv.Itoa.
It'll also handle the case where the host part contains a colon: "host:port". Feed that directly to ListenAndServe.
Here is some sample code:
host := ""
port := 80
str := net.JoinHostPort(host, strconv.Itoa(port))
fmt.Printf("host:port = '%s'", str)
// Can be fed directly to:
// http.ListenAndServe(str, nil)
The above can be run on a playground: https://play.golang.org/p/AL3obKjwcjZ
if err := http.ListenAndServe(fmt.Sprintf(":%d", port), handler); err != nil {
log.Fatal(err)
}
Use strconv.Itoa()
Something like:
p := strconv.Itoa(port)
addr := ":" + p
// or for localhost only
// addr := "localhost:" + p
Then
if err := http.ListenAndServe(addr, nil); err != nil {
log.Fatal("ListenAndServe: ", err)
}

Encode/Decode base64

here is my code and I don't understand why the decode function doesn't work.
Little insight would be great please.
func EncodeB64(message string) (retour string) {
base64Text := make([]byte, base64.StdEncoding.EncodedLen(len(message)))
base64.StdEncoding.Encode(base64Text, []byte(message))
return string(base64Text)
}
func DecodeB64(message string) (retour string) {
base64Text := make([]byte, base64.StdEncoding.DecodedLen(len(message)))
base64.StdEncoding.Decode(base64Text, []byte(message))
fmt.Printf("base64: %s\n", base64Text)
return string(base64Text)
}
It gaves me :
[Decode error - output not utf-8][Decode error - output not utf-8]
The len prefix is superficial and causes the invalid utf-8 error:
package main
import (
"encoding/base64"
"fmt"
"log"
)
func main() {
str := base64.StdEncoding.EncodeToString([]byte("Hello, playground"))
fmt.Println(str)
data, err := base64.StdEncoding.DecodeString(str)
if err != nil {
log.Fatal("error:", err)
}
fmt.Printf("%q\n", data)
}
(Also here)
Output
SGVsbG8sIHBsYXlncm91bmQ=
"Hello, playground"
EDIT: I read too fast, the len was not used as a prefix. dystroy got it right.
DecodedLen returns the maximal length.
This length is useful for sizing your buffer but part of the buffer won't be written and thus won't be valid UTF-8.
You have to use only the real written length returned by the Decode function.
l, _ := base64.StdEncoding.Decode(base64Text, []byte(message))
log.Printf("base64: %s\n", base64Text[:l])
To sum up the other two posts, here are two simple functions to encode/decode Base64 strings with Go:
// Dont forget to import "encoding/base64"!
func base64Encode(str string) string {
return base64.StdEncoding.EncodeToString([]byte(str))
}
func base64Decode(str string) (string, bool) {
data, err := base64.StdEncoding.DecodeString(str)
if err != nil {
return "", true
}
return string(data), false
}
Try it!
#Denys Séguret's answer is almost 100% correct. As an improvement to avoid wasting memory with non used space in base64Text, you should use base64.DecodedLen. Take a look at how base64.DecodeString uses it.
It should look like this:
func main() {
message := base64.StdEncoding.EncodeToString([]byte("Hello, playground"))
base64Text := make([]byte, base64.StdEncoding.DecodedLen(len(message)))
n, _ := base64.StdEncoding.Decode(base64Text, []byte(message))
fmt.Println("base64Text:", string(base64Text[:n]))
}
Try it here.
More or less like above, but using []bytes and part of a bigger struct:
func (s secure) encodePayload(body []byte) string {
//Base64 Encode
return base64.StdEncoding.EncodeToString(body)
}
func (s secure) decodePayload(body []byte) ([]byte, error) {
//Base64 Decode
b64 := make([]byte, base64.StdEncoding.DecodedLen(len(body)))
n, err := base64.StdEncoding.Decode(b64, body)
if err != nil {
return nil, err
}
return b64[:n], nil
}

Go issue with strings

I'm having some trouble with strings in Golang. It seems that they don't get handed over to another function.
func Sendtext(ip string, port string, text string) (err int) {
targ := ip + ":" + port
raddr,e := net.ResolveTCPAddr("tcp",targ)
if e != nil {
os.Stdout.WriteString(e.String()+"\n")
return 1
}
conn,e := net.DialTCP("tcp",nil,raddr)
if e != nil {
os.Stdout.WriteString(e.String()+"\n")
return 1
}
conn.Write([]byte(text))
mess := make([]byte,1024)
conn.Read(mess)
message := string(mess)
conn.Close()
if message[0] == 'a' {
return 0
} else {
return 1
}
return 0
}
func main() {
os.Stdout.WriteString("Will send URL: ")
url := GetURL()
os.Stdout.WriteString(url + "\n\n")
_, port, pass, ip := browserbridge_config.ReadPropertiesFile()
os.Stdout.WriteString("sending this url to " + ip + ":" + port + "\n")
message := url + "\n" + pass + "\n"
os.Stdout.WriteString("\nsending... ")
e := Sendtext(ip, port, message)
if e != 0 {
os.Stdout.WriteString("ERROR\n")
os.Exit(e);
}
os.Stdout.WriteString("DONE\n")
}
and my config reader:
func ReadConfigFile(filename string) (browsercommand string, port string, pass string, ip string) {
// set defaults
browsercommand = "%u"
port = "7896"
pass = "hallo"
ip = "127.0.0.1"
// open file
file, err := os.Open(filename)
if err != nil {
os.Stdout.WriteString("Error opening config file. proceeding with standard config...")
return
}
// Get reader and buffer
reader := bufio.NewReader(file)
for {
part,_,err := reader.ReadLine()
if err != nil {
break
}
buffer := bytes.NewBuffer(make([]byte,2048))
buffer.Write(part)
s := strings.ToLower(buffer.String())
if strings.Contains(s,"browsercommand=") {
browsercommand = strings.Replace(s,"browsercommand=","",1)
} else {
if strings.Contains(s,"port=") {
port = strings.Replace(s,"port=","",1)
} else {
if strings.Contains(s,"password=") {
pass = strings.Replace(s,"password=","",1)
} else {
if strings.Contains(s,"ip=") {
ip = strings.Replace(s,"ip=","",1)
}
}
}
}
}
return
}
Output of this program:
Will send URL: test.de
sending this url to 192.168.2.100:7896
sending...
dial tcp 192.168.2.1:0: connection refused
ERROR
(192.168.2.1 is gateway)
I tried to os.Stdout.WriteString(targ) or os.Stdout.WriteString(ip) just at the top of Sendtext, and got no output.
The confusing thing about it: yesterday it worked xD (before I migrated ReadConfig into its own .go file)
I hope you can help me solving this...
sylar
Update:
As PeterSO said, the problem is not the handover of the strings
My first guess, that it must be the conversion of String to TCPAddr, is true, but it seems to be a problem with the strings, not with the net library.
I just added
ip = "192.168.2.100"
port = "7896"
right after the call of Sendtext, and that helped... (at least until a user needs to set a custom ip/port...)
I know that the problem firs occured when I decided to switch from goconf (http://code.google.com/p/goconf/) to my own. This is why I think the problem is in the ReadProperties() function.
I also realized that strconv.Atoi(port) returns 0 (parsing "7896": invalid argument)
When I used the server and client with implemented (not-changable) config, and then let the client read the password from the config file, the password comparison fails. When I also set the password right in the code (without reading a file), it works.
I really don't know what to do now... Any idea?
Go bytes package: func NewBuffer(buf []byte) *Buffer
NewBuffer creates and initializes a new Buffer using buf as its
initial contents. It is intended to prepare a Buffer to read
existing data. It can also be used to size the internal buffer for
writing. To do that, buf should have the desired capacity but a
length of zero.
In most cases, new(Buffer) (or just declaring a Buffer variable)
is preferable to NewBuffer. In particular, passing a non-empty buf
to NewBuffer and then writing to the Buffer will overwrite buf,
not append to it.
In your ReadConfigFile function, you write:
buffer := bytes.NewBuffer(make([]byte,2048))
buffer.Write(part)
The make([]byte,2048) function call creates an initial slice for buffer with a length and capacity of 2048 bytes. The buffer.Write(part) function call writes part by overwriting buffer. At the very least, you should have written make([]byte,0,2048) to initially give the buffer slice a length of zero and capacity of 2048 bytes.
Your ReadConfigFile function has other flaws. For example, the key=value format is very rigid, only keys hardcoded into the function are recognized, if a configuration file is not given it doesn't return the defaults, the configuration file is not closed, etc. Here's a basic implementation of a configuration file reader.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type Config map[string]string
func ReadConfig(filename string) (Config, os.Error) {
config := Config{
"browsercommand": "%u",
"port": "7896",
"password": "hallo",
"ip": "127.0.0.1",
}
if len(filename) == 0 {
return config, nil
}
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
rdr := bufio.NewReader(file)
for {
line, err := rdr.ReadString('\n')
if eq := strings.Index(line, "="); eq >= 0 {
if key := strings.TrimSpace(line[:eq]); len(key) > 0 {
value := ""
if len(line) > eq {
value = strings.TrimSpace(line[eq+1:])
}
config[key] = value
}
}
if err == os.EOF {
break
}
if err != nil {
return nil, err
}
}
return config, nil
}
func main() {
config, err := ReadConfig(`netconfig.txt`)
if err != nil {
fmt.Println(err)
}
fmt.Println("config:", config)
ip := config["ip"]
pass := config["password"]
port := config["port"]
fmt.Println("values:", ip, port, pass)
}
Input:
[a section]
key=value
; a comment
port = 80
password = hello
ip= 217.110.104.156
# another comment
url =test.de
file =
Output:
config: map[browsercommand:%u key:value port:80 ip:217.110.104.156 url:test.de
file: password:hello]
values: 217.110.104.156 80 hello
Insert the following statement as the statement just before the call to the Sendtext function in the main function.
fmt.Println("\nmain:", "\nip = |", ip, "| \nport = |", port, "| \ntext = |", message, "|")
The output should look something like this:
main:
ip = | 192.168.2.100 |
port = | 7896 |
text = | test.de
hallo
|
Insert the following statement as the first statement in the Sendtext function.
fmt.Println("\nSendtext:", "\nip = |", ip, "| \nport = |", port, "| \ntext = |", text, "|")
The output should look something like this:
Sendtext:
ip = | 192.168.2.100 |
port = | 7896 |
text = | test.de
hallo
|
As expected, the arguments are passed to the parameters by value.
Solved it. The problem was the conversion of the 2048-long []byte to a string. This made the string to be equal long, but with a lot of NIL-chars after it.
So running a ip = strings.Replace(ip,string(0),"",-1) over all values at the end of ReadConfig() solved the problem.

Resources