package fic import ( "bytes" "crypto/md5" "regexp" "strings" ) // ToURLid converts the given string to a valid URLid. func ToURLid(str string) string { re_a := regexp.MustCompile("[áàâäā]") str = re_a.ReplaceAllLiteralString(str, "a") re_A := regexp.MustCompile("[ÀÁÂÄĀ]") str = re_A.ReplaceAllLiteralString(str, "A") re_c := regexp.MustCompile("[ç]") str = re_c.ReplaceAllLiteralString(str, "c") re_C := regexp.MustCompile("[Ç]") str = re_C.ReplaceAllLiteralString(str, "C") re_e := regexp.MustCompile("[éèêëȩē]") str = re_e.ReplaceAllLiteralString(str, "e") re_E := regexp.MustCompile("[ÉÈÊËĒ]") str = re_E.ReplaceAllLiteralString(str, "E") re_i := regexp.MustCompile("[íìîïī]") str = re_i.ReplaceAllLiteralString(str, "i") re_I := regexp.MustCompile("[ÌÍÎÏĪ]") str = re_I.ReplaceAllLiteralString(str, "I") re_l := regexp.MustCompile("[ł]") str = re_l.ReplaceAllLiteralString(str, "l") re_o := regexp.MustCompile("[òóôöō]") str = re_o.ReplaceAllLiteralString(str, "o") re_O := regexp.MustCompile("[ÒÓÔÖŌ]") str = re_O.ReplaceAllLiteralString(str, "O") re_oe := regexp.MustCompile("[œ]") str = re_oe.ReplaceAllLiteralString(str, "oe") re_OE := regexp.MustCompile("[Œ]") str = re_OE.ReplaceAllLiteralString(str, "OE") re_u := regexp.MustCompile("[ùúûüū]") str = re_u.ReplaceAllLiteralString(str, "u") re_U := regexp.MustCompile("[ÙÚÛÜŪ]") str = re_U.ReplaceAllLiteralString(str, "U") re_y := regexp.MustCompile("[ỳýŷÿȳ]") str = re_y.ReplaceAllLiteralString(str, "y") re_Y := regexp.MustCompile("[ỲÝŶŸȲ]") str = re_Y.ReplaceAllLiteralString(str, "Y") re := regexp.MustCompile("[^a-zA-Z0-9]+") return strings.TrimSuffix(re.ReplaceAllLiteralString(str, "-"), "-") } // Apr1Md5 computes a usable hash for basic auth in Apache and nginx. // Function copied from https://github.com/jimstudt/http-authentication/blob/master/basic/md5.go // as it was not exported in package and comes with other unwanted functions. // Original source code under MIT. func Apr1Md5(password string, salt string) string { initBin := md5.Sum([]byte(password + salt + password)) initText := bytes.NewBufferString(password + "$apr1$" + salt) for i := len(password); i > 0; i -= 16 { lim := i if lim > 16 { lim = 16 } initText.Write(initBin[0:lim]) } for i := len(password); i > 0; i >>= 1 { if (i & 1) == 1 { initText.WriteByte(byte(0)) } else { initText.WriteByte(password[0]) } } bin := md5.Sum(initText.Bytes()) n := bytes.NewBuffer([]byte{}) for i := 0; i < 1000; i++ { n.Reset() if (i & 1) == 1 { n.WriteString(password) } else { n.Write(bin[:]) } if i%3 != 0 { n.WriteString(salt) } if i%7 != 0 { n.WriteString(password) } if (i & 1) == 1 { n.Write(bin[:]) } else { n.WriteString(password) } bin = md5.Sum(n.Bytes()) } result := bytes.NewBuffer([]byte{}) fill := func(a byte, b byte, c byte) { v := (uint(a) << 16) + (uint(b) << 8) + uint(c) for i := 0; i < 4; i++ { result.WriteByte("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[v&0x3f]) v >>= 6 } } fill(bin[0], bin[6], bin[12]) fill(bin[1], bin[7], bin[13]) fill(bin[2], bin[8], bin[14]) fill(bin[3], bin[9], bin[15]) fill(bin[4], bin[10], bin[5]) fill(0, 0, bin[11]) resultString := string(result.Bytes()[0:22]) return resultString } // Function copied from https://github.com/gerow/go-color/blob/master/color.go type HSL struct { H, S, L float64 } func hueToRGB(v1, v2, h float64) uint32 { if h < 0 { h += 1 } if h > 1 { h -= 1 } var res float64 switch { case 6*h < 1: res = (v1 + (v2-v1)*6*h) case 2*h < 1: res = v2 case 3*h < 2: res = v1 + (v2-v1)*((2.0/3.0)-h)*6 default: res = v1 } return uint32((res + 1/512.0) * 255) } func (c HSL) ToRGB() (rgb uint32) { h := c.H s := c.S l := c.L if s == 0 { // it's gray v := uint32((l + 1/512.0) * 255) return v*65536 + v*256 + v } var v1, v2 float64 if l < 0.5 { v2 = l * (1 + s) } else { v2 = (l + s) - (s * l) } v1 = 2*l - v2 r := hueToRGB(v1, v2, h+(1.0/3.0)) g := hueToRGB(v1, v2, h) b := hueToRGB(v1, v2, h-(1.0/3.0)) return r*65536 + g*256 + b }