How to extract a .jar file - go

I like to extract a .jar file in Go. I tried different approaches with the build in libraries but with no success. In buff is a little part of the JAR I try to analyze. The errors also occur on the full byte array.
flate:
buff := []byte{80, 75, 3, 4, 10, 0, 8, 8, 8, 0, 239, 77, 77, 78,
147,
98, 6, 159, 116, 0, 0, 0, 132, 0, 0, 0, 20, 0, 0, 0, 77, 69, 84, 65,
45, 73, 78, 70, 47, 77, 65, 78, 73, 70, 69, 83, 84, 46, 77, 70, 37,
140, 49, 14, 194, 48, 12, 0, 247, 72, 249, 131, 63, 16, 43, 128, 88,
178, 181, 221, 144, 178, 178, 91, 196, 64, 32, 184, 81, 28, 42, 248,
61,5, 214, 187, 211, 69, 146, 124, 102, 237}
b := bytes.NewReader(buff)
zr := flate.NewReader(b)
if _, err := io.Copy(os.Stdout, zr); err != nil {
log.Fatal(err)
}
if err := zr.Close(); err != nil {
log.Fatal(err)
}
fmt.Println()
Error: flate: corrupt input before offset 5
zlib:
b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
panic(err)
}
io.Copy(os.Stdout, r)
r.Close()
Error: zlib: invalid header
Wikipedia says JAR is a extension of zip and normal compression programs can unzip them. Any ideas how to get this working? Like adding a working header or is my code wrong?

JAR files are zip archives, not just zlib or flate compressed data.
So use the archive/zip package to properly process them. For example, to list the files inside the JAR file:
r, err := zip.NewReader(bytes.NewReader(buff), int64(len(buff)))
if err != nil {
panic(err)
}
for _, f := range r.File {
fmt.Println("Found in jar:", f.Name)
}
Of course you have to provide the full file content, else you will most likely get an error when obtaining the zip.Reader.
If you also want to print the contents of the files inside the archive, this is how you could do it:
for _, f := range r.File {
fmt.Printf("Found in jar: %s, contents:\n", f.Name)
rc, err := f.Open()
if err != nil {
log.Fatal(err)
}
_, err = io.CopyN(os.Stdout, rc, int64(f.UncompressedSize64))
if err != nil {
log.Fatal(err)
}
rc.Close()
fmt.Println()
}
Here's a JAR file which contains a single file named a.txt, with contents "Hello Gopher":
buff := []byte{80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 91, 109, 103, 78, 132, 225, 60, 127, 13, 0, 0, 0, 13, 0, 0, 0, 5, 0, 28, 0, 97, 46, 116, 120, 116, 85, 84, 9, 0, 3, 206, 17, 129, 92, 219, 17, 129, 92, 117, 120, 11, 0, 1, 4, 232, 3, 0, 0, 4, 232, 3, 0, 0, 72, 101, 108, 108, 111, 32, 71, 111, 112, 104, 101, 114, 10, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 91, 109, 103, 78, 132, 225, 60, 127, 13, 0, 0, 0, 13, 0, 0, 0, 5, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 164, 129, 0, 0, 0, 0, 97, 46, 116, 120, 116, 85, 84, 5, 0, 3, 206, 17, 129, 92, 117, 120, 11, 0, 1, 4, 232, 3, 0, 0, 4, 232, 3, 0, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 75, 0, 0, 0, 76, 0, 0, 0, 0, 0}
Running the above code on this buffer, the output is (try it on the Go Playground):
Found in jar: a.txt, contents:
Hello Gopher

Related

Is it possible to sort a slice of structs by time in Golang?

I am trying to sort the structs Session in the slice Session by each Session's start time and hall_id. Here is the code:
Sessions := []Session{
Session{
name: "superman",
hall_id: 1,
startTime: time.Date(2022, time.August, 15, 17, 35, 0, 0, time.UTC),
endTime: time.Date(2022, time.August, 15, 18, 35, 0, 0, time.UTC),
},
Session{
name: "thor",
hall_id: 2,
startTime: time.Date(2022, time.August, 15, 16, 30, 0, 0, time.UTC),
endTime: time.Date(2022, time.August, 15, 17, 30, 0, 0, time.UTC),
},
Session{
name: "joker",
hall_id: 3,
startTime: time.Date(2022, time.August, 15, 19, 40, 0, 0, time.UTC),
endTime: time.Date(2022, time.August, 15, 20, 30, 0, 0, time.UTC),
},
Session{
name: "batman",
hall_id: 1,
startTime: time.Date(2022, time.August, 15, 17, 40, 0, 0, time.UTC),
endTime: time.Date(2022, time.August, 15, 18, 20, 0, 0, time.UTC),
},
}
The point is that I am using "time" package, and in order to create a date, you need to use Date() function, which requires multiple stuff like: year int, month, day int, hour int, minute int, etc.
I have tried the AndreKR's answer which is:
slice.Sort(planets[:], func(i, j int) bool {
return planets[i].Axis < planets[j].Axis
})
but it seems that it does not work with multiple "parameters" of a struct. I tried this:
sort.Slice(Sessions[:], func(i, j int) bool {
return Sessions[i].startTime.Year() < Sessions[j].startTime.Year(),
int(Sessions[i].startTime.Month()) < int(Sessions[j].startTime.Month()),
Sessions[i].startTime.Day() < Sessions[j].startTime.Day(),
Sessions[i].startTime.Hour() < Sessions[j].startTime.Hour(),
Sessions[i].startTime.Minute() < Sessions[j].startTime.Minute()
})
I am new to the Golang, so if I have made an obvious mistake I am sorry ;(
Alright, I have got the answer:
sort.Slice(Sessions[:], func(i, j int) bool {
return Sessions[i].startTime.Before(Sessions[j].startTime)
})
this code will solve this problem

strange behaviour of goroutines in for loop [duplicate]

This question already has answers here:
Strange golang "append" behavior (overwriting values in slice)
(3 answers)
Closed 2 years ago.
I am switching from Python to GoLang. I was learning goroutines. I faced strange outputs when I used the goroutines in for loop.
package main
import "fmt"
func main() {
var test = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}
for _, x := range test{
go func() {
fmt.Println(x)
}()
}
}
the output:
25
19
28
19
40
40
6
I was thinking it was capturing values from for loop but, when I saw it was increasing and decreasing. I got confused. Why is that happening?
The goroutines are accessing the x variable that is changing in parallel with the execution of the goroutines. This is a common problem encountered by I think even go programmer at least once. You can capture the current value of the variable like this:
for _, x := range test{
go func(x int) {
fmt.Println(x)
}(x)
}
Or like this:
for _, x := range test{
x2 := x
go func() {
fmt.Println(x2)
}()
}

Finding numbers above the mean

