OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [http/] [cookie.go] - Blame information for rev 848

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package http
6
 
7
import (
8
        "bytes"
9
        "fmt"
10
        "strconv"
11
        "strings"
12
        "time"
13
)
14
 
15
// This implementation is done according to RFC 6265:
16
//
17
//    http://tools.ietf.org/html/rfc6265
18
 
19
// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
20
// HTTP response or the Cookie header of an HTTP request.
21
type Cookie struct {
22
        Name       string
23
        Value      string
24
        Path       string
25
        Domain     string
26
        Expires    time.Time
27
        RawExpires string
28
 
29
        // MaxAge=0 means no 'Max-Age' attribute specified.
30
        // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
31
        // MaxAge>0 means Max-Age attribute present and given in seconds
32
        MaxAge   int
33
        Secure   bool
34
        HttpOnly bool
35
        Raw      string
36
        Unparsed []string // Raw text of unparsed attribute-value pairs
37
}
38
 
39
// readSetCookies parses all "Set-Cookie" values from
40
// the header h and returns the successfully parsed Cookies.
41
func readSetCookies(h Header) []*Cookie {
42
        cookies := []*Cookie{}
43
        for _, line := range h["Set-Cookie"] {
44
                parts := strings.Split(strings.TrimSpace(line), ";")
45
                if len(parts) == 1 && parts[0] == "" {
46
                        continue
47
                }
48
                parts[0] = strings.TrimSpace(parts[0])
49
                j := strings.Index(parts[0], "=")
50
                if j < 0 {
51
                        continue
52
                }
53
                name, value := parts[0][:j], parts[0][j+1:]
54
                if !isCookieNameValid(name) {
55
                        continue
56
                }
57
                value, success := parseCookieValue(value)
58
                if !success {
59
                        continue
60
                }
61
                c := &Cookie{
62
                        Name:  name,
63
                        Value: value,
64
                        Raw:   line,
65
                }
66
                for i := 1; i < len(parts); i++ {
67
                        parts[i] = strings.TrimSpace(parts[i])
68
                        if len(parts[i]) == 0 {
69
                                continue
70
                        }
71
 
72
                        attr, val := parts[i], ""
73
                        if j := strings.Index(attr, "="); j >= 0 {
74
                                attr, val = attr[:j], attr[j+1:]
75
                        }
76
                        lowerAttr := strings.ToLower(attr)
77
                        parseCookieValueFn := parseCookieValue
78
                        if lowerAttr == "expires" {
79
                                parseCookieValueFn = parseCookieExpiresValue
80
                        }
81
                        val, success = parseCookieValueFn(val)
82
                        if !success {
83
                                c.Unparsed = append(c.Unparsed, parts[i])
84
                                continue
85
                        }
86
                        switch lowerAttr {
87
                        case "secure":
88
                                c.Secure = true
89
                                continue
90
                        case "httponly":
91
                                c.HttpOnly = true
92
                                continue
93
                        case "domain":
94
                                c.Domain = val
95
                                // TODO: Add domain parsing
96
                                continue
97
                        case "max-age":
98
                                secs, err := strconv.Atoi(val)
99
                                if err != nil || secs != 0 && val[0] == '0' {
100
                                        break
101
                                }
102
                                if secs <= 0 {
103
                                        c.MaxAge = -1
104
                                } else {
105
                                        c.MaxAge = secs
106
                                }
107
                                continue
108
                        case "expires":
109
                                c.RawExpires = val
110
                                exptime, err := time.Parse(time.RFC1123, val)
111
                                if err != nil {
112
                                        exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
113
                                        if err != nil {
114
                                                c.Expires = time.Time{}
115
                                                break
116
                                        }
117
                                }
118
                                c.Expires = exptime.UTC()
119
                                continue
120
                        case "path":
121
                                c.Path = val
122
                                // TODO: Add path parsing
123
                                continue
124
                        }
125
                        c.Unparsed = append(c.Unparsed, parts[i])
126
                }
127
                cookies = append(cookies, c)
128
        }
129
        return cookies
130
}
131
 
132
// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
133
func SetCookie(w ResponseWriter, cookie *Cookie) {
134
        w.Header().Add("Set-Cookie", cookie.String())
135
}
136
 
