@@ -122,54 +122,82 @@ + (NSString *) decodePath:(NSString *)pathString {
122
122
return [NSString stringWithFormat: @" /%@ " , [decodedPieces componentsJoinedByString: @" /" ]];
123
123
}
124
124
125
- + (FParsedUrl *) parseUrl : (NSString *)url {
126
- NSString * original = url;
127
- // NSURL* n = [[NSURL alloc] initWithString:url]
125
+ + (NSString *) extractPathFromUrlString : (NSString *)url {
126
+ NSString * path = url;
128
127
129
- NSString * host;
130
- NSString * namespace;
131
- bool secure;
128
+ NSRange schemeIndex = [path rangeOfString: @" //" ];
129
+ if (schemeIndex.location != NSNotFound ) {
130
+ path = [path substringFromIndex: schemeIndex.location + 2 ];
131
+ }
132
132
133
- NSString * scheme = nil ;
134
- FPath* path = nil ;
135
- NSRange colonIndex = [url rangeOfString: @" //" ];
136
- if (colonIndex.location != NSNotFound ) {
137
- scheme = [url substringToIndex: colonIndex.location - 1 ];
138
- url = [url substringFromIndex: colonIndex.location + 2 ];
133
+ NSUInteger pathIndex = [path rangeOfString: @" /" ].location ;
134
+ if (pathIndex != NSNotFound ) {
135
+ path = [path substringFromIndex: pathIndex + 1 ];
136
+ } else {
137
+ path = @" " ;
139
138
}
140
- NSInteger slashIndex = [url rangeOfString: @" /" ].location ;
141
- if (slashIndex == NSNotFound ) {
142
- slashIndex = url.length ;
139
+
140
+ NSUInteger queryParamIndex = [path rangeOfString: @" ?" ].location ;
141
+ if (queryParamIndex != NSNotFound ) {
142
+ path = [path substringToIndex: queryParamIndex];
143
143
}
144
144
145
- host = [[url substringToIndex: slashIndex] lowercaseString ];
146
- if (slashIndex >= url.length ) {
147
- url = @" " ;
148
- } else {
149
- url = [url substringFromIndex: slashIndex + 1 ];
145
+ return path;
146
+ }
147
+
148
+ + (FParsedUrl *) parseUrl : (NSString *)url {
149
+ // For backwards compatibility, support URLs without schemes on iOS.
150
+ if (![url containsString: @" ://" ]) {
151
+ url = [@" http://" stringByAppendingString: url];
152
+ }
153
+
154
+ NSString * originalPathString = [self extractPathFromUrlString: url];
155
+
156
+ // Sanitize the database URL by removing the path component, which may contain invalid URL characters.
157
+ NSString * sanitizedUrlWithoutPath = [url stringByReplacingOccurrencesOfString: originalPathString withString: @" " ];
158
+ NSURLComponents *urlComponents = [NSURLComponents componentsWithString: sanitizedUrlWithoutPath];
159
+ if (!urlComponents) {
160
+ [NSException raise :@" Failed to parse database URL" format: @" Failed to parse database URL: %@ " , url];
150
161
}
151
162
152
- NSArray *parts = [host componentsSeparatedByString: @" ." ];
163
+ NSString * host = [urlComponents.host lowercaseString ];
164
+ NSString * namespace;
165
+ bool secure;
166
+
167
+ if (urlComponents.port != nil ) {
168
+ secure = [urlComponents.scheme isEqualToString: @" https" ];
169
+ host = [host stringByAppendingFormat: @" :%@ " , urlComponents.port];
170
+ } else if ( [urlComponents.host isEqualToString: @" localhost" ]) {
171
+ secure = NO ;
172
+ } else {
173
+ secure = YES ;
174
+ };
175
+
176
+ NSArray *parts = [urlComponents.host componentsSeparatedByString: @" ." ];
153
177
if ([parts count ] == 3 ) {
154
- NSInteger colonIndex = [[parts objectAtIndex: 2 ] rangeOfString: @" :" ].location ;
155
- if (colonIndex != NSNotFound ) {
156
- // we have a port, use the provided scheme
157
- secure = [scheme isEqualToString: @" https" ];
158
- } else {
159
- secure = YES ;
178
+ namespace = [parts[0 ] lowercaseString ];
179
+ } else {
180
+ // Attempt to extract namespace from "ns" query param.
181
+ NSArray *queryItems = urlComponents.queryItems ;
182
+ NSMutableArray *someIDs = [NSMutableArray new ];
183
+ for (NSURLQueryItem *item in queryItems) {
184
+ if ([item.name isEqualToString: @" ns" ]) {
185
+ namespace = item.value ;
186
+ break ;
187
+ }
160
188
}
161
189
162
- namespace = [[parts objectAtIndex: 0 ] lowercaseString ];
163
- NSString * pathString = [self decodePath: [NSString stringWithFormat: @" /%@ " , url]];
164
- path = [[FPath alloc ] initWith: pathString];
165
- }
166
- else {
167
- [NSException raise :@" No Firebase database specified." format: @" No Firebase database found for input: %@ " , url];
190
+ if (!namespace) {
191
+ namespace = [parts[0 ] lowercaseString ];
192
+ }
168
193
}
169
194
195
+
196
+ NSString * pathString = [self decodePath: [NSString stringWithFormat: @" /%@ " , originalPathString]];
197
+ FPath * path = [[FPath alloc ] initWith: pathString];
170
198
FRepoInfo* repoInfo = [[FRepoInfo alloc ] initWithHost: host isSecure: secure withNamespace: namespace];
171
199
172
- FFLog (@" I-RDB095002" , @" ---> Parsed (%@ ) to: (%@ ,%@ ); ns=(%@ ); path=(%@ )" , original , [repoInfo description ], [repoInfo connectionURL ], repoInfo.namespace , [path description ]);
200
+ FFLog (@" I-RDB095002" , @" ---> Parsed (%@ ) to: (%@ ,%@ ); ns=(%@ ); path=(%@ )" , url , [repoInfo description ], [repoInfo connectionURL ], repoInfo.namespace , [path description ]);
173
201
174
202
FParsedUrl* parsedUrl = [[FParsedUrl alloc ] init ];
175
203
parsedUrl.repoInfo = repoInfo;
0 commit comments