github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/utils/utils.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package utils 5 6 import ( 7 "io/ioutil" 8 "net" 9 "net/http" 10 "net/url" 11 "strings" 12 13 "github.com/pkg/errors" 14 15 "github.com/mattermost/mattermost-server/v5/model" 16 ) 17 18 func StringInSlice(a string, slice []string) bool { 19 for _, b := range slice { 20 if b == a { 21 return true 22 } 23 } 24 return false 25 } 26 27 // RemoveStringFromSlice removes the first occurrence of a from slice. 28 func RemoveStringFromSlice(a string, slice []string) []string { 29 for i, str := range slice { 30 if str == a { 31 return append(slice[:i], slice[i+1:]...) 32 } 33 } 34 return slice 35 } 36 37 // RemoveStringsFromSlice removes all occurrences of strings from slice. 38 func RemoveStringsFromSlice(slice []string, strings ...string) []string { 39 newSlice := []string{} 40 41 for _, item := range slice { 42 if !StringInSlice(item, strings) { 43 newSlice = append(newSlice, item) 44 } 45 } 46 47 return newSlice 48 } 49 50 func StringArrayIntersection(arr1, arr2 []string) []string { 51 arrMap := map[string]bool{} 52 result := []string{} 53 54 for _, value := range arr1 { 55 arrMap[value] = true 56 } 57 58 for _, value := range arr2 { 59 if arrMap[value] { 60 result = append(result, value) 61 } 62 } 63 64 return result 65 } 66 67 func RemoveDuplicatesFromStringArray(arr []string) []string { 68 result := make([]string, 0, len(arr)) 69 seen := make(map[string]bool) 70 71 for _, item := range arr { 72 if !seen[item] { 73 result = append(result, item) 74 seen[item] = true 75 } 76 } 77 78 return result 79 } 80 81 func StringSliceDiff(a, b []string) []string { 82 m := make(map[string]bool) 83 result := []string{} 84 85 for _, item := range b { 86 m[item] = true 87 } 88 89 for _, item := range a { 90 if !m[item] { 91 result = append(result, item) 92 } 93 } 94 return result 95 } 96 97 func GetIpAddress(r *http.Request, trustedProxyIPHeader []string) string { 98 address := "" 99 100 for _, proxyHeader := range trustedProxyIPHeader { 101 header := r.Header.Get(proxyHeader) 102 if header != "" { 103 addresses := strings.Fields(header) 104 if len(addresses) > 0 { 105 address = strings.TrimRight(addresses[0], ",") 106 } 107 } 108 109 if address != "" { 110 return address 111 } 112 } 113 114 if address == "" { 115 address, _, _ = net.SplitHostPort(r.RemoteAddr) 116 } 117 118 return address 119 } 120 121 func GetHostnameFromSiteURL(siteURL string) string { 122 u, err := url.Parse(siteURL) 123 if err != nil { 124 return "" 125 } 126 127 return u.Hostname() 128 } 129 130 type RequestCache struct { 131 Data []byte 132 Date string 133 Key string 134 } 135 136 // Fetch JSON data from the notices server 137 // if skip is passed, does a fetch without touching the cache 138 func GetUrlWithCache(url string, cache *RequestCache, skip bool) ([]byte, error) { 139 // Build a GET Request, including optional If-None-Match header. 140 req, err := http.NewRequest("GET", url, nil) 141 if err != nil { 142 cache.Data = nil 143 return nil, err 144 } 145 if !skip && cache.Data != nil { 146 req.Header.Add("If-None-Match", cache.Key) 147 req.Header.Add("If-Modified-Since", cache.Date) 148 } 149 150 client := &http.Client{} 151 resp, err := client.Do(req) 152 if err != nil { 153 cache.Data = nil 154 return nil, err 155 } 156 defer resp.Body.Close() 157 // No change from latest known Etag? 158 if resp.StatusCode == http.StatusNotModified { 159 return cache.Data, nil 160 } 161 162 if resp.StatusCode != 200 { 163 cache.Data = nil 164 return nil, errors.Errorf("Fetching notices failed with status code %d", resp.StatusCode) 165 } 166 167 cache.Data, err = ioutil.ReadAll(resp.Body) 168 if err != nil { 169 cache.Data = nil 170 return nil, err 171 } 172 173 // If etags headers are missing, ignore. 174 cache.Key = resp.Header.Get("ETag") 175 cache.Date = resp.Header.Get("Date") 176 return cache.Data, err 177 } 178 179 // Append tokens to passed baseUrl as query params 180 func AppendQueryParamsToURL(baseUrl string, params map[string]string) string { 181 u, err := url.Parse(baseUrl) 182 if err != nil { 183 return "" 184 } 185 q, err := url.ParseQuery(u.RawQuery) 186 if err != nil { 187 return "" 188 } 189 for key, value := range params { 190 q.Add(key, value) 191 } 192 u.RawQuery = q.Encode() 193 return u.String() 194 } 195 196 // Validates RedirectURL passed during OAuth or SAML 197 func IsValidWebAuthRedirectURL(config *model.Config, redirectURL string) bool { 198 u, err := url.Parse(redirectURL) 199 if err == nil && (u.Scheme == "http" || u.Scheme == "https") { 200 if config.ServiceSettings.SiteURL != nil { 201 siteUrl := *config.ServiceSettings.SiteURL 202 return strings.Index(strings.ToLower(redirectURL), strings.ToLower(siteUrl)) == 0 203 } 204 return false 205 } 206 return true 207 } 208 209 // Validates Mobile Custom URL Scheme passed during OAuth or SAML 210 func IsValidMobileAuthRedirectURL(config *model.Config, redirectURL string) bool { 211 for _, URLScheme := range config.NativeAppSettings.AppCustomURLSchemes { 212 if strings.Index(strings.ToLower(redirectURL), strings.ToLower(URLScheme)) == 0 { 213 return true 214 } 215 } 216 return false 217 }