Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "nsCookie.h" |
michael@0 | 7 | #include "nsUTF8ConverterService.h" |
michael@0 | 8 | #include <stdlib.h> |
michael@0 | 9 | |
michael@0 | 10 | /****************************************************************************** |
michael@0 | 11 | * nsCookie: |
michael@0 | 12 | * string helper impl |
michael@0 | 13 | ******************************************************************************/ |
michael@0 | 14 | |
michael@0 | 15 | // copy aSource strings into contiguous storage provided in aDest1, |
michael@0 | 16 | // providing terminating nulls for each destination string. |
michael@0 | 17 | static inline void |
michael@0 | 18 | StrBlockCopy(const nsACString &aSource1, |
michael@0 | 19 | const nsACString &aSource2, |
michael@0 | 20 | const nsACString &aSource3, |
michael@0 | 21 | const nsACString &aSource4, |
michael@4 | 22 | const nsACString &aSource5, |
michael@0 | 23 | char *&aDest1, |
michael@0 | 24 | char *&aDest2, |
michael@0 | 25 | char *&aDest3, |
michael@0 | 26 | char *&aDest4, |
michael@4 | 27 | char *&aDest5, |
michael@0 | 28 | char *&aDestEnd) |
michael@0 | 29 | { |
michael@0 | 30 | char *toBegin = aDest1; |
michael@0 | 31 | nsACString::const_iterator fromBegin, fromEnd; |
michael@0 | 32 | |
michael@0 | 33 | *copy_string(aSource1.BeginReading(fromBegin), aSource1.EndReading(fromEnd), toBegin) = char(0); |
michael@0 | 34 | aDest2 = ++toBegin; |
michael@0 | 35 | *copy_string(aSource2.BeginReading(fromBegin), aSource2.EndReading(fromEnd), toBegin) = char(0); |
michael@0 | 36 | aDest3 = ++toBegin; |
michael@0 | 37 | *copy_string(aSource3.BeginReading(fromBegin), aSource3.EndReading(fromEnd), toBegin) = char(0); |
michael@0 | 38 | aDest4 = ++toBegin; |
michael@0 | 39 | *copy_string(aSource4.BeginReading(fromBegin), aSource4.EndReading(fromEnd), toBegin) = char(0); |
michael@4 | 40 | aDest5 = ++toBegin; |
michael@4 | 41 | *copy_string(aSource5.BeginReading(fromBegin), aSource5.EndReading(fromEnd), toBegin) = char(0); |
michael@0 | 42 | aDestEnd = toBegin; |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | /****************************************************************************** |
michael@0 | 46 | * nsCookie: |
michael@0 | 47 | * creation helper |
michael@0 | 48 | ******************************************************************************/ |
michael@0 | 49 | |
michael@0 | 50 | // This is a counter that keeps track of the last used creation time, each time |
michael@0 | 51 | // we create a new nsCookie. This is nominally the time (in microseconds) the |
michael@0 | 52 | // cookie was created, but is guaranteed to be monotonically increasing for |
michael@0 | 53 | // cookies added at runtime after the database has been read in. This is |
michael@0 | 54 | // necessary to enforce ordering among cookies whose creation times would |
michael@0 | 55 | // otherwise overlap, since it's possible two cookies may be created at the same |
michael@0 | 56 | // time, or that the system clock isn't monotonic. |
michael@0 | 57 | static int64_t gLastCreationTime; |
michael@0 | 58 | |
michael@0 | 59 | int64_t |
michael@0 | 60 | nsCookie::GenerateUniqueCreationTime(int64_t aCreationTime) |
michael@0 | 61 | { |
michael@0 | 62 | // Check if the creation time given to us is greater than the running maximum |
michael@0 | 63 | // (it should always be monotonically increasing). |
michael@0 | 64 | if (aCreationTime > gLastCreationTime) { |
michael@0 | 65 | gLastCreationTime = aCreationTime; |
michael@0 | 66 | return aCreationTime; |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | // Make up our own. |
michael@0 | 70 | return ++gLastCreationTime; |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | nsCookie * |
michael@0 | 74 | nsCookie::Create(const nsACString &aName, |
michael@0 | 75 | const nsACString &aValue, |
michael@0 | 76 | const nsACString &aHost, |
michael@4 | 77 | const nsACString &aOrigin, |
michael@0 | 78 | const nsACString &aPath, |
michael@0 | 79 | int64_t aExpiry, |
michael@0 | 80 | int64_t aLastAccessed, |
michael@0 | 81 | int64_t aCreationTime, |
michael@0 | 82 | bool aIsSession, |
michael@0 | 83 | bool aIsSecure, |
michael@0 | 84 | bool aIsHttpOnly) |
michael@0 | 85 | { |
michael@0 | 86 | // Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will |
michael@0 | 87 | // truncate the string after the first invalid octet. |
michael@0 | 88 | nsUTF8ConverterService converter; |
michael@0 | 89 | nsAutoCString aUTF8Value; |
michael@0 | 90 | converter.ConvertStringToUTF8(aValue, "UTF-8", false, true, 1, aUTF8Value); |
michael@0 | 91 | |
michael@4 | 92 | // find the required string buffer size, accommodating terminating nulls |
michael@0 | 93 | const uint32_t stringLength = aName.Length() + aUTF8Value.Length() + |
michael@4 | 94 | aHost.Length() + aOrigin.Length() + |
michael@4 | 95 | aPath.Length() + 5; |
michael@0 | 96 | |
michael@0 | 97 | // allocate contiguous space for the nsCookie and its strings - |
michael@0 | 98 | // we store the strings in-line with the nsCookie to save allocations |
michael@0 | 99 | void *place = ::operator new(sizeof(nsCookie) + stringLength); |
michael@0 | 100 | if (!place) |
michael@0 | 101 | return nullptr; |
michael@0 | 102 | |
michael@0 | 103 | // assign string members |
michael@4 | 104 | char *name, *value, *host, *origin, *path, *end; |
michael@0 | 105 | name = static_cast<char *>(place) + sizeof(nsCookie); |
michael@4 | 106 | StrBlockCopy(aName, aUTF8Value, aHost, aOrigin, aPath, |
michael@4 | 107 | name, value, host, origin, path, end); |
michael@0 | 108 | |
michael@0 | 109 | // If the creationTime given to us is higher than the running maximum, update |
michael@0 | 110 | // our maximum. |
michael@0 | 111 | if (aCreationTime > gLastCreationTime) |
michael@0 | 112 | gLastCreationTime = aCreationTime; |
michael@0 | 113 | |
michael@0 | 114 | // construct the cookie. placement new, oh yeah! |
michael@4 | 115 | return new (place) nsCookie(name, value, host, origin, path, end, |
michael@0 | 116 | aExpiry, aLastAccessed, aCreationTime, |
michael@0 | 117 | aIsSession, aIsSecure, aIsHttpOnly); |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | size_t |
michael@0 | 121 | nsCookie::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const |
michael@0 | 122 | { |
michael@0 | 123 | // There is no need to measure the sizes of the individual string |
michael@0 | 124 | // members, since the strings are stored in-line with the nsCookie. |
michael@0 | 125 | return aMallocSizeOf(this); |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | /****************************************************************************** |
michael@0 | 129 | * nsCookie: |
michael@0 | 130 | * xpcom impl |
michael@0 | 131 | ******************************************************************************/ |
michael@0 | 132 | |
michael@0 | 133 | // xpcom getters |
michael@0 | 134 | NS_IMETHODIMP nsCookie::GetName(nsACString &aName) { aName = Name(); return NS_OK; } |
michael@0 | 135 | NS_IMETHODIMP nsCookie::GetValue(nsACString &aValue) { aValue = Value(); return NS_OK; } |
michael@4 | 136 | NS_IMETHODIMP nsCookie::GetOrigin(nsACString &aOrigin) { aOrigin = Origin(); return NS_OK; } |
michael@0 | 137 | NS_IMETHODIMP nsCookie::GetHost(nsACString &aHost) { aHost = Host(); return NS_OK; } |
michael@0 | 138 | NS_IMETHODIMP nsCookie::GetRawHost(nsACString &aHost) { aHost = RawHost(); return NS_OK; } |
michael@0 | 139 | NS_IMETHODIMP nsCookie::GetPath(nsACString &aPath) { aPath = Path(); return NS_OK; } |
michael@0 | 140 | NS_IMETHODIMP nsCookie::GetExpiry(int64_t *aExpiry) { *aExpiry = Expiry(); return NS_OK; } |
michael@0 | 141 | NS_IMETHODIMP nsCookie::GetIsSession(bool *aIsSession) { *aIsSession = IsSession(); return NS_OK; } |
michael@0 | 142 | NS_IMETHODIMP nsCookie::GetIsDomain(bool *aIsDomain) { *aIsDomain = IsDomain(); return NS_OK; } |
michael@0 | 143 | NS_IMETHODIMP nsCookie::GetIsSecure(bool *aIsSecure) { *aIsSecure = IsSecure(); return NS_OK; } |
michael@0 | 144 | NS_IMETHODIMP nsCookie::GetIsHttpOnly(bool *aHttpOnly) { *aHttpOnly = IsHttpOnly(); return NS_OK; } |
michael@0 | 145 | NS_IMETHODIMP nsCookie::GetStatus(nsCookieStatus *aStatus) { *aStatus = 0; return NS_OK; } |
michael@0 | 146 | NS_IMETHODIMP nsCookie::GetPolicy(nsCookiePolicy *aPolicy) { *aPolicy = 0; return NS_OK; } |
michael@0 | 147 | NS_IMETHODIMP nsCookie::GetCreationTime(int64_t *aCreation){ *aCreation = CreationTime(); return NS_OK; } |
michael@0 | 148 | NS_IMETHODIMP nsCookie::GetLastAccessed(int64_t *aTime) { *aTime = LastAccessed(); return NS_OK; } |
michael@0 | 149 | |
michael@0 | 150 | // compatibility method, for use with the legacy nsICookie interface. |
michael@0 | 151 | // here, expires == 0 denotes a session cookie. |
michael@0 | 152 | NS_IMETHODIMP |
michael@0 | 153 | nsCookie::GetExpires(uint64_t *aExpires) |
michael@0 | 154 | { |
michael@0 | 155 | if (IsSession()) { |
michael@0 | 156 | *aExpires = 0; |
michael@0 | 157 | } else { |
michael@0 | 158 | *aExpires = Expiry() > 0 ? Expiry() : 1; |
michael@0 | 159 | } |
michael@0 | 160 | return NS_OK; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | NS_IMPL_ISUPPORTS(nsCookie, nsICookie2, nsICookie) |