util.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package util
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "errors"
  6. "io"
  7. "io/ioutil"
  8. "net"
  9. "os"
  10. "os/user"
  11. "path/filepath"
  12. "runtime"
  13. "strconv"
  14. "strings"
  15. "time"
  16. "github.com/jhoonb/archivex"
  17. )
  18. // Expand tilde in paths
  19. func Expand(input string) string {
  20. if runtime.GOOS == "windows" {
  21. return input
  22. }
  23. usr, _ := user.Current()
  24. dir := usr.HomeDir
  25. if input == "~" {
  26. input = dir
  27. } else if strings.HasPrefix(input, "~/") {
  28. input = filepath.Join(dir, input[2:])
  29. }
  30. return input
  31. }
  32. // ZipFiles and return the resulting zip's filename
  33. func ZipFiles(files []string) (string, error) {
  34. zip := new(archivex.ZipFile)
  35. tmpfile, err := ioutil.TempFile("", "qrcp")
  36. if err != nil {
  37. return "", err
  38. }
  39. tmpfile.Close()
  40. if err := os.Rename(tmpfile.Name(), tmpfile.Name()+".zip"); err != nil {
  41. return "", err
  42. }
  43. if err := zip.Create(tmpfile.Name() + ".zip"); err != nil {
  44. return "", err
  45. }
  46. for _, filename := range files {
  47. fileinfo, err := os.Stat(filename)
  48. if err != nil {
  49. return "", err
  50. }
  51. if fileinfo.IsDir() {
  52. if err := zip.AddAll(filename, true); err != nil {
  53. return "", err
  54. }
  55. } else {
  56. file, err := os.Open(filename)
  57. if err != nil {
  58. return "", err
  59. }
  60. defer file.Close()
  61. if err := zip.Add(filename, file, fileinfo); err != nil {
  62. return "", err
  63. }
  64. }
  65. }
  66. if err := zip.Close(); err != nil {
  67. return "", nil
  68. }
  69. return zip.Name, nil
  70. }
  71. // GetRandomURLPath returns a random string of 4 alphanumeric characters
  72. func GetRandomURLPath() string {
  73. timeNum := time.Now().UTC().UnixNano()
  74. alphaString := strconv.FormatInt(timeNum, 36)
  75. return alphaString[len(alphaString)-4:]
  76. }
  77. // GetSessionID returns a base64 encoded string of 40 random characters
  78. func GetSessionID() (string, error) {
  79. randbytes := make([]byte, 40)
  80. if _, err := io.ReadFull(rand.Reader, randbytes); err != nil {
  81. return "", err
  82. }
  83. return base64.StdEncoding.EncodeToString(randbytes), nil
  84. }
  85. // GetInterfaceAddress returns the address of the network interface to
  86. // bind the server to. If the interface is "any", it will return 0.0.0.0.
  87. // If no interface is found with that name, an error is returned
  88. func GetInterfaceAddress(ifaceString string) (string, error) {
  89. if ifaceString == "any" {
  90. return "0.0.0.0", nil
  91. }
  92. ifaces, err := net.Interfaces()
  93. if err != nil {
  94. return "", err
  95. }
  96. var candidateInterface *net.Interface
  97. for _, iface := range ifaces {
  98. if iface.Name == ifaceString {
  99. candidateInterface = &iface
  100. break
  101. }
  102. }
  103. if candidateInterface != nil {
  104. ip, err := FindIP(*candidateInterface)
  105. if err != nil {
  106. return "", err
  107. }
  108. return ip, nil
  109. }
  110. return "", errors.New("unable to find interface")
  111. }
  112. // FindIP returns the IP address of the passed interface, and an error
  113. func FindIP(iface net.Interface) (string, error) {
  114. var ip string
  115. addrs, err := iface.Addrs()
  116. if err != nil {
  117. return "", err
  118. }
  119. for _, addr := range addrs {
  120. if ipnet, ok := addr.(*net.IPNet); ok {
  121. if ipnet.IP.IsLinkLocalUnicast() {
  122. continue
  123. }
  124. if ipnet.IP.To4() != nil {
  125. ip = ipnet.IP.String()
  126. continue
  127. }
  128. // Use IPv6 only if an IPv4 hasn't been found yet.
  129. // This is eventually overwritten with an IPv4, if found (see above)
  130. if ip == "" {
  131. ip = "[" + ipnet.IP.String() + "]"
  132. }
  133. }
  134. }
  135. if ip == "" {
  136. return "", errors.New("unable to find an IP for this interface")
  137. }
  138. return ip, nil
  139. }
  140. // ReadFilenames from dir
  141. func ReadFilenames(dir string) []string {
  142. files, err := ioutil.ReadDir(dir)
  143. if err != nil {
  144. panic(err)
  145. }
  146. // Create array of names of files which are stored in dir
  147. // used later to set valid name for received files
  148. filenames := make([]string, len(files))
  149. for _, fi := range files {
  150. filenames = append(filenames, fi.Name())
  151. }
  152. return filenames
  153. }