ReactOS  0.4.12-dev-396-g37af787
cookie.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "config.h"
20 #include <stdarg.h>
21 
22 #include "wine/debug.h"
23 #include "wine/list.h"
24 
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winhttp.h"
28 
29 #include "winhttp_private.h"
30 
32 
33 static domain_t *add_domain( session_t *session, WCHAR *name )
34 {
35  domain_t *domain;
36 
37  if (!(domain = heap_alloc_zero( sizeof(domain_t) ))) return NULL;
38 
39  list_init( &domain->entry );
40  list_init( &domain->cookies );
41 
42  domain->name = strdupW( name );
43  list_add_tail( &session->cookie_cache, &domain->entry );
44 
45  TRACE("%s\n", debugstr_w(domain->name));
46  return domain;
47 }
48 
49 static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *name )
50 {
51  struct list *item;
52  cookie_t *cookie;
53 
54  LIST_FOR_EACH( item, &domain->cookies )
55  {
56  cookie = LIST_ENTRY( item, cookie_t, entry );
57  if (!strcmpW( cookie->path, path ) && !strcmpW( cookie->name, name ))
58  {
59  TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value));
60  return cookie;
61  }
62  }
63  return NULL;
64 }
65 
66 static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial )
67 {
68  TRACE("comparing %s with %s\n", debugstr_w(name), debugstr_w(domain->name));
69 
70  if (partial && !strstrW( name, domain->name )) return FALSE;
71  else if (!partial && strcmpW( name, domain->name )) return FALSE;
72  return TRUE;
73 }
74 
75 static void free_cookie( cookie_t *cookie )
76 {
77  heap_free( cookie->name );
78  heap_free( cookie->value );
79  heap_free( cookie->path );
80  heap_free( cookie );
81 }
82 
83 static void delete_cookie( cookie_t *cookie )
84 {
85  list_remove( &cookie->entry );
86  free_cookie( cookie );
87 }
88 
89 void delete_domain( domain_t *domain )
90 {
91  cookie_t *cookie;
92  struct list *item, *next;
93 
94  LIST_FOR_EACH_SAFE( item, next, &domain->cookies )
95  {
96  cookie = LIST_ENTRY( item, cookie_t, entry );
97  delete_cookie( cookie );
98  }
99 
100  list_remove( &domain->entry );
101  heap_free( domain->name );
102  heap_free( domain );
103 }
104 
105 static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR *path )
106 {
107  domain_t *domain = NULL;
108  cookie_t *old_cookie;
109  struct list *item;
110 
111  LIST_FOR_EACH( item, &session->cookie_cache )
112  {
113  domain = LIST_ENTRY( item, domain_t, entry );
114  if (domain_match( domain_name, domain, FALSE )) break;
115  domain = NULL;
116  }
117  if (!domain)
118  {
119  if (!(domain = add_domain( session, domain_name ))) return FALSE;
120  }
121  else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie );
122 
123  cookie->path = strdupW( path );
124  list_add_head( &domain->cookies, &cookie->entry );
125 
126  TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path),
127  debugstr_w(cookie->name), debugstr_w(cookie->value));
128  return TRUE;
129 }
130 
131 static cookie_t *parse_cookie( const WCHAR *string )
132 {
133  cookie_t *cookie;
134  const WCHAR *p;
135  int len;
136 
137  if (!(p = strchrW( string, '=' ))) p = string + strlenW( string );
138  len = p - string;
139  while (len && string[len - 1] == ' ') len--;
140  if (!len) return NULL;
141 
142  if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL;
143  list_init( &cookie->entry );
144 
145  if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
146  {
147  heap_free( cookie );
148  return NULL;
149  }
150  memcpy( cookie->name, string, len * sizeof(WCHAR) );
151  cookie->name[len] = 0;
152 
153  if (*p++ == '=')
154  {
155  while (*p == ' ') p++;
156  len = strlenW( p );
157  while (len && p[len - 1] == ' ') len--;
158 
159  if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
160  {
161  free_cookie( cookie );
162  return NULL;
163  }
164  memcpy( cookie->value, p, len * sizeof(WCHAR) );
165  cookie->value[len] = 0;
166  }
167  return cookie;
168 }
169 
170 struct attr
171 {
174 };
175 
176 static void free_attr( struct attr *attr )
177 {
178  if (!attr) return;
179  heap_free( attr->name );
180  heap_free( attr->value );
181  heap_free( attr );
182 }
183 
184 static struct attr *parse_attr( const WCHAR *str, int *used )
185 {
186  const WCHAR *p = str, *q;
187  struct attr *attr;
188  int len;
189 
190  while (*p == ' ') p++;
191  q = p;
192  while (*q && *q != ' ' && *q != '=' && *q != ';') q++;
193  len = q - p;
194  if (!len) return NULL;
195 
196  if (!(attr = heap_alloc( sizeof(struct attr) ))) return NULL;
197  if (!(attr->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
198  {
199  heap_free( attr );
200  return NULL;
201  }
202  memcpy( attr->name, p, len * sizeof(WCHAR) );
203  attr->name[len] = 0;
204  attr->value = NULL;
205 
206  p = q;
207  while (*p == ' ') p++;
208  if (*p++ == '=')
209  {
210  while (*p == ' ') p++;
211  q = p;
212  while (*q && *q != ';') q++;
213  len = q - p;
214  while (len && p[len - 1] == ' ') len--;
215 
216  if (!(attr->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
217  {
218  free_attr( attr );
219  return NULL;
220  }
221  memcpy( attr->value, p, len * sizeof(WCHAR) );
222  attr->value[len] = 0;
223  }
224 
225  while (*q == ' ') q++;
226  if (*q == ';') q++;
227  *used = q - str;
228 
229  return attr;
230 }
231 
233 {
234  static const WCHAR pathW[] = {'p','a','t','h',0};
235  static const WCHAR domainW[] = {'d','o','m','a','i','n',0};
236  BOOL ret = FALSE;
237  WCHAR *buffer, *p;
238  WCHAR *cookie_domain = NULL, *cookie_path = NULL;
239  struct attr *attr, *domain = NULL, *path = NULL;
240  session_t *session = request->connect->session;
241  cookie_t *cookie;
242  int len, used;
243 
244  len = strlenW( cookies );
245  if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
246  strcpyW( buffer, cookies );
247 
248  p = buffer;
249  while (*p && *p != ';') p++;
250  if (*p == ';') *p++ = 0;
251  if (!(cookie = parse_cookie( buffer )))
252  {
253  heap_free( buffer );
254  return FALSE;
255  }
256  len = strlenW( p );
257  while (len && (attr = parse_attr( p, &used )))
258  {
259  if (!strcmpiW( attr->name, domainW ))
260  {
261  domain = attr;
262  cookie_domain = attr->value;
263  }
264  else if (!strcmpiW( attr->name, pathW ))
265  {
266  path = attr;
267  cookie_path = attr->value;
268  }
269  else
270  {
271  FIXME( "unhandled attribute %s\n", debugstr_w(attr->name) );
272  free_attr( attr );
273  }
274  len -= used;
275  p += used;
276  }
277  if (!cookie_domain && !(cookie_domain = strdupW( request->connect->servername ))) goto end;
278  if (!cookie_path && !(cookie_path = strdupW( request->path ))) goto end;
279 
280  if ((p = strrchrW( cookie_path, '/' )) && p != cookie_path) *p = 0;
281  ret = add_cookie( session, cookie, cookie_domain, cookie_path );
282 
283 end:
284  if (!ret) free_cookie( cookie );
285  if (domain) free_attr( domain );
286  else heap_free( cookie_domain );
287  if (path) free_attr( path );
288  else heap_free( cookie_path );
289  heap_free( buffer );
290  return ret;
291 }
292 
294 {
295  struct list *domain_cursor;
296  session_t *session = request->connect->session;
297 
298  LIST_FOR_EACH( domain_cursor, &session->cookie_cache )
299  {
300  domain_t *domain = LIST_ENTRY( domain_cursor, domain_t, entry );
301  if (domain_match( request->connect->servername, domain, TRUE ))
302  {
303  struct list *cookie_cursor;
304  TRACE("found domain %s\n", debugstr_w(domain->name));
305 
306  LIST_FOR_EACH( cookie_cursor, &domain->cookies )
307  {
308  cookie_t *cookie = LIST_ENTRY( cookie_cursor, cookie_t, entry );
309 
310  TRACE("comparing path %s with %s\n", debugstr_w(request->path), debugstr_w(cookie->path));
311 
312  if (strstrW( request->path, cookie->path ) == request->path)
313  {
314  const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
315  int len, len_cookie = sizeof(cookieW) / sizeof(cookieW[0]), len_name = strlenW( cookie->name );
316  WCHAR *header;
317 
318  len = len_cookie + len_name;
319  if (cookie->value) len += strlenW( cookie->value ) + 1;
320  if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
321 
322  memcpy( header, cookieW, len_cookie * sizeof(WCHAR) );
323  strcpyW( header + len_cookie, cookie->name );
324  if (cookie->value)
325  {
326  header[len_cookie + len_name] = '=';
327  strcpyW( header + len_cookie + len_name + 1, cookie->value );
328  }
329 
330  TRACE("%s\n", debugstr_w(header));
333  heap_free( header );
334  }
335  }
336  }
337  }
338  return TRUE;
339 }
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192
#define TRUE
Definition: types.h:120
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
WCHAR * value
Definition: cookie.c:173
#define WINHTTP_ADDREQ_FLAG_ADD
Definition: winhttp.h:84
struct list entry
__wchar_t WCHAR
Definition: xmlstorage.h:180
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
uint8_t entry
Definition: isohybrid.c:63
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
GLuint buffer
Definition: glext.h:5915
BOOL add_cookie_headers(request_t *request)
Definition: cookie.c:293
GLuint GLuint end
Definition: gl.h:1545
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
WINE_DEFAULT_DEBUG_CHANNEL(winhttp)
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
static cookie_t * find_cookie(domain_t *domain, const WCHAR *path, const WCHAR *name)
Definition: cookie.c:49
static void free_attr(struct attr *attr)
Definition: cookie.c:176
static domain_t * add_domain(session_t *session, WCHAR *name)
Definition: cookie.c:33
WCHAR * name
struct list entry
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
char path[256]
Definition: tftpd.h:94
const WCHAR * str
#define strstrW(d, s)
Definition: unicode.h:32
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:188
smooth NULL
Definition: ftsmooth.c:416
static BOOL domain_match(const WCHAR *name, domain_t *domain, BOOL partial)
Definition: cookie.c:66
struct list cookie_cache
#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
Definition: winhttp.h:86
c used
Definition: write.c:2885
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define TRACE(s)
Definition: solgame.cpp:4
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL add_request_headers(request_t *request, LPCWSTR headers, DWORD len, DWORD flags)
Definition: request.c:474
Definition: cookie.c:170
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
int ret
static CookieInternal * cookies
Definition: msctf.c:67
__u8 attr
Definition: mkdosfs.c:359
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
WCHAR * name
BOOL set_cookies(request_t *request, const WCHAR *cookies)
Definition: cookie.c:232
static struct attr * parse_attr(const WCHAR *str, int *used)
Definition: cookie.c:184
char string[160]
Definition: util.h:11
#define strcmpiW(s1, s2)
Definition: unicode.h:39
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
static unsigned __int64 next
Definition: rand_nt.c:6
static ATOM item
Definition: dde.c:856
static void free_cookie(cookie_t *cookie)
Definition: cookie.c:75
Definition: services.c:325
static cookie_t * parse_cookie(const WCHAR *string)
Definition: cookie.c:131
WCHAR * value
Definition: tftpd.h:85
Definition: name.c:36
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
WCHAR * name
Definition: cookie.c:172
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
struct list cookies
static void delete_cookie(cookie_t *cookie)
Definition: cookie.c:83
GLfloat GLfloat p
Definition: glext.h:8902
#define LIST_ENTRY(type)
Definition: queue.h:175
void delete_domain(domain_t *domain)
Definition: cookie.c:89
struct CFHEADER header
Definition: fdi.c:109
WCHAR * path
static BOOL add_cookie(session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR *path)
Definition: cookie.c:105
static BOOL heap_free(void *mem)
Definition: appwiz.h:75