1 module soup.CookieJar;
2 
3 private import glib.ConstructionException;
4 private import glib.ListSG;
5 private import glib.Str;
6 private import gobject.ObjectG;
7 private import gobject.Signals;
8 private import soup.Cookie;
9 private import soup.SessionFeatureIF;
10 private import soup.SessionFeatureT;
11 private import soup.URI;
12 private import soup.c.functions;
13 public  import soup.c.types;
14 private import std.algorithm;
15 
16 
17 /**
18  * A #SoupCookieJar stores #SoupCookie<!-- -->s and arrange for them
19  * to be sent with the appropriate #SoupMessage<!-- -->s.
20  * #SoupCookieJar implements #SoupSessionFeature, so you can add a
21  * cookie jar to a session with soup_session_add_feature() or
22  * soup_session_add_feature_by_type().
23  * 
24  * Note that the base #SoupCookieJar class does not support any form
25  * of long-term cookie persistence.
26  */
27 public class CookieJar : ObjectG, SessionFeatureIF
28 {
29 	/** the main Gtk struct */
30 	protected SoupCookieJar* soupCookieJar;
31 
32 	/** Get the main Gtk struct */
33 	public SoupCookieJar* getCookieJarStruct(bool transferOwnership = false)
34 	{
35 		if (transferOwnership)
36 			ownedRef = false;
37 		return soupCookieJar;
38 	}
39 
40 	/** the main Gtk struct as a void* */
41 	protected override void* getStruct()
42 	{
43 		return cast(void*)soupCookieJar;
44 	}
45 
46 	/**
47 	 * Sets our main struct and passes it to the parent class.
48 	 */
49 	public this (SoupCookieJar* soupCookieJar, bool ownedRef = false)
50 	{
51 		this.soupCookieJar = soupCookieJar;
52 		super(cast(GObject*)soupCookieJar, ownedRef);
53 	}
54 
55 	// add the SessionFeature capabilities
56 	mixin SessionFeatureT!(SoupCookieJar);
57 
58 
59 	/** */
60 	public static GType getType()
61 	{
62 		return soup_cookie_jar_get_type();
63 	}
64 
65 	/**
66 	 * Creates a new #SoupCookieJar. The base #SoupCookieJar class does
67 	 * not support persistent storage of cookies; use a subclass for that.
68 	 *
69 	 * Returns: a new #SoupCookieJar
70 	 *
71 	 * Since: 2.24
72 	 *
73 	 * Throws: ConstructionException GTK+ fails to create the object.
74 	 */
75 	public this()
76 	{
77 		auto __p = soup_cookie_jar_new();
78 
79 		if(__p is null)
80 		{
81 			throw new ConstructionException("null returned by new");
82 		}
83 
84 		this(cast(SoupCookieJar*) __p, true);
85 	}
86 
87 	/**
88 	 * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying
89 	 * an existing cookie or adding a valid new cookie ('valid' means
90 	 * that the cookie's expire date is not in the past).
91 	 *
92 	 * @cookie will be 'stolen' by the jar, so don't free it afterwards.
93 	 *
94 	 * Params:
95 	 *     cookie = a #SoupCookie
96 	 *
97 	 * Since: 2.26
98 	 */
99 	public void addCookie(Cookie cookie)
100 	{
101 		soup_cookie_jar_add_cookie(soupCookieJar, (cookie is null) ? null : cookie.getCookieStruct(true));
102 	}
103 
104 	/**
105 	 * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying
106 	 * an existing cookie or adding a valid new cookie ('valid' means
107 	 * that the cookie's expire date is not in the past).
108 	 *
109 	 * @first_party will be used to reject cookies coming from third party
110 	 * resources in case such a security policy is set in the @jar.
111 	 *
112 	 * @uri will be used to reject setting or overwriting secure cookies
113 	 * from insecure origins. %NULL is treated as secure.
114 	 *
115 	 * @cookie will be 'stolen' by the jar, so don't free it afterwards.
116 	 *
117 	 * Params:
118 	 *     cookie = a #SoupCookie
119 	 *     uri = the URI setting the cookie
120 	 *     firstParty = the URI for the main document
121 	 *
122 	 * Since: 2.68
123 	 */
124 	public void addCookieFull(Cookie cookie, URI uri, URI firstParty)
125 	{
126 		soup_cookie_jar_add_cookie_full(soupCookieJar, (cookie is null) ? null : cookie.getCookieStruct(true), (uri is null) ? null : uri.getURIStruct(), (firstParty is null) ? null : firstParty.getURIStruct());
127 	}
128 
129 	/**
130 	 * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying
131 	 * an existing cookie or adding a valid new cookie ('valid' means
132 	 * that the cookie's expire date is not in the past).
133 	 *
134 	 * @first_party will be used to reject cookies coming from third party
135 	 * resources in case such a security policy is set in the @jar.
136 	 *
137 	 * @cookie will be 'stolen' by the jar, so don't free it afterwards.
138 	 *
139 	 * For secure cookies to work properly you may want to use
140 	 * soup_cookie_jar_add_cookie_full().
141 	 *
142 	 * Params:
143 	 *     firstParty = the URI for the main document
144 	 *     cookie = a #SoupCookie
145 	 *
146 	 * Since: 2.40
147 	 */
148 	public void addCookieWithFirstParty(URI firstParty, Cookie cookie)
149 	{
150 		soup_cookie_jar_add_cookie_with_first_party(soupCookieJar, (firstParty is null) ? null : firstParty.getURIStruct(), (cookie is null) ? null : cookie.getCookieStruct(true));
151 	}
152 
153 	/**
154 	 * Constructs a #GSList with every cookie inside the @jar.
155 	 * The cookies in the list are a copy of the original, so
156 	 * you have to free them when you are done with them.
157 	 *
158 	 * Returns: a #GSList
159 	 *     with all the cookies in the @jar.
160 	 *
161 	 * Since: 2.26
162 	 */
163 	public ListSG allCookies()
164 	{
165 		auto __p = soup_cookie_jar_all_cookies(soupCookieJar);
166 
167 		if(__p is null)
168 		{
169 			return null;
170 		}
171 
172 		return new ListSG(cast(GSList*) __p, true);
173 	}
174 
175 	/**
176 	 * Deletes @cookie from @jar, emitting the 'changed' signal.
177 	 *
178 	 * Params:
179 	 *     cookie = a #SoupCookie
180 	 *
181 	 * Since: 2.26
182 	 */
183 	public void deleteCookie(Cookie cookie)
184 	{
185 		soup_cookie_jar_delete_cookie(soupCookieJar, (cookie is null) ? null : cookie.getCookieStruct());
186 	}
187 
188 	/**
189 	 * Gets @jar's #SoupCookieJarAcceptPolicy
190 	 *
191 	 * Returns: the #SoupCookieJarAcceptPolicy set in the @jar
192 	 *
193 	 * Since: 2.30
194 	 */
195 	public SoupCookieJarAcceptPolicy getAcceptPolicy()
196 	{
197 		return soup_cookie_jar_get_accept_policy(soupCookieJar);
198 	}
199 
200 	/**
201 	 * Retrieves the list of cookies that would be sent with a request to @uri
202 	 * as a #GSList of #SoupCookie objects.
203 	 *
204 	 * If @for_http is %TRUE, the return value will include cookies marked
205 	 * "HttpOnly" (that is, cookies that the server wishes to keep hidden
206 	 * from client-side scripting operations such as the JavaScript
207 	 * document.cookies property). Since #SoupCookieJar sets the Cookie
208 	 * header itself when making the actual HTTP request, you should
209 	 * almost certainly be setting @for_http to %FALSE if you are calling
210 	 * this.
211 	 *
212 	 * Params:
213 	 *     uri = a #SoupURI
214 	 *     forHttp = whether or not the return value is being passed directly
215 	 *         to an HTTP operation
216 	 *
217 	 * Returns: a #GSList
218 	 *     with the cookies in the @jar that would be sent with a request to @uri.
219 	 *
220 	 * Since: 2.40
221 	 */
222 	public ListSG getCookieList(URI uri, bool forHttp)
223 	{
224 		auto __p = soup_cookie_jar_get_cookie_list(soupCookieJar, (uri is null) ? null : uri.getURIStruct(), forHttp);
225 
226 		if(__p is null)
227 		{
228 			return null;
229 		}
230 
231 		return new ListSG(cast(GSList*) __p, true);
232 	}
233 
234 	/**
235 	 * This is an extended version of soup_cookie_jar_get_cookie_list() that
236 	 * provides more information required to use SameSite cookies. See the
237 	 * [SameSite cookies spec](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00)
238 	 * for more detailed information.
239 	 *
240 	 * Params:
241 	 *     uri = a #SoupURI
242 	 *     topLevel = a #SoupURI for the top level document
243 	 *     siteForCookies = a #SoupURI indicating the origin to get cookies for
244 	 *     forHttp = whether or not the return value is being passed directly
245 	 *         to an HTTP operation
246 	 *     isSafeMethod = if the HTTP method is safe, as defined by RFC 7231, ignored when @for_http is %FALSE
247 	 *     isTopLevelNavigation = whether or not the HTTP request is part of
248 	 *         top level navigation
249 	 *
250 	 * Returns: a #GSList
251 	 *     with the cookies in the @jar that would be sent with a request to @uri.
252 	 *
253 	 * Since: 2.70
254 	 */
255 	public ListSG getCookieListWithSameSiteInfo(URI uri, URI topLevel, URI siteForCookies, bool forHttp, bool isSafeMethod, bool isTopLevelNavigation)
256 	{
257 		auto __p = soup_cookie_jar_get_cookie_list_with_same_site_info(soupCookieJar, (uri is null) ? null : uri.getURIStruct(), (topLevel is null) ? null : topLevel.getURIStruct(), (siteForCookies is null) ? null : siteForCookies.getURIStruct(), forHttp, isSafeMethod, isTopLevelNavigation);
258 
259 		if(__p is null)
260 		{
261 			return null;
262 		}
263 
264 		return new ListSG(cast(GSList*) __p, true);
265 	}
266 
267 	/**
268 	 * Retrieves (in Cookie-header form) the list of cookies that would
269 	 * be sent with a request to @uri.
270 	 *
271 	 * If @for_http is %TRUE, the return value will include cookies marked
272 	 * "HttpOnly" (that is, cookies that the server wishes to keep hidden
273 	 * from client-side scripting operations such as the JavaScript
274 	 * document.cookies property). Since #SoupCookieJar sets the Cookie
275 	 * header itself when making the actual HTTP request, you should
276 	 * almost certainly be setting @for_http to %FALSE if you are calling
277 	 * this.
278 	 *
279 	 * Params:
280 	 *     uri = a #SoupURI
281 	 *     forHttp = whether or not the return value is being passed directly
282 	 *         to an HTTP operation
283 	 *
284 	 * Returns: the cookies, in string form, or %NULL if
285 	 *     there are no cookies for @uri.
286 	 *
287 	 * Since: 2.24
288 	 */
289 	public string getCookies(URI uri, bool forHttp)
290 	{
291 		auto retStr = soup_cookie_jar_get_cookies(soupCookieJar, (uri is null) ? null : uri.getURIStruct(), forHttp);
292 
293 		scope(exit) Str.freeString(retStr);
294 		return Str.toString(retStr);
295 	}
296 
297 	/**
298 	 * Gets whether @jar stores cookies persistenly.
299 	 *
300 	 * Returns: %TRUE if @jar storage is persistent or %FALSE otherwise.
301 	 *
302 	 * Since: 2.40
303 	 */
304 	public bool isPersistent()
305 	{
306 		return soup_cookie_jar_is_persistent(soupCookieJar) != 0;
307 	}
308 
309 	/**
310 	 * This function exists for backward compatibility, but does not do
311 	 * anything any more; cookie jars are saved automatically when they
312 	 * are changed.
313 	 *
314 	 * Deprecated: This is a no-op.
315 	 *
316 	 * Since: 2.24
317 	 */
318 	public void save()
319 	{
320 		soup_cookie_jar_save(soupCookieJar);
321 	}
322 
323 	/**
324 	 * Sets @policy as the cookie acceptance policy for @jar.
325 	 *
326 	 * Params:
327 	 *     policy = a #SoupCookieJarAcceptPolicy
328 	 *
329 	 * Since: 2.30
330 	 */
331 	public void setAcceptPolicy(SoupCookieJarAcceptPolicy policy)
332 	{
333 		soup_cookie_jar_set_accept_policy(soupCookieJar, policy);
334 	}
335 
336 	/**
337 	 * Adds @cookie to @jar, exactly as though it had appeared in a
338 	 * Set-Cookie header returned from a request to @uri.
339 	 *
340 	 * Keep in mind that if the #SoupCookieJarAcceptPolicy set is either
341 	 * %SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY or
342 	 * %SOUP_COOKIE_JAR_ACCEPT_GRANDFATHERED_THIRD_PARTY you'll need to use
343 	 * soup_cookie_jar_set_cookie_with_first_party(), otherwise the jar
344 	 * will have no way of knowing if the cookie is being set by a third
345 	 * party or not.
346 	 *
347 	 * Params:
348 	 *     uri = the URI setting the cookie
349 	 *     cookie = the stringified cookie to set
350 	 *
351 	 * Since: 2.24
352 	 */
353 	public void setCookie(URI uri, string cookie)
354 	{
355 		soup_cookie_jar_set_cookie(soupCookieJar, (uri is null) ? null : uri.getURIStruct(), Str.toStringz(cookie));
356 	}
357 
358 	/**
359 	 * Adds @cookie to @jar, exactly as though it had appeared in a
360 	 * Set-Cookie header returned from a request to @uri. @first_party
361 	 * will be used to reject cookies coming from third party resources in
362 	 * case such a security policy is set in the @jar.
363 	 *
364 	 * Params:
365 	 *     uri = the URI setting the cookie
366 	 *     firstParty = the URI for the main document
367 	 *     cookie = the stringified cookie to set
368 	 *
369 	 * Since: 2.30
370 	 */
371 	public void setCookieWithFirstParty(URI uri, URI firstParty, string cookie)
372 	{
373 		soup_cookie_jar_set_cookie_with_first_party(soupCookieJar, (uri is null) ? null : uri.getURIStruct(), (firstParty is null) ? null : firstParty.getURIStruct(), Str.toStringz(cookie));
374 	}
375 
376 	/**
377 	 * Emitted when @jar changes. If a cookie has been added,
378 	 * @new_cookie will contain the newly-added cookie and
379 	 * @old_cookie will be %NULL. If a cookie has been deleted,
380 	 * @old_cookie will contain the to-be-deleted cookie and
381 	 * @new_cookie will be %NULL. If a cookie has been changed,
382 	 * @old_cookie will contain its old value, and @new_cookie its
383 	 * new value.
384 	 *
385 	 * Params:
386 	 *     oldCookie = the old #SoupCookie value
387 	 *     newCookie = the new #SoupCookie value
388 	 */
389 	gulong addOnChanged(void delegate(Cookie, Cookie, CookieJar) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
390 	{
391 		return Signals.connect(this, "changed", dlg, connectFlags ^ ConnectFlags.SWAPPED);
392 	}
393 }