I could use some help finding all the numbers from a struct array that are above a calculated mean!
//MeanMedianMode struct
type MeanMedianMode struct {
numbers []float64
}
func main() {
// range of numbers
dataType := MeanMedianMode{
numbers: []float64{
84, 25, 88, 56, 10, 19, 11, 80,
45, 83, 22, 40, 22, 52, 61, 13, 73, 23, //Data to be used
90, 89, 6,
},
}
I've figured out how to pass my data easily and find the average as follows...
//CalcMean float64
func (mm *MeanMedianMode) CalcMean() float64 {
total := 0.0
for _, v := range mm.numbers {
total += v
}
return (total / float64(len(mm.numbers)))
//return math.Round(total / float64(len(mm.numbers))) //Should it need to be rounded
}
My biggest issue is replicating that process and using the values stored in the array within another function and iterating over them to find the values greater than (>) the found mean!
I appreciate the insights!
I don't know how you'd like to do it, but something like this I guess:
package main
import (
"fmt"
)
//MeanMedianMode struct
type MeanMedianMode struct {
numbers []float64
}
func main() {
m := &MeanMedianMode{
numbers: []float64{
84, 25, 88, 56, 10, 19, 11, 80,
45, 83, 22, 40, 22, 52, 61, 13, 73, 23,
90, 89, 6,
},
}
mean := m.CalcMean()
for _, n := range m.numbers {
if n > mean {
fmt.Printf("%.3f is greater than the mean\n", n)
}
}
}
//CalcMean float64
func (mm *MeanMedianMode) CalcMean() float64 {
total := 0.0
for _, v := range mm.numbers {
total += v
}
return (total / float64(len(mm.numbers)))
}

How to convert Point Coordinate in Database to Point struct GoLang

CurrentCoordinates []uint8 `json:"current_coordinates"`
type Points struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
DB Column has data as :
POINT(6.887035 79.883757)
From DB i got it into []uint8, then the result is :
[0 0 0 0 1 1 0 0 0 35 161 45 231 82 140 27 64 28 39 133 121 143 248 83 64]
Anyone know how to convert this to coordinates?
The coordinates are stored at the end of your slice, both have 8 bytes which are the little-endian encoded bytes of the IEEE 754 double-precision representation of the floating point numbers.
You may use the encoding/binary package to get the floating-point data of the coordinates as an uint64, and you may use math.Float64frombits() to "convert" that data to float64 type.
This is how you can decode them:
data := []byte{0, 0, 0, 0, 1, 1, 0, 0, 0, 35, 161, 45, 231, 82, 140, 27, 64, 28, 39, 133, 121, 143, 248, 83, 64}
d := binary.LittleEndian.Uint64(data[9:])
x := math.Float64frombits(d)
d = binary.LittleEndian.Uint64(data[17:])
y := math.Float64frombits(d)
fmt.Println(x, y)
This will output (try it on the Go Playground):
6.887035 79.883757
The beginning of your data may be SRID (spatial reference identifier) and/or some kind of distance / accuracy for searches, depends on the database you're using.
Alternatively you may create an io.Reader reading from your slice using bytes.NewReader(), and use the binary.Read() function:
data := []byte{0, 0, 0, 0, 1, 1, 0, 0, 0, 35, 161, 45, 231, 82, 140, 27, 64, 28, 39, 133, 121, 143, 248, 83, 64}
r := bytes.NewReader(data[9:])
var x, y float64
if err := binary.Read(r, binary.LittleEndian, &x); err != nil {
panic(err)
}
if err := binary.Read(r, binary.LittleEndian, &y); err != nil {
panic(err)
}
fmt.Println(x, y)
This will output the same. Try this one on the Go Playground.

Difficulty with variadic functions [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
From An Introduction to Programming in Go, page 91, Exercise Question no 4, Topic: Functions:
Write a function with one variadic parameter that finds the greatest number in a list of numbers?
So far I had written this code but it is showing errors
package main
import (
"fmt"
)
func findMaximum(args ...[]int) []int {
max := args[0]
for _, v := range args {
if v > []args {
max = v
}
}
return args
}
func main() {
x := []int{
48, 96, 86, 68,
57, 82, 63, 70,
37, 34, 83, 27,
19, 97, 9, 17,
}
fmt.Println(findMaximum(x))
}
I had taken reference from this Program
(Page, 75, Question No. - 4, Topic: Arrays, Slices and Maps)
Write a program that finds the smallest number
in this list:
x := []int{
48,96,86,68,
57,82,63,70,
37,34,83,27,
19,97, 9,17,
}
This is the program I had written to solve this Question
package main
import "fmt"
func main() {
arr := []uint{
48, 96, 86, 68,
57, 82, 63, 70,
37, 34, 83, 27,
19, 97, 9, 17,
}
min := arr[0] // assume first value is smallest
for _, value := range arr {
if value < min {
min = value // found another value, replace previous value of min
}
}
fmt.Println("The smallest value is : ", min)
}
This Question Program is running but the First one is not I don't know why.
In mathematics and in computer programming, a variadic function is a
function of indefinite arity, i.e., one which accepts a variable
number of arguments.
Source: Wikipedia
Your function signature is slightly incorrect.
func findMaximum(args ...[]int) []int
This indicates that findMaximum takes in a variable number of int slices as arguments and returns an int slice. The problem that you're trying to solve is asking to take in a variable number of int arguments and return a singular int which is the largest in the set provided.
Calling your function would look something like this:
largest := findMaximum([]int{1, 2, 3}, []int{4, 5, 6}, []int{7, 8, 9})
In this case, largest would be of type []int indicating that the function returned multiple int values in the form of a slice. This wouldn't make sense, since there should only be one largest value (assuming no duplicates).
You're wanting a function signature that looks like this:
func findMaximum(args ...int) int
Calling this function would look like this:
largest := findMaximum(1, 2, 3, 4, 5, 6, 7, 8, 9)
...or if you had your numbers in a slice:
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
largest := findMaximum(nums...)
In this case, largest would be of type int, which is the correct return value you're looking for in this problem.
(Go Playground)
Good luck!
If you run your code through https://play.golang.org/ you will see a couple of syntax errors. Below is the correct version which finds max in a slice.
As you can note you had extra ... in the slice argument call.
package main
import (
"fmt"
)
func findMaximum(args []int) int {
max := args[0]
for _, v := range args {
if v > max{
max = v
}
}
return max
}
func main() {
x := []int{
48, 96, 86, 68,
57, 82, 63, 70,
37, 34, 83, 27,
19, 97, 9, 17,
}
fmt.Println(findMaximum(x))
}

Resources