137
// String returns the serialization of the cookie for use in a Cookie
138
// header (if only Name and Value are set) or a Set-Cookie response
139
// header (if other fields are set).
140
func (c *Cookie) String() string {
141
        var b bytes.Buffer
142
        fmt.Fprintf(&b, "%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
143
        if len(c.Path) > 0 {
144
                fmt.Fprintf(&b, "; Path=%s", sanitizeValue(c.Path))
145
        }
146
        if len(c.Domain) > 0 {
147
                fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(c.Domain))
148
        }
149
        if c.Expires.Unix() > 0 {
150
                fmt.Fprintf(&b, "; Expires=%s", c.Expires.UTC().Format(time.RFC1123))
151
        }
152
        if c.MaxAge > 0 {
153
                fmt.Fprintf(&b, "; Max-Age=%d", c.MaxAge)
154
        } else if c.MaxAge < 0 {
155
                fmt.Fprintf(&b, "; Max-Age=0")
156
        }
157
        if c.HttpOnly {
158
                fmt.Fprintf(&b, "; HttpOnly")
159
        }
160
        if c.Secure {
161
                fmt.Fprintf(&b, "; Secure")
162
        }
163
        return b.String()
164
}
165
 
166
// readCookies parses all "Cookie" values from the header h and
167
// returns the successfully parsed Cookies.
168
//
169
// if filter isn't empty, only cookies of that name are returned
170
func readCookies(h Header, filter string) []*Cookie {
171
        cookies := []*Cookie{}
172
        lines, ok := h["Cookie"]
173
        if !ok {
174
                return cookies
175
        }
176
 
177
        for _, line := range lines {
178
                parts := strings.Split(strings.TrimSpace(line), ";")
179
                if len(parts) == 1 && parts[0] == "" {
180
                        continue
181
                }
182
                // Per-line attributes
183
                parsedPairs := 0
184
                for i := 0; i < len(parts); i++ {
185
                        parts[i] = strings.TrimSpace(parts[i])
186
                        if len(parts[i]) == 0 {
187
                                continue
188
                        }
189
                        name, val := parts[i], ""
190
                        if j := strings.Index(name, "="); j >= 0 {
191
                                name, val = name[:j], name[j+1:]
192
                        }
193
                        if !isCookieNameValid(name) {
194
                                continue
195
                        }
196
                        if filter != "" && filter != name {
197
                                continue
198
                        }
199
                        val, success := parseCookieValue(val)
200
                        if !success {
201
                                continue
202
                        }
203
                        cookies = append(cookies, &Cookie{Name: name, Value: val})
204
                        parsedPairs++
205
                }
206
        }
207
        return cookies
208
}
209
 
210
var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
211
 
212
func sanitizeName(n string) string {
213
        return cookieNameSanitizer.Replace(n)
214
}
215
 
216
var cookieValueSanitizer = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")
217
 
218
func sanitizeValue(v string) string {
219
        return cookieValueSanitizer.Replace(v)
220
}
221
 
222
func unquoteCookieValue(v string) string {
223
        if len(v) > 1 && v[0] == '"' && v[len(v)-1] == '"' {
224
                return v[1 : len(v)-1]
225
        }
226
        return v
227
}
228
 
229
func isCookieByte(c byte) bool {
230
        switch {
231
        case c == 0x21, 0x23 <= c && c <= 0x2b, 0x2d <= c && c <= 0x3a,
232
                0x3c <= c && c <= 0x5b, 0x5d <= c && c <= 0x7e:
233
                return true
234
        }
235
        return false
236
}
237
 
238
func isCookieExpiresByte(c byte) (ok bool) {
239
        return isCookieByte(c) || c == ',' || c == ' '
240
}
241
 
242
func parseCookieValue(raw string) (string, bool) {
243
        return parseCookieValueUsing(raw, isCookieByte)
244
}
245
 
246
func parseCookieExpiresValue(raw string) (string, bool) {
247
        return parseCookieValueUsing(raw, isCookieExpiresByte)
248
}
249
 
250
func parseCookieValueUsing(raw string, validByte func(byte) bool) (string, bool) {
251
        raw = unquoteCookieValue(raw)
252
        for i := 0; i < len(raw); i++ {
253
                if !validByte(raw[i]) {
254
                        return "", false
255
                }
256
        }
257
        return raw, true
258
}
259
 
260
func isCookieNameValid(raw string) bool {
261
        for _, c := range raw {
262
                if !isToken(byte(c)) {
263
                        return false
264
                }
265
        }
266
        return true
267
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.