1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2008, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexander Krivonogov ( gentee )
11 *
12 ******************************************************************************/
13 include {
14 "..\\gt\\gt.g"
15 }
16
17 type cookies <inherit = gt>
18 {
19 str curfilename
20 hash hosts
21 }
22
23 type cookie
24 {
25 str name
26 str value
27 str domain
28 str path
29 datetime expires
30 uint secure
31 }
32
33 method cookies.read( str filename )
34 {
35 datetime cdt, dt
36 cdt.gettime()
37 this->gt.read( filename )
38 .curfilename = filename
39 foreach chost, this.root()
40 {
41 foreach ccookie, chost
42 {
43 dt.fromstr( ccookie.get( "expires" ))
44 if dt < cdt
45 {
46 ccookie.del()
47 }
48 }
49 if chost.child()
50 {
51 str name
52 chost.get("name", name )
53 this.hosts[name] = &chost
54 }
55 else : chost.del()
56
57 }
58 }
59
60 method cookies.write( str filename )
61 {
62 if &filename && *filename : this->gt.write( filename )
63 }
64
65 method cookies.write()
66 {
67 .write( .curfilename )
68 }
69
70
71 method str cookies.get<result>( str host, str path )
72 {
73 datetime cdt, dt
74 arrstr arp
75 cdt.gettime()
76 str domain2
77 host.split( arp, '.', 0 )
78 if *arp >= 1
79 {
80 domain2 = "\(arp[*arp-2]).\(arp[*arp-1])"
81 }
82 else : domain2=host
83
84 uint chost = .hosts.find(domain2)
85 if chost
86 {
87 chost as chost->uint->gtitem
88 foreach ccookie, chost
89 {
90
91 dt.fromstr( ccookie.get( "expires" ) )
92 if dt.year!=0 && dt < cdt
93 {
94 ccookie.del()
95 }
96 else
97 {
98 if ccookie.get( "path" ).eqlen( path )
99 {
100 str domain
101 ccookie.get( "domain", domain )
102 if *host >= *domain
103 {
104 if "".substr( host, *host - *domain, *domain ) == domain
105 {
106 if *result : result@"; "
107 result@"\(ccookie.get("name",""))=\(ccookie.value)"
108 }
109 }
110 }
111
112 /* str cpath
113 ccookie.get( "path", cpath )
114 if cpath.eqlen( path )
115 {
116 if *result : result@"; ";
117 result@"\(ccookie.name)=\(ccookie.value)"
118 }*/
119 }
120 }
121 }
122 }
123
124
125 method cookies.set( str host, str path, str setcookie )
126 {
127 cookie c
128 arrstr arp
129 str domain2
130 host.split( arp, '.', 0 )
131 if *arp >= 1
132 {
133 domain2="\(arp[*arp-2]).\(arp[*arp-1])"
134 }
135 else : domain2=host
136 arp.clear()
137
138 c.path = path
139 c.domain = host
140
141 setcookie.split( arp, ';', $SPLIT_NOSYS )
142 foreach pair, arp
143 {
144 arrstr arv
145 pair.split( arv, '=', $SPLIT_NOSYS | $SPLIT_FIRST )
146 if *arv
147 {
148 str val, stmp
149
150 if *arv[0] > 4096 : arv[0].setlen( 4096 )
151 if *arv > 1
152 {
153 val = arv[1]
154 if *val > 4096 : val.setlen( 4096 )
155 }
156 stmp = arv[0]
157 stmp.lower()
158 switch ( stmp )
159 {
160 case "secure": c.secure = 1
161 case "path": c.path = val
162 case "domain": c.domain = val
163 case "expires": c.expires.frominet( val )
164 case "httponly": ;
165 default
166 {
167 c.name = arv[0]
168 c.value = val
169 }
170 }
171 }
172 }
173 if *c.name
174 {
175 uint curhost
176 if curhost = this.hosts.find( domain2 )
177 {
178 curhost = curhost->uint
179 }
180 else
181 {
182 curhost as this.root().insertchild( "", (-1)->gtitem )
183 curhost.set( "name", domain2 )
184 this.hosts[ domain2 ] = &curhost
185 }
186
187 curhost as gtitem
188
189 foreach curcookie, curhost
190 {
191 if curcookie.get( "name" ) == c.name &&
192 curcookie.get( "path" ) == c.path &&
193 curcookie.get( "domain" ) == c.domain
194 {
195 break
196 }
197 }
198 if !&curcookie
199 {
200 curcookie as curhost.insertchild( "", (-1)->gtitem )
201 }
202
203 curcookie.value = c.value
204 curcookie.set( "name", c.name )
205 curcookie.setuint( "secure", c.secure )
206 curcookie.set( "path", c.path )
207 curcookie.set( "domain", c.domain )
208 curcookie.set( "expires", c.expires.tostr("") )
209 }
210 }
211
212 method cookies.parse( str host, str path, str shead )
213 {
214 arrstr val
215 arrstr lines
216 shead.split( lines, 0xA, $SPLIT_NOSYS )
217 if *lines
218 {
219 foreach cur, lines
220 {
221 cur.split( val, ':', $SPLIT_NOSYS | $SPLIT_FIRST )
222 if *val == 2 &&
223 val[0] == "Set-Cookie" : this.set( host, path, val[1] )
224 }
225 }
226 }
227
228 global {
229 cookies mcookies
230 uint usecookies
231 }
232
233 /*-----------------------------------------------------------------------------
234 * Idx: cookies_init F
235 *
236 * Summary: Cookies initialization. Функции http_get,
237 http_post, http_file, http_header будут использовать cookies.
238 Cookies от предыдущих сеансов будут браться из файла.
239 *
240 * Params: filename - The file name where stored cookies data.
241 *
242 -----------------------------------------------------------------------------*/
243 func cookies_init( str filename )
244 {
245 usecookies = 1
246 mcookies.clear()
247 mcookies.read( filename )
248 }
249
250 /*-----------------------------------------------------------------------------
251 * Idx: cookies_init F
252 *
253 * Summary: Cookies initialization. Функции http_get,
254 http_post, http_file, http_header будут использовать cookies.
255 *
256 * Params: filename - The file name where stored cookies data.
257 *
258 -----------------------------------------------------------------------------*/
259 func cookies_init( )
260 {
261 cookies_init( "" )
262 }
263
264 /*-----------------------------------------------------------------------------
265 * Idx: cookies_deinit F
266 *
267 * Summary: Отключение использования cookies и запись данных в файл,
268 если он был указан при cookies_init.
269 *
270 *
271 -----------------------------------------------------------------------------*/
272 func cookies_deinit( )
273 {
274 usecookies = 0
275 mcookies.write()
276 mcookies.hosts.clear()
277 mcookies.clear()
278 }
279