Skip to content

Commit f4d7db8

Browse files
committed
Build-To-Use: 3.3.0-75
CBL-6952: Revise Database name validation in C4Address.fromURL() (#2283) CBL-7010: Update min versions of iOS (to 15.0), macOS (to 13.0) (#2281) CBL-6971: Cannot access the kCBLCertAttrKeyLocality value from the certificate's attributes (#2282) CBL-6285: Explain for predictive query no longer names an index (#2193)
2 parents de7e81e + 84af54e commit f4d7db8

File tree

15 files changed

+82
-41
lines changed

15 files changed

+82
-41
lines changed

C/include/c4CertificateTypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ typedef C4Slice C4CertNameAttributeID;
4949
# define kC4Cert_Organization C4STR("O") // e.g. "Example Corp."
5050
# define kC4Cert_OrganizationUnit C4STR("OU") // e.g. "Marketing"
5151
# define kC4Cert_PostalAddress C4STR("postalAddress") // e.g. "123 Example Blvd #2A"
52-
# define kC4Cert_Locality C4STR("locality") // e.g. "Boston"
52+
# define kC4Cert_Locality C4STR("L") // e.g. "Boston"
5353
# define kC4Cert_PostalCode C4STR("postalCode") // e.g. "02134"
5454
# define kC4Cert_StateOrProvince C4STR("ST") // e.g. "Massachusetts" (or "Quebec", ...)
5555
# define kC4Cert_Country C4STR("C") // e.g. "us" (2-letter ISO country code)

C/tests/c4CertificateTest.cc

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,43 @@ TEST_CASE("C4Certificate smoke test", "[Certs][C]") {
3434
}
3535
}
3636

37+
TEST_CASE("C4Certificate Subject Name", "[Certs][C]") {
38+
C4CertNameComponent nameComponents[] = {{kC4Cert_CommonName, "CommonName"_sl},
39+
{kC4Cert_Pseudonym, "Pseudonym"_sl},
40+
{kC4Cert_GivenName, "GivenName"_sl},
41+
{kC4Cert_Surname, "Surname"_sl},
42+
{kC4Cert_Organization, "Organiztion"_sl},
43+
{kC4Cert_OrganizationUnit, "OrganizationUnit"_sl},
44+
{kC4Cert_PostalAddress, "PostalAddress"_sl},
45+
{kC4Cert_Locality, "Locality"_sl},
46+
{kC4Cert_PostalCode, "PostalCode"_sl},
47+
{kC4Cert_StateOrProvince, "StateOrProvince"_sl},
48+
{kC4Cert_Country, "Country"_sl},
49+
{kC4Cert_EmailAddress, "EmailAddress"_sl},
50+
{kC4Cert_Hostname, "Hostname"_sl},
51+
{kC4Cert_URL, "URL"_sl},
52+
{kC4Cert_IPAddress, "IPAddress"_sl},
53+
{kC4Cert_RegisteredID, "RegisteredID"_sl}};
54+
size_t compCount = std::size(nameComponents);
3755

38-
#endif
56+
c4::ref<C4Cert> cert = [&]() -> C4Cert* {
57+
c4::ref<C4KeyPair> key = c4keypair_generate(kC4RSA, 2048, false, nullptr);
58+
REQUIRE(key);
59+
60+
c4::ref<C4Cert> csr = c4cert_createRequest(nameComponents, compCount, kC4CertUsage_TLSClient, key, nullptr);
61+
REQUIRE(csr);
62+
63+
C4CertIssuerParameters issuerParams = kDefaultCertIssuerParameters;
64+
issuerParams.validityInSeconds = 3600;
65+
issuerParams.isCA = false;
66+
return c4cert_signRequest(csr, &issuerParams, key, nullptr, nullptr);
67+
}();
68+
REQUIRE(cert);
69+
70+
for ( size_t i = 0; i < compCount; ++i ) {
71+
alloc_slice nameComp = c4cert_subjectNameComponent(cert, nameComponents[i].attributeID);
72+
CHECK(nameComp == nameComponents[i].value);
73+
}
74+
}
75+
76+
#endif //#ifdef COUCHBASE_ENTERPRISE

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ SQLite3_UnicodeSN - The snowball tokenizer library for SQLite
2222
This project is built for the following platforms at Couchbase:
2323
- Windows 10
2424
- UWP
25-
- macOS 12.0
25+
- macOS 13.0
2626
- CentOS 7 (gcc 7.x+)
2727
- Android API 22+
2828
@@ -40,7 +40,7 @@ Platform logic is largely separated into the cmake/platform_*.cmake files. Plat
4040
cmake_minimum_required (VERSION 3.21.0)
4141

