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 }