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