4242
# Mac/apple setup -- must appear before the first "project()" line"
43-
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0")
43+
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0")
4444
if(NOT DEFINED CMAKE_OSX_SYSROOT)
4545
# Tells Mac builds to use the current SDK's headers & libs, not what's in the OS.
4646
set(CMAKE_OSX_SYSROOT macosx)

LiteCore/Query/Translator/IndexedNodes.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ namespace litecore::qt {
225225
expr.append(args[1]);
226226
string id = expressionIdentifier(expr);
227227

228-
if ( ctx.delegate.hasPredictiveIndex(id) ) {
228+
if ( ctx.delegate.hasPredictiveIndex(id, ctx) ) {
229229
return new (ctx) PredictionNode(args, ctx, id);
230230
} else {
231231
return FunctionNode::parse(kPredictionFnName, args, ctx);

LiteCore/Query/Translator/Node.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace litecore::qt {
2929
class SelectNode;
3030
class SourceNode;
3131
class SQLWriter;
32+
struct ParseContext;
3233
template <class T>
3334
class List;
3435

@@ -74,8 +75,10 @@ namespace litecore::qt {
7475

7576
struct ParseDelegate {
7677
#ifdef COUCHBASE_ENTERPRISE
77-
std::function<bool(string_view id)> hasPredictiveIndex;
78+
std::function<bool(string_view id, ParseContext& ctx)> hasPredictiveIndex;
7879
#endif
80+
std::function<void(SourceNode*, ParseContext&)> assignTableNameToMainSource;
81+
std::function<string_view()> translatorDefaultCollection;
7982
};
8083

8184
/** State used during parsing, passed down through the recursive descent. */

LiteCore/Query/Translator/QueryTranslator.cc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,18 @@ namespace litecore {
3939
RootContext QueryTranslator::makeRootContext() const {
4040
RootContext root;
4141
#ifdef COUCHBASE_ENTERPRISE
42-
root.hasPredictiveIndex = [&](string_view id) -> bool {
43-
string indexTable = _delegate.predictiveTableName(_defaultTableName, string(id));
42+
root.hasPredictiveIndex = [&](string_view id, ParseContext& ctx) -> bool {
43+
string tableName = ctx.from ? string(ctx.from->tableName()) : _defaultTableName;
44+
string indexTable = _delegate.predictiveTableName(tableName, string(id));
4445
return _delegate.tableExists(indexTable);
4546
};
4647
#endif
48+
QueryTranslator* mutableThis = const_cast<QueryTranslator*>(this);
49+
root.assignTableNameToMainSource = [mutableThis](SourceNode* source, ParseContext& ctx) -> void {
50+
Assert(source->isCollection());
51+
mutableThis->assignTableNameToSource(source, ctx);
52+
};
53+
root.translatorDefaultCollection = [&]() -> string_view { return _defaultCollectionName; };
4754
return root;
4855
}
4956

LiteCore/Query/Translator/SelectNodes.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ namespace litecore::qt {
129129
bool explicitCollection = false;
130130
if ( slice collection = optionalString(getCaseInsensitive(dict, "COLLECTION"), "COLLECTION") ) {
131131
explicitCollection = true;
132-
if ( collection == "_" || collection == kDefaultCollectionName ) {
133-
_collection = "";
132+
if ( collection == "_" ) {
133+
_collection = kDefaultCollectionName;
134134
_columnName = collection;
135135
} else {
136136
_collection = collection;
@@ -432,7 +432,9 @@ namespace litecore::qt {
432432
addIndexes(ctx);
433433

434434
for ( SourceNode* source : _sources ) {
435-
if ( !source->_usesDeleted && source->_collection.empty() && source->isCollection() ) {
435+
string_view coll{source->collection()};
436+
if ( coll.empty() ) coll = ctx.delegate.translatorDefaultCollection();
437+
if ( !source->_usesDeleted && coll == "_default" && source->isCollection() ) {
436438
// The default collection may contain deleted documents in its main table,
437439
// so if the query didn't ask for deleted docs, add a condition to the WHERE
438440
// or ON clause that only passes live docs:
@@ -481,6 +483,7 @@ namespace litecore::qt {
481483
isFrom = true;
482484
require(_sources.empty(), "multiple non-join FROM items");
483485
ctx.from = source;
486+
ctx.delegate.assignTableNameToMainSource(source, ctx);
484487
}
485488
ctx.sources.emplace_back(source);
486489
}

LiteCore/Query/Translator/SelectNodes.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ namespace litecore::qt {
113113
void disambiguateColumnName(ParseContext&);
114114
void writeASandON(SQLWriter& ctx) const;
115115

116-
void setUsesDeleted() { _usesDeleted = true; }
116+
void setUsesDeleted() {
117+
_usesDeleted = true; // It will turn kv_.xyz to all_.xyz
118+
_tableName = string_view{};
119+
}
117120

118121
private:
119122
string_view _scope; // Scope name, or empty for default

LiteCore/tests/PredictiveQueryTest.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,11 @@ N_WAY_TEST_CASE_METHOD(QueryTest, "Predictive Query compound indexed", "[Query][
206206
// Query numbers in descending order of square-ness:
207207
std::stringstream sstr;
208208
sstr << "{'WHAT': [['.num'], " << square << "],"
209+
<< " 'FROM': [{'COLLECTION': '" + collectionName + "'}],"
209210
<< " 'WHERE': ['AND', ['>=', " << square + ", 1], ['>=', " << even << ", 1]],"
210211
<< " 'ORDER_BY': [['DESC', ['.num']]] }";
211212

212-
Retained<Query> query{store->compileQuery(json5(sstr.str()))};
213+
Retained<Query> query{db->compileQuery(json5(sstr.str()))};
213214
string explanation = query->explain();
214215
Log("Explanation: %s", explanation.c_str());
215216

Replicator/ChangesFeed.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ namespace litecore::repl {
218218
bool ChangesFeed::shouldPushRev(RevToSend* rev, C4DocEnumerator* e) const {
219219
bool needRemoteRevID = _getForeignAncestors && !rev->remoteAncestorRevID && _isCheckpointValid;
220220
if ( needRemoteRevID || _options->pushFilter(_collectionIndex) ) {
221-
C4Error error;
221+
C4Error error{};
222222
Retained<C4Document> doc;
223223
try {
224224
if ( e ) doc = e->getDocument();

Replicator/c4Replicator.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ bool C4Replicator::isValidDatabaseName(slice dbName) noexcept {
139139
bool C4Address::isValidRemote(slice dbName, C4Error* outError) const noexcept {
140140
slice message;
141141
if ( !isValidReplicatorScheme(scheme) ) message = "Invalid replication URL scheme (use ws: or wss:)"_sl;
142-
else if ( !C4Replicator::isValidDatabaseName(dbName) )
143-
message = "Invalid or missing remote database name"_sl;
142+
else if ( dbName.empty() )
143+
message = "Missing remote database name"_sl;
144144
else if ( hostname.size == 0 || port == 0 )
145145
message = "Invalid replication URL (bad hostname or port)"_sl;
146146

@@ -286,7 +286,7 @@ bool C4Address::fromURL(slice url, C4Address* address, slice* dbName) {
286286

287287
address->path = slice(pathStart, str.buf);
288288
*dbName = str;
289-
return C4Replicator::isValidDatabaseName(str);
289+
return !str.empty();
290290
} else {
291291
address->path = slice(pathStart, str.end());
292292
return true;

Replicator/tests/ReplicatorAPITest.cc

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ TEST_CASE("URL Parsing", "[C][Replicator]") {
102102
REQUIRE(c4address_fromURL("wss://localhost/p/d/"_sl, &address, &dbName));
103103
REQUIRE(c4address_fromURL("wss://localhost//p//d/"_sl, &address, &dbName));
104104

105-
REQUIRE(!c4address_fromURL("ws://example.com/db@name"_sl, &address, &dbName));
105+
// We don't check the validity of the database name.
106+
REQUIRE(c4address_fromURL("ws://example.com/db@name"_sl, &address, &dbName));
106107
CHECK(dbName == "db@name"_sl);
107108

108109
// The following URLs should all be rejected:
@@ -121,7 +122,10 @@ TEST_CASE("URL Parsing", "[C][Replicator]") {
121122
CHECK(!c4address_fromURL("ws://localhost:/foo"_sl, &address, &dbName));
122123
CHECK(!c4address_fromURL("ws://localhost"_sl, &address, &dbName));
123124
CHECK(!c4address_fromURL("ws://localhost/"_sl, &address, &dbName));
124-
CHECK(!c4address_fromURL("ws://localhost/B^dn^m*"_sl, &address, &dbName));
125+
126+
// We don't check the validity of the database name.
127+
CHECK(c4address_fromURL("ws://localhost/B^dn^m*"_sl, &address, &dbName));
128+
CHECK(dbName == "B^dn^m*"_sl);
125129

126130
CHECK(!c4address_fromURL("ws://snej@example.com/db"_sl, &address, &dbName));
127131
CHECK(!c4address_fromURL("ws://snej@example.com:8080/db"_sl, &address, &dbName));
@@ -163,24 +167,6 @@ TEST_CASE_METHOD(ReplicatorAPITest, "API Invalid Scheme", "[C][Push][!throws]")
163167
CHECK(err.code == kC4NetErrInvalidURL);
164168
}
165169

166-
// Test missing or invalid database name:
167-
TEST_CASE_METHOD(ReplicatorAPITest, "API Invalid URLs", "[C][Push][!throws]") {
168-
ExpectingExceptions x;
169-
_sg.remoteDBName = ""_sl;
170-
C4Error err;
171-
CHECK(!c4repl_isValidRemote(_sg.address, _sg.remoteDBName, nullptr));
172-
REQUIRE(!startReplicator(kC4Disabled, kC4OneShot, &err));
173-
CHECK(err.domain == NetworkDomain);
174-
CHECK(err.code == kC4NetErrInvalidURL);
175-
176-
_sg.remoteDBName = "Invalid Name"_sl;
177-
err = {};
178-
CHECK(!c4repl_isValidRemote(_sg.address, _sg.remoteDBName, nullptr));
179-
REQUIRE(!startReplicator(kC4Disabled, kC4OneShot, &err));
180-
CHECK(err.domain == NetworkDomain);
181-
CHECK(err.code == kC4NetErrInvalidURL);
182-
}
183-
184170
// Test connection-refused error by connecting to a bogus port of localhost
185171
TEST_CASE_METHOD(ReplicatorAPITest, "API Connection Failure", "[C][Push]") {
186172
ExpectingExceptions x;

Replicator/tests/ReplicatorCollectionSGTest.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ TEST_CASE_METHOD(ReplicatorCollectionSGTest, "Sync with Single Collection SG", "
241241
std::vector<C4CollectionSpec> collectionSpecs{collectionCount};
242242

243243
bool continuous = false;
244-
C4Error expectedError;
244+
C4Error expectedError{};
245245

246246
SECTION("Named Collection") { collectionSpecs = {Roses}; }
247247

Xcode/xcconfigs/Project.xcconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ CLANG_STATIC_ANALYZER_MODE = shallow
2424
LITECORE_VERSION_STRING = 3.2.2
2525
LITECORE_BUILD_NUMBER = 0
2626

27-
IPHONEOS_DEPLOYMENT_TARGET = 12.0
28-
MACOSX_DEPLOYMENT_TARGET = 12.0
27+
IPHONEOS_DEPLOYMENT_TARGET = 15.0
28+
MACOSX_DEPLOYMENT_TARGET = 13.0
2929
TVOS_DEPLOYMENT_TARGET = 12.0
3030
ONLY_ACTIVE_ARCH = YES
3131
SKIP_INSTALL = YES

0 commit comments

Comments
 (0)