utils.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2012 Julien Schmidt. All rights reserved.
  4. // http://www.julienschmidt.com
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla Public
  7. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  8. // You can obtain one at http://mozilla.org/MPL/2.0/.
  9. package mysql
  10. import (
  11. "crypto/sha1"
  12. "database/sql/driver"
  13. "encoding/binary"
  14. "fmt"
  15. "io"
  16. "log"
  17. "os"
  18. "regexp"
  19. "strings"
  20. "time"
  21. )
  22. // Logger
  23. var (
  24. errLog *log.Logger
  25. )
  26. func init() {
  27. errLog = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile)
  28. dsnPattern = regexp.MustCompile(
  29. `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
  30. `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
  31. `\/(?P<dbname>.*?)` + // /dbname
  32. `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
  33. }
  34. // Data Source Name Parser
  35. var dsnPattern *regexp.Regexp
  36. func parseDSN(dsn string) (cfg *config, err error) {
  37. cfg = new(config)
  38. cfg.params = make(map[string]string)
  39. matches := dsnPattern.FindStringSubmatch(dsn)
  40. names := dsnPattern.SubexpNames()
  41. for i, match := range matches {
  42. switch names[i] {
  43. case "user":
  44. cfg.user = match
  45. case "passwd":
  46. cfg.passwd = match
  47. case "net":
  48. cfg.net = match
  49. case "addr":
  50. cfg.addr = match
  51. case "dbname":
  52. cfg.dbname = match
  53. case "params":
  54. for _, v := range strings.Split(match, "&") {
  55. param := strings.SplitN(v, "=", 2)
  56. if len(param) != 2 {
  57. continue
  58. }
  59. cfg.params[param[0]] = param[1]
  60. }
  61. }
  62. }
  63. // Set default network if empty
  64. if cfg.net == "" {
  65. cfg.net = "tcp"
  66. }
  67. // Set default adress if empty
  68. if cfg.addr == "" {
  69. cfg.addr = "127.0.0.1:3306"
  70. }
  71. cfg.loc, err = time.LoadLocation(cfg.params["loc"])
  72. return
  73. }
  74. // Encrypt password using 4.1+ method
  75. // http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#4.1_and_later
  76. func scramblePassword(scramble, password []byte) []byte {
  77. if len(password) == 0 {
  78. return nil
  79. }
  80. // stage1Hash = SHA1(password)
  81. crypt := sha1.New()
  82. crypt.Write(password)
  83. stage1 := crypt.Sum(nil)
  84. // scrambleHash = SHA1(scramble + SHA1(stage1Hash))
  85. // inner Hash
  86. crypt.Reset()
  87. crypt.Write(stage1)
  88. hash := crypt.Sum(nil)
  89. // outer Hash
  90. crypt.Reset()
  91. crypt.Write(scramble)
  92. crypt.Write(hash)
  93. scramble = crypt.Sum(nil)
  94. // token = scrambleHash XOR stage1Hash
  95. for i := range scramble {
  96. scramble[i] ^= stage1[i]
  97. }
  98. return scramble
  99. }
  100. func parseDateTime(str string, loc *time.Location) (driver.Value, error) {
  101. var t time.Time
  102. var err error
  103. switch len(str) {
  104. case 10: // YYYY-MM-DD
  105. if str == "0000-00-00" {
  106. return time.Time{}, nil
  107. }
  108. t, err = time.Parse(timeFormat[:10], str)
  109. case 19: // YYYY-MM-DD HH:MM:SS
  110. if str == "0000-00-00 00:00:00" {
  111. return time.Time{}, nil
  112. }
  113. t, err = time.Parse(timeFormat, str)
  114. default:
  115. return nil, fmt.Errorf("Invalid Time-String: %s", str)
  116. }
  117. // Adjust location
  118. if err == nil && loc != time.UTC {
  119. y, mo, d := t.Date()
  120. h, mi, s := t.Clock()
  121. return time.Date(y, mo, d, h, mi, s, t.Nanosecond(), loc), nil
  122. }
  123. return t, err
  124. }
  125. func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Value, error) {
  126. switch num {
  127. case 0:
  128. return time.Time{}, nil
  129. case 4:
  130. return time.Date(
  131. int(binary.LittleEndian.Uint16(data[:2])), // year
  132. time.Month(data[2]), // month
  133. int(data[3]), // day
  134. 0, 0, 0, 0,
  135. loc,
  136. ), nil
  137. case 7:
  138. return time.Date(
  139. int(binary.LittleEndian.Uint16(data[:2])), // year
  140. time.Month(data[2]), // month
  141. int(data[3]), // day
  142. int(data[4]), // hour
  143. int(data[5]), // minutes
  144. int(data[6]), // seconds
  145. 0,
  146. loc,
  147. ), nil
  148. case 11:
  149. return time.Date(
  150. int(binary.LittleEndian.Uint16(data[:2])), // year
  151. time.Month(data[2]), // month
  152. int(data[3]), // day
  153. int(data[4]), // hour
  154. int(data[5]), // minutes
  155. int(data[6]), // seconds
  156. int(binary.LittleEndian.Uint32(data[7:11]))*1000, // nanoseconds
  157. loc,
  158. ), nil
  159. }
  160. return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num)
  161. }
  162. func formatBinaryDate(num uint64, data []byte) (driver.Value, error) {
  163. switch num {
  164. case 0:
  165. return []byte("0000-00-00"), nil
  166. case 4:
  167. return []byte(fmt.Sprintf(
  168. "%04d-%02d-%02d",
  169. binary.LittleEndian.Uint16(data[:2]),
  170. data[2],
  171. data[3],
  172. )), nil
  173. }
  174. return nil, fmt.Errorf("Invalid DATE-packet length %d", num)
  175. }
  176. func formatBinaryDateTime(num uint64, data []byte) (driver.Value, error) {
  177. switch num {
  178. case 0:
  179. return []byte("0000-00-00 00:00:00"), nil
  180. case 4:
  181. return []byte(fmt.Sprintf(
  182. "%04d-%02d-%02d 00:00:00",
  183. binary.LittleEndian.Uint16(data[:2]),
  184. data[2],
  185. data[3],
  186. )), nil
  187. case 7:
  188. return []byte(fmt.Sprintf(
  189. "%04d-%02d-%02d %02d:%02d:%02d",
  190. binary.LittleEndian.Uint16(data[:2]),
  191. data[2],
  192. data[3],
  193. data[4],
  194. data[5],
  195. data[6],
  196. )), nil
  197. case 11:
  198. return []byte(fmt.Sprintf(
  199. "%04d-%02d-%02d %02d:%02d:%02d.%06d",
  200. binary.LittleEndian.Uint16(data[:2]),
  201. data[2],
  202. data[3],
  203. data[4],
  204. data[5],
  205. data[6],
  206. binary.LittleEndian.Uint32(data[7:11]),
  207. )), nil
  208. }
  209. return nil, fmt.Errorf("Invalid DATETIME-packet length %d", num)
  210. }
  211. /******************************************************************************
  212. * Convert from and to bytes *
  213. ******************************************************************************/
  214. func uint64ToBytes(n uint64) []byte {
  215. return []byte{
  216. byte(n),
  217. byte(n >> 8),
  218. byte(n >> 16),
  219. byte(n >> 24),
  220. byte(n >> 32),
  221. byte(n >> 40),
  222. byte(n >> 48),
  223. byte(n >> 56),
  224. }
  225. }
  226. func uint64ToString(n uint64) []byte {
  227. var a [20]byte
  228. i := 20
  229. // U+0030 = 0
  230. // ...
  231. // U+0039 = 9
  232. var q uint64
  233. for n >= 10 {
  234. i--
  235. q = n / 10
  236. a[i] = uint8(n-q*10) + 0x30
  237. n = q
  238. }
  239. i--
  240. a[i] = uint8(n) + 0x30
  241. return a[i:]
  242. }
  243. // treats string value as unsigned integer representation
  244. func stringToInt(b []byte) int {
  245. val := 0
  246. for i := range b {
  247. val *= 10
  248. val += int(b[i] - 0x30)
  249. }
  250. return val
  251. }
  252. func readLengthEnodedString(b []byte) ([]byte, bool, int, error) {
  253. // Get length
  254. num, isNull, n := readLengthEncodedInteger(b)
  255. if num < 1 {
  256. return nil, isNull, n, nil
  257. }
  258. n += int(num)
  259. // Check data length
  260. if len(b) >= n {
  261. return b[n-int(num) : n], false, n, nil
  262. }
  263. return nil, false, n, io.EOF
  264. }
  265. func skipLengthEnodedString(b []byte) (int, error) {
  266. // Get length
  267. num, _, n := readLengthEncodedInteger(b)
  268. if num < 1 {
  269. return n, nil
  270. }
  271. n += int(num)
  272. // Check data length
  273. if len(b) >= n {
  274. return n, nil
  275. }
  276. return n, io.EOF
  277. }
  278. func readLengthEncodedInteger(b []byte) (num uint64, isNull bool, n int) {
  279. switch b[0] {
  280. // 251: NULL
  281. case 0xfb:
  282. n = 1
  283. isNull = true
  284. return
  285. // 252: value of following 2
  286. case 0xfc:
  287. num = uint64(b[1]) | uint64(b[2])<<8
  288. n = 3
  289. return
  290. // 253: value of following 3
  291. case 0xfd:
  292. num = uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16
  293. n = 4
  294. return
  295. // 254: value of following 8
  296. case 0xfe:
  297. num = uint64(b[1]) | uint64(b[2])<<8 | uint64(b[3])<<16 |
  298. uint64(b[4])<<24 | uint64(b[5])<<32 | uint64(b[6])<<40 |
  299. uint64(b[7])<<48 | uint64(b[8])<<54
  300. n = 9
  301. return
  302. }
  303. // 0-250: value of first byte
  304. num = uint64(b[0])
  305. n = 1
  306. return
  307. }
  308. func lengthEncodedIntegerToBytes(n uint64) []byte {
  309. switch {
  310. case n <= 250:
  311. return []byte{byte(n)}
  312. case n <= 0xffff:
  313. return []byte{0xfc, byte(n), byte(n >> 8)}
  314. case n <= 0xffffff:
  315. return []byte{0xfd, byte(n), byte(n >> 8), byte(n >> 16)}
  316. }
  317. return nil
  318. }