• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 636

05 Dec 2025 03:27AM UTC coverage: 80.509%. Remained the same
636

push

github

hazendaz
Cleanup more old since tags

you guessed it, at this point going to jautodoc the rest so the warnings on builds go away ;)

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8249 of 10132 relevant lines covered (81.42%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.44
/src/main/java/com/meterware/httpunit/cookies/CookieJar.java
1
/*
2
 * MIT License
3
 *
4
 * Copyright 2011-2025 Russell Gold
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
9
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions
12
 * of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
15
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
 * DEALINGS IN THE SOFTWARE.
19
 */
20
package com.meterware.httpunit.cookies;
21

22
import java.io.IOException;
23
import java.io.StreamTokenizer;
24
import java.io.StringReader;
25
import java.net.URL;
26
import java.util.ArrayList;
27
import java.util.Collection;
28
import java.util.HashMap;
29
import java.util.HashSet;
30
import java.util.Iterator;
31
import java.util.Vector;
32

33
/**
34
 * A collection of HTTP cookies, which can interact with cookie and set-cookie header values.
35
 **/
36
public class CookieJar {
37

38
    private static final int DEFAULT_HEADER_SIZE = 80;
39

40
    private ArrayList _cookies = new ArrayList<>();
1✔
41
    private ArrayList _globalCookies = new ArrayList<>();
1✔
42
    private CookiePress _press;
43

44
    /**
45
     * Creates an empty cookie jar.
46
     */
47
    public CookieJar() {
1✔
48
        _press = new CookiePress(null);
1✔
49
    }
1✔
50

51
    /**
52
     * Creates a cookie jar which is initially populated with cookies parsed from the <code>Set-Cookie</code> and
53
     * <code>Set-Cookie2</code> header fields.
54
     * <p>
55
     * Note that the parsing does not strictly follow the specifications, but attempts to imitate the behavior of
56
     * popular browsers. Specifically, it allows cookie values to contain commas, which the Netscape standard does not
57
     * allow for, but which is required by some servers.
58
     * </p>
59
     */
60
    public CookieJar(CookieSource source) {
1✔
61
        _press = new CookiePress(source.getURL());
1✔
62
        findCookies(source.getHeaderFields("Set-Cookie"), new RFC2109CookieRecipe());
1✔
63
        findCookies(source.getHeaderFields("Set-Cookie2"), new RFC2965CookieRecipe());
1✔
64
    }
1✔
65

66
    /**
67
     * find the cookies in the given Header String array
68
     *
69
     * @param cookieHeader
70
     *            - the strings to look for cookies
71
     * @param recipe
72
     *            - the recipe to use
73
     */
74
    private void findCookies(String cookieHeader[], CookieRecipe recipe) {
75
        for (String element : cookieHeader) {
1✔
76
            recipe.findCookies(element);
1✔
77
        }
78
    }
1✔
79

80
    /**
81
     * Empties this cookie jar of all contents.
82
     */
83
    public void clear() {
84
        _cookies.clear();
×
85
        _globalCookies.clear();
×
86
    }
×
87

88
    /**
89
     * Defines a cookie to be sent to the server on every request. This bypasses the normal mechanism by which only
90
     * certain cookies are sent based on their host and path.
91
     *
92
     * @deprecated as of 1.6, use #putCookie
93
     **/
94
    @Deprecated
95
    public void addCookie(String name, String value) {
96
        _globalCookies.add(new Cookie(name, value));
×
97
    }
×
98

99
    /**
100
     * Defines a cookie to be sent to the server on every request. This bypasses the normal mechanism by which only
101
     * certain cookies are sent based on their host and path. Values of null will result in the cookie being removed.
102
     * Any other value will leave the cookie unchanged expect for the value.
103
     **/
104
    public void putCookie(String name, String value) {
105
        boolean foundCookie = false;
1✔
106
        for (Iterator iterator = _globalCookies.iterator(); iterator.hasNext();) {
1✔
107
            Cookie cookie = (Cookie) iterator.next();
1✔
108
            if (name.equals(cookie.getName())) {
1✔
109
                foundCookie = true;
1✔
110
                if (value != null) {
1✔
111
                    cookie.setValue(value);
1✔
112
                } else {
113
                    iterator.remove();
1✔
114
                }
115
            }
116
        }
1✔
117

118
        for (Iterator iterator = _cookies.iterator(); iterator.hasNext();) {
1✔
119
            Cookie cookie = (Cookie) iterator.next();
1✔
120
            if (name.equals(cookie.getName())) {
1!
121
                foundCookie = true;
1✔
122
                if (value != null) {
1!
123
                    cookie.setValue(value);
1✔
124
                } else {
125
                    iterator.remove();
×
126
                }
127
            }
128
        }
1✔
129

130
        // only add it if it does not already exist
131
        if (!foundCookie) {
1✔
132
            _globalCookies.add(new Cookie(name, value));
1✔
133
        }
134
    }
1✔
135

136
    /**
137
     * Define a non-global cookie. This cookie can be overwritten by subsequent cookie definitions in http headers. This
138
     * cookie definition requires a domain and path. If a global cookie is defined with the same name, this cookie is
139
     * not added.
140
     */
141
    public void putSingleUseCookie(String name, String value, String domain, String path) {
142
        for (Iterator iterator = _globalCookies.iterator(); iterator.hasNext();) {
1!
143
            Cookie cookie = (Cookie) iterator.next();
×
144
            if (name.equals(cookie.getName())) {
×
145
                return;
×
146
            }
147
        }
×
148

149
        for (Iterator iterator = _cookies.iterator(); iterator.hasNext();) {
1!
150
            Cookie cookie = (Cookie) iterator.next();
×
151
            if (name.equals(cookie.getName())) {
×
152
                iterator.remove();
×
153
            }
154
        }
×
155

156
        _cookies.add(new Cookie(name, value, domain, path));
1✔
157
    }
1✔
158

159
    /**
160
     * Returns the name of all the active cookies in this cookie jar.
161
     **/
162
    public String[] getCookieNames() {
163
        final int numGlobalCookies = _globalCookies.size();
1✔
164
        String[] names = new String[_cookies.size() + numGlobalCookies];
1✔
165
        for (int i = 0; i < numGlobalCookies; i++) {
1✔
166
            names[i] = ((Cookie) _globalCookies.get(i)).getName();
1✔
167
        }
168
        for (int i = numGlobalCookies; i < names.length; i++) {
1✔
169
            names[i] = ((Cookie) _cookies.get(i - numGlobalCookies)).getName();
1✔
170
        }
171
        return names;
1✔
172
    }
173

174
    /**
175
     * Returns a collection containing all of the cookies in this jar.
176
     */
177
    public Collection getCookies() {
178
        final Collection collection = (Collection) _cookies.clone();
1✔
179
        collection.addAll(_globalCookies);
1✔
180
        return collection;
1✔
181
    }
182

183
    /**
184
     * Returns the value of the specified cookie.
185
     *
186
     * @param name
187
     *            - the name of the cookie to get the value for
188
     *
189
     * @return the value of the cookie
190
     **/
191
    public String getCookieValue(String name) {
192
        Cookie cookie = getCookie(name);
1✔
193
        return cookie == null ? null : cookie.getValue();
1✔
194
    }
195

196
    /**
197
     * Returns the value of the specified cookie.
198
     **/
199
    public Cookie getCookie(String name) {
200
        if (name == null) {
1!
201
            throw new IllegalArgumentException("getCookieValue: no name specified");
×
202
        }
203
        for (Iterator iterator = _cookies.iterator(); iterator.hasNext();) {
1✔
204
            Cookie cookie = (Cookie) iterator.next();
1✔
205
            if (name.equals(cookie.getName())) {
1✔
206
                return cookie;
1✔
207
            }
208
        }
1✔
209
        for (Iterator iterator = _globalCookies.iterator(); iterator.hasNext();) {
1✔
210
            Cookie cookie = (Cookie) iterator.next();
1✔
211
            if (name.equals(cookie.getName())) {
1!
212
                return cookie;
1✔
213
            }
214
        }
×
215
        return null;
1✔
216
    }
217

218
    /**
219
     * Returns the value of the cookie header to be sent to the specified URL. Will return null if no compatible cookie
220
     * is defined.
221
     **/
222
    public String getCookieHeaderField(URL targetURL) {
223
        if (_cookies.isEmpty() && _globalCookies.isEmpty()) {
1✔
224
            return null;
1✔
225
        }
226
        StringBuilder sb = new StringBuilder(DEFAULT_HEADER_SIZE);
1✔
227
        HashSet restrictedCookies = new HashSet<>();
1✔
228
        for (Iterator i = _cookies.iterator(); i.hasNext();) {
1✔
229
            Cookie cookie = (Cookie) i.next();
1✔
230
            if (!cookie.mayBeSentTo(targetURL)) {
1✔
231
                continue;
1✔
232
            }
233
            restrictedCookies.add(cookie.getName());
1✔
234
            if (sb.length() != 0) {
1✔
235
                sb.append("; ");
1✔
236
            }
237
            sb.append(cookie.getName()).append('=').append(cookie.getValue());
1✔
238
        }
1✔
239
        for (Iterator i = _globalCookies.iterator(); i.hasNext();) {
1✔
240
            Cookie cookie = (Cookie) i.next();
1✔
241
            if (restrictedCookies.contains(cookie.getName())) {
1✔
242
                continue;
1✔
243
            }
244
            if (sb.length() != 0) {
1✔
245
                sb.append("; ");
1✔
246
            }
247
            sb.append(cookie.getName()).append('=').append(cookie.getValue());
1✔
248
        }
1✔
249
        return sb.length() == 0 ? null : sb.toString();
1!
250
    }
251

252
    /**
253
     * Updates the cookies maintained in this cookie jar with those in another cookie jar. Any duplicate cookies in the
254
     * new jar will replace those in this jar.
255
     **/
256
    public void updateCookies(CookieJar newJar) {
257
        for (Iterator i = newJar._cookies.iterator(); i.hasNext();) {
1✔
258
            addUniqueCookie((Cookie) i.next());
1✔
259
        }
260
    }
1✔
261

262
    /**
263
     * Add the cookie to this jar, replacing any previous matching cookie.
264
     */
265
    void addUniqueCookie(Cookie cookie) {
266
        _cookies.remove(cookie);
1✔
267
        for (Iterator i = _cookies.iterator(); i.hasNext();) {
1✔
268
            Cookie c = (Cookie) i.next();
1✔
269
            if (c.getName().equals(cookie.getName()) && compareDomain(c.getDomain(), cookie.getDomain())) {
1!
270
                if (c.getPath() != null && cookie.getPath() != null && c.getPath().equals(cookie.getPath())) {
1!
271
                    i.remove();
1✔
272
                }
273
            }
274
        }
1✔
275
        _cookies.add(cookie);
1✔
276
    }
1✔
277

278
    /**
279
     * compare the two domains given for "cookie-equality"
280
     *
281
     * @param domain
282
     * @param newDomain
283
     *
284
     * @return
285
     */
286
    private boolean compareDomain(String domain, String newDomain) {
287
        if (domain.charAt(0) == '.' && newDomain.endsWith(domain)
1!
288
                || newDomain.charAt(0) == '.' && domain.endsWith(newDomain)) {
1!
289
            return true;
1✔
290
        }
291

292
        return domain.equals(newDomain);
×
293
    }
294

295
    /**
296
     * base class for the cookie recipies - there are two different implementations of this
297
     */
298
    abstract class CookieRecipe {
1✔
299

300
        /**
301
         * Extracts cookies from a cookie header. Works in conjunction with a cookie press class, which actually creates
302
         * the cookies and adds them to the jar as appropriate. 1. Parse the header into tokens, separated by ',' and
303
         * ';' (respecting single and double quotes) 2. Process tokens from the end: a. if the token contains an '=' we
304
         * have a name/value pair. Add them to the cookie press, which will decide if it is a cookie name or an
305
         * attribute name. b. if the token is a reserved word, flush the cookie press and continue. c. otherwise, add
306
         * the token to the cookie press, passing along the last character of the previous token.
307
         */
308
        void findCookies(String cookieHeader) {
309
            Vector tokens = getCookieTokens(cookieHeader);
1✔
310

311
            for (int i = tokens.size() - 1; i >= 0; i--) {
1✔
312
                String token = (String) tokens.elementAt(i);
1✔
313

314
                int equalsIndex = getEqualsIndex(token);
1✔
315
                if (equalsIndex != -1) {
1✔
316
                    _press.addTokenWithEqualsSign(this, token, equalsIndex);
1✔
317
                } else if (isCookieReservedWord(token)) {
1!
318
                    _press.clear();
×
319
                } else {
320
                    _press.addToken(token, lastCharOf(i == 0 ? "" : (String) tokens.elementAt(i - 1)));
1!
321
                }
322
            }
323
        }
1✔
324

325
        private char lastCharOf(String string) {
326
            return string.isEmpty() ? ' ' : string.charAt(string.length() - 1);
1!
327
        }
328

329
        /**
330
         * Returns the index (if any) of the equals sign separating a cookie name from the its value. Equals signs at
331
         * the end of the token are ignored in this calculation, since they may be part of a Base64-encoded value.
332
         */
333
        private int getEqualsIndex(String token) {
334
            if (!token.endsWith("==")) {
1✔
335
                return token.indexOf('=');
1✔
336
            }
337
            return getEqualsIndex(token.substring(0, token.length() - 2));
1✔
338
        }
339

340
        /**
341
         * Tokenizes a cookie header and returns the tokens in a <code>Vector</code>. handles the broken syntax for
342
         * expires= fields ...
343
         *
344
         * @param cookieHeader
345
         *            - the header to read
346
         *
347
         * @return a Vector of cookieTokens as name=value pairs
348
         **/
349
        private Vector getCookieTokens(String cookieHeader) {
350
            StringReader sr = new StringReader(cookieHeader);
1✔
351
            StreamTokenizer st = new StreamTokenizer(sr);
1✔
352
            Vector tokens = new Vector<>();
1✔
353

354
            // clear syntax tables of the StreamTokenizer
355
            st.resetSyntax();
1✔
356

357
            // set all characters as word characters
358
            st.wordChars(0, Character.MAX_VALUE);
1✔
359

360
            // set up characters for quoting
361
            st.quoteChar('"'); // double quotes
1✔
362
            st.quoteChar('\''); // single quotes
1✔
363

364
            // set up characters to separate tokens
365
            st.whitespaceChars(59, 59); // semicolon
1✔
366
            // and here we run into trouble ...
367
            // see http://www.mnot.net/blog/2006/10/27/cookie_fun
368
            // ... Notice something about the above? It uses a comma inside of
369
            // the date,
370
            // without quoting the value. This makes it difficult for generic
371
            // processors to handle the Set-Cookie header.
372
            st.whitespaceChars(44, 44); // comma
1✔
373

374
            try {
375
                while (st.nextToken() != StreamTokenizer.TT_EOF) {
1✔
376
                    String tokenContent = st.sval;
1✔
377
                    // fix expires comma delimiter token problem
378
                    if (tokenContent.toLowerCase().startsWith("expires=") && st.nextToken() != StreamTokenizer.TT_EOF) {
1!
379
                        tokenContent += "," + st.sval;
1✔
380
                    } // if // if
381
                    tokenContent = tokenContent.trim();
1✔
382
                    tokens.addElement(tokenContent);
1✔
383
                }
1✔
384
            } catch (IOException ioe) {
×
385
                // this will never happen with a StringReader
386
            }
1✔
387
            sr.close();
1✔
388
            return tokens;
1✔
389
        }
390

391
        abstract protected boolean isCookieAttribute(String stringLowercase);
392

393
        abstract protected boolean isCookieReservedWord(String token);
394

395
    }
396

397
    /**
398
     * cookie Factory - creates cookies for URL s
399
     */
400
    class CookiePress {
401

402
        // the current value
403
        private StringBuilder _value = new StringBuilder();
1✔
404
        private HashMap _attributes = new HashMap<>();
1✔
405
        private URL _sourceURL;
406

407
        /**
408
         * create a cookie press for the given URL
409
         *
410
         * @param sourceURL
411
         */
412
        public CookiePress(URL sourceURL) {
1✔
413
            _sourceURL = sourceURL;
1✔
414
        }
1✔
415

416
        /**
417
         * clear the attributes and the cookie value
418
         */
419
        void clear() {
420
            _value.setLength(0);
×
421
            _attributes.clear();
×
422
        }
×
423

424
        /**
425
         * add the token content
426
         *
427
         * @param token
428
         * @param lastChar
429
         */
430
        void addToken(String token, char lastChar) {
431
            _value.insert(0, token);
1✔
432
            if (lastChar != '=') {
1!
433
                _value.insert(0, ',');
1✔
434
            }
435
        }
1✔
436

437
        /**
438
         * add from a token
439
         *
440
         * @param recipe
441
         *            - the recipe to use
442
         * @param token
443
         *            - the token to use
444
         * @param equalsIndex
445
         *            - the position of the equal sign
446
         */
447
        void addTokenWithEqualsSign(CookieRecipe recipe, String token, int equalsIndex) {
448
            final String name = token.substring(0, equalsIndex).trim();
1✔
449
            final String value = token.substring(equalsIndex + 1).trim();
1✔
450
            _value.insert(0, value);
1✔
451
            final String fvalue = _value.toString();
1✔
452
            if (recipe.isCookieAttribute(name.toLowerCase())) {
1✔
453
                _attributes.put(name.toLowerCase(), value);
1✔
454
            } else {
455
                addCookieIfValid(new Cookie(name, fvalue, _attributes));
1✔
456
                _attributes.clear();
1✔
457
            }
458
            _value.setLength(0);
1✔
459
        }
1✔
460

461
        /**
462
         * add the given cookie if it is valid
463
         *
464
         * @param cookie
465
         */
466
        private void addCookieIfValid(Cookie cookie) {
467
            if (acceptCookie(cookie)) {
1✔
468
                addUniqueCookie(cookie);
1✔
469
            }
470
        }
1✔
471

472
        /**
473
         * accept the given cookie
474
         *
475
         * @param cookie
476
         *
477
         * @return
478
         */
479
        private boolean acceptCookie(Cookie cookie) {
480
            if (cookie.getPath() == null) {
1✔
481
                cookie.setPath(getParentPath(_sourceURL.getPath()));
1✔
482
            } else {
483
                int status = getPathAttributeStatus(cookie.getPath(), _sourceURL.getPath());
1✔
484
                if (status != CookieListener.ACCEPTED) {
1✔
485
                    reportCookieRejected(status, cookie.getPath(), cookie.getName());
1✔
486
                    return false;
1✔
487
                }
488
            }
489

490
            if (cookie.getDomain() == null || !CookieProperties.isDomainMatchingStrict()
1✔
491
                    && cookie.getDomain().equalsIgnoreCase(_sourceURL.getHost())) {
1✔
492
                cookie.setDomain(_sourceURL.getHost());
1✔
493
            } else {
494
                int status = getDomainAttributeStatus(cookie, _sourceURL.getHost());
1✔
495
                if (status != CookieListener.ACCEPTED) {
1✔
496
                    reportCookieRejected(status, cookie.getDomain(), cookie.getName());
1✔
497
                    return false;
1✔
498
                }
499
            }
500

501
            return true;
1✔
502
        }
503

504
        private String getParentPath(String path) {
505
            int rightmostSlashIndex = path.lastIndexOf('/');
1✔
506
            return rightmostSlashIndex < 0 ? "/" : path.substring(0, rightmostSlashIndex);
1✔
507
        }
508

509
        private int getPathAttributeStatus(String pathAttribute, String sourcePath) {
510
            if (!CookieProperties.isPathMatchingStrict() || sourcePath.isEmpty()
1✔
511
                    || sourcePath.startsWith(pathAttribute)) {
1✔
512
                return CookieListener.ACCEPTED;
1✔
513
            }
514
            return CookieListener.PATH_NOT_PREFIX;
1✔
515
        }
516

517
        /**
518
         * get the domainAttribute Status for the given cookie with the given sourceHost
519
         *
520
         * @see http://wp.netscape.com/newsref/std/cookie_spec.html
521
         *
522
         * @param cookie
523
         *            - the cookie to use
524
         * @param sourceHost
525
         *
526
         * @return
527
         */
528
        private int getDomainAttributeStatus(Cookie cookie, String sourceHost) {
529
            String domainAttribute = cookie.getDomain();
1✔
530
            // patch according to [ 1476380 ] Cookies incorrectly rejected
531
            // despite valid domain
532
            if (domainAttribute.equals(sourceHost)) {
1✔
533
                return CookieListener.ACCEPTED;
1✔
534
            }
535
            if (!domainAttribute.startsWith(".")) {
1✔
536
                domainAttribute = '.' + domainAttribute;
1✔
537
            }
538

539
            if (domainAttribute.lastIndexOf('.') == 0) {
1✔
540
                return CookieListener.DOMAIN_ONE_DOT;
1✔
541
            }
542
            if (!sourceHost.endsWith(domainAttribute)) {
1✔
543
                return CookieListener.DOMAIN_NOT_SOURCE_SUFFIX;
1✔
544
            }
545
            if (CookieProperties.isDomainMatchingStrict()
1✔
546
                    && sourceHost.lastIndexOf(domainAttribute) > sourceHost.indexOf('.')) {
1✔
547
                return CookieListener.DOMAIN_TOO_MANY_LEVELS;
1✔
548
            }
549
            // modified for Bugreport 2825872 Cookie domains not stored correctly - ID: 2825872
550
            // http://sourceforge.net/tracker/?func=detail&aid=2825872&group_id=6550&atid=106550
551
            cookie.setDomain(domainAttribute);
1✔
552
            return CookieListener.ACCEPTED;
1✔
553
        }
554

555
        private boolean reportCookieRejected(int reason, String attribute, String source) {
556
            CookieProperties.reportCookieRejected(reason, attribute, source);
1✔
557
            return false;
1✔
558
        }
559

560
    }
561

562
    /**
563
     * Parses cookies according to <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a> <br />
564
     * These cookies come from the <code>Set-Cookie:</code> header
565
     **/
566
    class RFC2109CookieRecipe extends CookieRecipe {
1✔
567

568
        /**
569
         * check whether the given lower case String is a cookie attribute
570
         *
571
         * @param stringLowercase
572
         *            - the string to check
573
         *
574
         * @return true - if the string is the name of a valid cookie attribute
575
         */
576
        @Override
577
        protected boolean isCookieAttribute(String stringLowercase) {
578
            return stringLowercase.equals("path") || stringLowercase.equals("domain")
1✔
579
                    || stringLowercase.equals("expires") || stringLowercase.equals("comment")
1!
580
                    || stringLowercase.equals("max-age") || stringLowercase.equals("version");
1!
581
        }
582

583
        @Override
584
        protected boolean isCookieReservedWord(String token) {
585
            return token.equalsIgnoreCase("secure");
1✔
586
        }
587
    }
588

589
    /**
590
     * Parses cookies according to <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a> <br />
591
     * These cookies come from the <code>Set-Cookie2:</code> header
592
     **/
593
    class RFC2965CookieRecipe extends CookieRecipe {
1✔
594

595
        @Override
596
        protected boolean isCookieAttribute(String stringLowercase) {
597
            return stringLowercase.equals("path") || stringLowercase.equals("domain")
×
598
                    || stringLowercase.equals("comment") || stringLowercase.equals("commenturl")
×
599
                    || stringLowercase.equals("max-age") || stringLowercase.equals("version")
×
600
                    || stringLowercase.equals("$version") || stringLowercase.equals("port");
×
601
        }
602

603
        @Override
604
        protected boolean isCookieReservedWord(String token) {
605
            return token.equalsIgnoreCase("discard") || token.equalsIgnoreCase("secure");
×
606
        }
607
    }
608

609
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc