xref: /haiku/src/kits/package/RepositoryConfig.cpp (revision 9d8d114499db1f50f105c48c1a2172ea56e18bcd)
1 /*
2  * Copyright 2011-2020, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Oliver Tappe <zooey@hirschkaefer.de>
7  *		Andrew Lindesay <apl@lindesay.co.nz>
8  */
9 
10 
11 #include <package/RepositoryConfig.h>
12 
13 #include <stdlib.h>
14 
15 #include <new>
16 
17 #include <Directory.h>
18 #include <driver_settings.h>
19 #include <File.h>
20 #include <FindDirectory.h>
21 #include <Path.h>
22 
23 #include <DriverSettings.h>
24 
25 
26 #define STORAGE_VERSION 2
27 
28 #define KEY_BASE_URL_V1 "url"
29 #define KEY_IDENTIFIER_V1 "url"
30 
31 #define KEY_BASE_URL_V2 "baseurl"
32 #define KEY_IDENTIFIER_V2 "identifier"
33 #define KEY_IDENTIFIER_V2_ALT "url"
34 	// should not be used any more in favour of 'identifier'
35 
36 #define KEY_PRIORITY "priority"
37 #define KEY_CONFIG_VERSION "cfgversion"
38 
39 namespace BPackageKit {
40 
41 
42 // these are mappings of known legacy identifier URLs that are possibly
43 // still present in some installations.  These are in pairs; the first
44 // being the legacy URL and the next being the replacement.  This can
45 // be phased out over time.
46 
47 static const char* kLegacyUrlMappings[] = {
48 	"https://eu.hpkg.haiku-os.org/haikuports/master/x86_gcc2/current",
49 	"https://hpkg.haiku-os.org/haikuports/master/x86_gcc2/current",
50 	"https://eu.hpkg.haiku-os.org/haikuports/master/x86_64/current",
51 	"https://hpkg.haiku-os.org/haikuports/master/x86_64/current",
52 	NULL,
53 	NULL
54 };
55 
56 
BRepositoryConfig()57 BRepositoryConfig::BRepositoryConfig()
58 	:
59 	fInitStatus(B_NO_INIT),
60 	fPriority(kUnsetPriority),
61 	fIsUserSpecific(false)
62 {
63 }
64 
65 
BRepositoryConfig(const BEntry & entry)66 BRepositoryConfig::BRepositoryConfig(const BEntry& entry)
67 {
68 	SetTo(entry);
69 }
70 
71 
BRepositoryConfig(const BString & name,const BString & baseURL,uint8 priority)72 BRepositoryConfig::BRepositoryConfig(const BString& name,
73 	const BString& baseURL, uint8 priority)
74 	:
75 	fInitStatus(B_OK),
76 	fName(name),
77 	fBaseURL(baseURL),
78 	fPriority(priority),
79 	fIsUserSpecific(false)
80 {
81 }
82 
83 
~BRepositoryConfig()84 BRepositoryConfig::~BRepositoryConfig()
85 {
86 }
87 
88 
89 status_t
Store(const BEntry & entry) const90 BRepositoryConfig::Store(const BEntry& entry) const
91 {
92 	BFile file(&entry, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
93 	status_t result = file.InitCheck();
94 	if (result != B_OK)
95 		return result;
96 
97 	BString configString;
98 	configString << KEY_CONFIG_VERSION << "=" << STORAGE_VERSION << "\n";
99 	configString << "\n";
100 	configString << "# the url where the repository data can be "
101 		"accessed.\n";
102 	configString << KEY_BASE_URL_V2 << "=" << fBaseURL << "\n";
103 	configString << "\n";
104 
105 	configString << "# an identifier for the repository that is "
106 		"consistent across mirrors\n";
107 	if (fIdentifier.IsEmpty())
108 		configString << "# " << KEY_IDENTIFIER_V2 << "=???\n";
109 	else
110 		configString << KEY_IDENTIFIER_V2 << "=" << fIdentifier << "\n";
111 	configString << "\n";
112 
113 	configString << "# a deprecated copy of the ["
114 		<< KEY_IDENTIFIER_V2 << "] key above for older os versions\n";
115 	if (fIdentifier.IsEmpty())
116 		configString << "# " << KEY_IDENTIFIER_V2_ALT << "=???\n";
117 	else
118 		configString << KEY_IDENTIFIER_V2_ALT << "=" << fIdentifier << "\n";
119 	configString << "\n";
120 
121 	configString << KEY_PRIORITY << "=" << fPriority << "\n";
122 
123 	int32 size = configString.Length();
124 	if ((result = file.Write(configString.String(), size)) < size)
125 		return (result >= 0) ? B_ERROR : result;
126 
127 	return B_OK;
128 }
129 
130 
131 status_t
InitCheck() const132 BRepositoryConfig::InitCheck() const
133 {
134 	return fInitStatus;
135 }
136 
137 
138 static const char*
repository_config_swap_legacy_identifier_v1(const char * identifier)139 repository_config_swap_legacy_identifier_v1(const char* identifier)
140 {
141 	for (int32 i = 0; kLegacyUrlMappings[i] != NULL; i += 2) {
142 		if (strcmp(identifier, kLegacyUrlMappings[i]) == 0)
143 			return kLegacyUrlMappings[i + 1];
144 	}
145 	return identifier;
146 }
147 
148 
149 status_t
SetTo(const BEntry & entry)150 BRepositoryConfig::SetTo(const BEntry& entry)
151 {
152 	fEntry = entry;
153 	fInitStatus = B_NO_INIT;
154 
155 	entry_ref ref;
156 	status_t result = entry.GetRef(&ref);
157 	if (result != B_OK)
158 		return result;
159 
160 	BDriverSettings driverSettings;
161 	result = driverSettings.Load(ref);
162 	if (result != B_OK)
163 		return result;
164 
165 	const char* version = driverSettings.GetParameterValue(KEY_CONFIG_VERSION);
166 	int versionNumber = version == NULL ? 1 : atoi(version);
167 	const char *baseUrlKey;
168 	const char *identifierKeys[3] = { NULL, NULL, NULL };
169 
170 	switch (versionNumber) {
171 		case 1:
172 			baseUrlKey = KEY_BASE_URL_V1;
173 			identifierKeys[0] = KEY_IDENTIFIER_V1;
174 			break;
175 		case 2:
176 			baseUrlKey = KEY_BASE_URL_V2;
177 			identifierKeys[0] = KEY_IDENTIFIER_V2;
178 			identifierKeys[1] = KEY_IDENTIFIER_V2_ALT;
179 			break;
180 		default:
181 			return B_BAD_DATA;
182 	}
183 
184 	const char* baseUrl = driverSettings.GetParameterValue(baseUrlKey);
185 	const char* priorityString = driverSettings.GetParameterValue(KEY_PRIORITY);
186 	const char* identifier = NULL;
187 
188 	for (int32 i = 0; identifier == NULL && identifierKeys[i] != NULL; i++)
189 		identifier = driverSettings.GetParameterValue(identifierKeys[i]);
190 
191 	if (baseUrl == NULL || *baseUrl == '\0')
192 		return B_BAD_DATA;
193 	if (identifier == NULL || *identifier == '\0')
194 		return B_BAD_DATA;
195 
196 	if (versionNumber == 1)
197 		identifier = repository_config_swap_legacy_identifier_v1(identifier);
198 
199 	fName = entry.Name();
200 	fBaseURL = baseUrl;
201 	fPriority = priorityString == NULL
202 		? kUnsetPriority : atoi(priorityString);
203 	fIdentifier = identifier;
204 
205 	BPath userSettingsPath;
206 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &userSettingsPath) == B_OK) {
207 		BDirectory userSettingsDir(userSettingsPath.Path());
208 		fIsUserSpecific = userSettingsDir.Contains(&entry);
209 	} else
210 		fIsUserSpecific = false;
211 
212 	fInitStatus = B_OK;
213 
214 	return B_OK;
215 }
216 
217 
218 const BString&
Name() const219 BRepositoryConfig::Name() const
220 {
221 	return fName;
222 }
223 
224 
225 const BString&
BaseURL() const226 BRepositoryConfig::BaseURL() const
227 {
228 	return fBaseURL;
229 }
230 
231 
232 const BString&
Identifier() const233 BRepositoryConfig::Identifier() const
234 {
235 	return fIdentifier;
236 }
237 
238 
239 uint8
Priority() const240 BRepositoryConfig::Priority() const
241 {
242 	return fPriority;
243 }
244 
245 
246 bool
IsUserSpecific() const247 BRepositoryConfig::IsUserSpecific() const
248 {
249 	return fIsUserSpecific;
250 }
251 
252 
253 const BEntry&
Entry() const254 BRepositoryConfig::Entry() const
255 {
256 	return fEntry;
257 }
258 
259 
260 BString
PackagesURL() const261 BRepositoryConfig::PackagesURL() const
262 {
263 	if (fBaseURL.IsEmpty())
264 		return BString();
265 	return BString().SetToFormat("%s/packages", fBaseURL.String());
266 }
267 
268 
269 void
SetName(const BString & name)270 BRepositoryConfig::SetName(const BString& name)
271 {
272 	fName = name;
273 }
274 
275 
276 void
SetBaseURL(const BString & baseURL)277 BRepositoryConfig::SetBaseURL(const BString& baseURL)
278 {
279 	fBaseURL = baseURL;
280 }
281 
282 
283 void
SetIdentifier(const BString & identifier)284 BRepositoryConfig::SetIdentifier(const BString& identifier)
285 {
286 	fIdentifier = identifier;
287 }
288 
289 
290 void
SetPriority(uint8 priority)291 BRepositoryConfig::SetPriority(uint8 priority)
292 {
293 	fPriority = priority;
294 }
295 
296 
297 void
SetIsUserSpecific(bool isUserSpecific)298 BRepositoryConfig::SetIsUserSpecific(bool isUserSpecific)
299 {
300 	fIsUserSpecific = isUserSpecific;
301 }
302 
303 
304 }	// namespace BPackageKit
305