ReactOS  0.4.14-dev-583-g2a1ba2c
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 "ws2tcpip.h"
21 #include <stdarg.h>
22 
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winhttp.h"
26 
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 #include "winhttp_private.h"
30 
32 
33 struct cookie
34 {
35  struct list entry;
39 };
40 
41 struct domain
42 {
43  struct list entry;
45  struct list cookies;
46 };
47 
48 static struct domain *add_domain( struct session *session, WCHAR *name )
49 {
50  struct domain *domain;
51 
52  if (!(domain = heap_alloc_zero( sizeof(struct domain) ))) return NULL;
53 
54  list_init( &domain->entry );
56 
57  domain->name = strdupW( name );
59 
60  TRACE("%s\n", debugstr_w(domain->name));
61  return domain;
62 }
63 
64 static struct cookie *find_cookie( struct domain *domain, const WCHAR *path, const WCHAR *name )
65 {
66  struct list *item;
67  struct cookie *cookie;
68 
70  {
71  cookie = LIST_ENTRY( item, struct cookie, entry );
72  if (!strcmpW( cookie->path, path ) && !strcmpW( cookie->name, name ))
73  {
74  TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value));
75  return cookie;
76  }
77  }
78  return NULL;
79 }
80 
81 static BOOL domain_match( const WCHAR *name, struct domain *domain, BOOL partial )
82 {
83  TRACE("comparing %s with %s\n", debugstr_w(name), debugstr_w(domain->name));
84 
85  if (partial && !strstrW( name, domain->name )) return FALSE;
86  else if (!partial && strcmpW( name, domain->name )) return FALSE;
87  return TRUE;
88 }
89 
90 static void free_cookie( struct cookie *cookie )
91 {
92  heap_free( cookie->name );
94  heap_free( cookie->path );
95  heap_free( cookie );
96 }
97 
98 static void delete_cookie( struct cookie *cookie )
99 {
100  list_remove( &cookie->entry );
101  free_cookie( cookie );
102 }
103 
104 static void delete_domain( struct domain *domain )
105 {
106  struct cookie *cookie;
107  struct list *item, *next;
108 
110  {
111  cookie = LIST_ENTRY( item, struct cookie, entry );
113  }
114 
115  list_remove( &domain->entry );
116  heap_free( domain->name );
117  heap_free( domain );
118 }
119 
121 {
122  struct list *item, *next;
123  struct domain *domain;
124 
126  {
127  domain = LIST_ENTRY( item, struct domain, entry );
129  }
130 }
131 
132 static BOOL add_cookie( struct session *session, struct cookie *cookie, WCHAR *domain_name, WCHAR *path )
133 {
134  struct domain *domain = NULL;
135  struct cookie *old_cookie;
136  struct list *item;
137 
138  if (!(cookie->path = strdupW( path ))) return FALSE;
139 
141 
143  {
144  domain = LIST_ENTRY( item, struct domain, entry );
145  if (domain_match( domain_name, domain, FALSE )) break;
146  domain = NULL;
147  }
148  if (!domain) domain = add_domain( session, domain_name );
149  else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie );
150 
151  if (domain)
152  {
154  TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path),
156  }
157 
159  return domain != NULL;
160 }
161 
162 static struct cookie *parse_cookie( const WCHAR *string )
163 {
164  struct cookie *cookie;
165  const WCHAR *p;
166  int len;
167 
168  if (!(p = strchrW( string, '=' ))) p = string + strlenW( string );
169  len = p - string;
170  while (len && string[len - 1] == ' ') len--;
171  if (!len) return NULL;
172 
173  if (!(cookie = heap_alloc_zero( sizeof(struct cookie) ))) return NULL;
174  list_init( &cookie->entry );
175 
176  if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
177  {
178  heap_free( cookie );
179  return NULL;
180  }
181  memcpy( cookie->name, string, len * sizeof(WCHAR) );
182  cookie->name[len] = 0;
183 
184  if (*p++ == '=')
185  {
186  while (*p == ' ') p++;
187  len = strlenW( p );
188  while (len && p[len - 1] == ' ') len--;
189 
190  if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
191  {
192  free_cookie( cookie );
193  return NULL;
194  }
195  memcpy( cookie->value, p, len * sizeof(WCHAR) );
196  cookie->value[len] = 0;
197  }
198  return cookie;
199 }
200 
201 struct attr
202 {
205 };
206 
207 static void free_attr( struct attr *attr )
208 {
209  if (!attr) return;
210  heap_free( attr->name );
211  heap_free( attr->value );
212  heap_free( attr );
213 }
214 
215 static struct attr *parse_attr( const WCHAR *str, int *used )
216 {
217  const WCHAR *p = str, *q;
218  struct attr *attr;
219  int len;
220 
221  while (*p == ' ') p++;
222  q = p;
223  while (*q && *q != ' ' && *q != '=' && *q != ';') q++;
224  len = q - p;
225  if (!len) return NULL;
226 
227  if (!(attr = heap_alloc( sizeof(struct attr) ))) return NULL;
228  if (!(attr->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
229  {
230  heap_free( attr );
231  return NULL;
232  }
233  memcpy( attr->name, p, len * sizeof(WCHAR) );
234  attr->name[len] = 0;
235  attr->value = NULL;
236 
237  p = q;
238  while (*p == ' ') p++;
239  if (*p++ == '=')
240  {
241  while (*p == ' ') p++;
242  q = p;
243  while (*q && *q != ';') q++;
244  len = q - p;
245  while (len && p[len - 1] == ' ') len--;
246 
247  if (!(attr->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
248  {
249  free_attr( attr );
250  return NULL;
251  }
252  memcpy( attr->value, p, len * sizeof(WCHAR) );
253  attr->value[len] = 0;
254  }
255 
256  while (*q == ' ') q++;
257  if (*q == ';') q++;
258  *used = q - str;
259 
260  return attr;
261 }
262 
264 {
265  static const WCHAR pathW[] = {'p','a','t','h',0};
266  static const WCHAR domainW[] = {'d','o','m','a','i','n',0};
267  BOOL ret = FALSE;
268  WCHAR *buffer, *p;
269  WCHAR *cookie_domain = NULL, *cookie_path = NULL;
270  struct attr *attr, *domain = NULL, *path = NULL;
271  struct session *session = request->connect->session;
272  struct cookie *cookie;
273  int len, used;
274 
275  len = strlenW( cookies );
276  if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
277  strcpyW( buffer, cookies );
278 
279  p = buffer;
280  while (*p && *p != ';') p++;
281  if (*p == ';') *p++ = 0;
282  if (!(cookie = parse_cookie( buffer )))
283  {
284  heap_free( buffer );
285  return FALSE;
286  }
287  len = strlenW( p );
288  while (len && (attr = parse_attr( p, &used )))
289  {
290  if (!strcmpiW( attr->name, domainW ))
291  {
292  domain = attr;
293  cookie_domain = attr->value;
294  }
295  else if (!strcmpiW( attr->name, pathW ))
296  {
297  path = attr;
298  cookie_path = attr->value;
299  }
300  else
301  {
302  FIXME( "unhandled attribute %s\n", debugstr_w(attr->name) );
303  free_attr( attr );
304  }
305  len -= used;
306  p += used;
307  }
308  if (!cookie_domain && !(cookie_domain = strdupW( request->connect->servername ))) goto end;
309  if (!cookie_path && !(cookie_path = strdupW( request->path ))) goto end;
310 
311  if ((p = strrchrW( cookie_path, '/' )) && p != cookie_path) *p = 0;
312  ret = add_cookie( session, cookie, cookie_domain, cookie_path );
313 
314 end:
315  if (!ret) free_cookie( cookie );
316  if (domain) free_attr( domain );
317  else heap_free( cookie_domain );
318  if (path) free_attr( path );
319  else heap_free( cookie_path );
320  heap_free( buffer );
321  return ret;
322 }
323 
325 {
326  struct list *domain_cursor;
327  struct session *session = request->connect->session;
328 
330 
331  LIST_FOR_EACH( domain_cursor, &session->cookie_cache )
332  {
333  struct domain *domain = LIST_ENTRY( domain_cursor, struct domain, entry );
334  if (domain_match( request->connect->servername, domain, TRUE ))
335  {
336  struct list *cookie_cursor;
337  TRACE("found domain %s\n", debugstr_w(domain->name));
338 
339  LIST_FOR_EACH( cookie_cursor, &domain->cookies )
340  {
341  struct cookie *cookie = LIST_ENTRY( cookie_cursor, struct cookie, entry );
342 
343  TRACE("comparing path %s with %s\n", debugstr_w(request->path), debugstr_w(cookie->path));
344 
345  if (strstrW( request->path, cookie->path ) == request->path)
346  {
347  static const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
348  int len, len_cookie = ARRAY_SIZE( cookieW ), len_name = strlenW( cookie->name );
349  WCHAR *header;
350 
351  len = len_cookie + len_name;
352  if (cookie->value) len += strlenW( cookie->value ) + 1;
353  if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) )))
354  {
356  return FALSE;
357  }
358 
359  memcpy( header, cookieW, len_cookie * sizeof(WCHAR) );
360  strcpyW( header + len_cookie, cookie->name );
361  if (cookie->value)
362  {
363  header[len_cookie + len_name] = '=';
364  strcpyW( header + len_cookie + len_name + 1, cookie->value );
365  }
366 
367  TRACE("%s\n", debugstr_w(header));
370  heap_free( header );
371  }
372  }
373  }
374  }
375 
377  return TRUE;
378 }
BOOL add_request_headers(struct request *request, const WCHAR *headers, DWORD len, DWORD flags)
Definition: request.c:495
struct connect * connect
#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
static struct cookie * find_cookie(struct domain *domain, const WCHAR *path, const WCHAR *name)
Definition: cookie.c:64
WCHAR * value
Definition: cookie.c:204
#define WINHTTP_ADDREQ_FLAG_ADD
Definition: winhttp.h:84
struct list cookies
Definition: cookie.c:45
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
static void delete_cookie(struct cookie *cookie)
Definition: cookie.c:98
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
BOOL set_cookies(struct request *request, const WCHAR *cookies)
Definition: cookie.c:263
GLuint buffer
Definition: glext.h:5915
GLuint GLuint end
Definition: gl.h:1545
WCHAR * name
Definition: cookie.c:36
static BOOL domain_match(const WCHAR *name, struct domain *domain, BOOL partial)
Definition: cookie.c:81
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
WCHAR * name
Definition: cookie.c:44
Definition: cookie.c:41
WINE_DEFAULT_DEBUG_CHANNEL(winhttp)
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
static void free_attr(struct attr *attr)
Definition: cookie.c:207
WCHAR * value
Definition: cookie.c:37
unsigned int BOOL
Definition: ntddk_ex.h:94
#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 struct domain * add_domain(struct session *session, WCHAR *name)
Definition: cookie.c:48
static BOOL add_cookie(struct session *session, struct cookie *cookie, WCHAR *domain_name, WCHAR *path)
Definition: cookie.c:132
#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
Definition: winhttp.h:86
void destroy_cookies(struct session *session)
Definition: cookie.c:120
c used
Definition: write.c:2877
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define TRACE(s)
Definition: solgame.cpp:4
CRITICAL_SECTION cs
__wchar_t WCHAR
Definition: xmlstorage.h:180
static struct cookie * parse_cookie(const WCHAR *string)
Definition: cookie.c:162
Definition: cookie.c:201
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
BOOL add_cookie_headers(struct request *request)
Definition: cookie.c:324
int ret
static CookieInternal * cookies
Definition: msctf.c:65
__u8 attr
Definition: mkdosfs.c:359
struct list cookie_cache
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
static struct attr * parse_attr(const WCHAR *str, int *used)
Definition: cookie.c:215
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
struct list entry
Definition: cookie.c:43
static void free_cookie(struct cookie *cookie)
Definition: cookie.c:90
#define ARRAY_SIZE(a)
Definition: main.h:24
Definition: cookie.c:33
Definition: tftpd.h:85
WCHAR * path
Definition: cookie.c:38
struct list entry
Definition: cookie.c:35
Definition: name.c:38
static void delete_domain(struct domain *domain)
Definition: cookie.c:104
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
WCHAR * name
Definition: cookie.c:203
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
GLfloat GLfloat p
Definition: glext.h:8902
#define LIST_ENTRY(type)
Definition: queue.h:175
struct CFHEADER header
Definition: fdi.c:101
static BOOL heap_free(void *mem)
Definition: appwiz.h:75