summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/base/system.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/base/system.cpp')
-rw-r--r--utils/rbutilqt/base/system.cpp519
1 files changed, 519 insertions, 0 deletions
diff --git a/utils/rbutilqt/base/system.cpp b/utils/rbutilqt/base/system.cpp
new file mode 100644
index 0000000000..dafab971ec
--- /dev/null
+++ b/utils/rbutilqt/base/system.cpp
@@ -0,0 +1,519 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19
20#include "system.h"
21
22#include <QtCore>
23#include <QDebug>
24
25#include <cstdlib>
26#include <stdio.h>
27
28// Windows Includes
29#if defined(Q_OS_WIN32)
30#if defined(UNICODE)
31#define _UNICODE
32#endif
33#include <windows.h>
34#include <tchar.h>
35#include <lm.h>
36#include <windows.h>
37#include <setupapi.h>
38#endif
39
40// Linux and Mac includes
41#if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
42#include <sys/utsname.h>
43#include <unistd.h>
44#include <pwd.h>
45#endif
46
47// Linux includes
48#if defined(Q_OS_LINUX)
49#include <libusb-1.0/libusb.h>
50#include <mntent.h>
51#endif
52
53// Mac includes
54#if defined(Q_OS_MACX)
55#include <sys/param.h>
56#include <sys/ucred.h>
57#include <sys/mount.h>
58
59#include <CoreFoundation/CoreFoundation.h>
60#include <SystemConfiguration/SystemConfiguration.h>
61#include <CoreServices/CoreServices.h>
62#include <IOKit/IOKitLib.h>
63#include <IOKit/usb/IOUSBLib.h>
64#endif
65
66#include "utils.h"
67#include "rbsettings.h"
68#include "Logger.h"
69
70/** @brief detect permission of user (only Windows at moment).
71 * @return enum userlevel.
72 */
73#if defined(Q_OS_WIN32)
74enum System::userlevel System::userPermissions(void)
75{
76 LPUSER_INFO_1 buf = NULL;
77 wchar_t userbuf[UNLEN];
78 DWORD usersize = UNLEN;
79 BOOL status;
80 enum userlevel result = ERR;
81
82 status = GetUserNameW(userbuf, &usersize);
83 if(!status)
84 return ERR;
85
86 if(NetUserGetInfo(NULL, userbuf, (DWORD)1, (LPBYTE*)&buf) == NERR_Success) {
87 switch(buf->usri1_priv) {
88 case USER_PRIV_GUEST:
89 result = GUEST;
90 break;
91 case USER_PRIV_USER:
92 result = USER;
93 break;
94 case USER_PRIV_ADMIN:
95 result = ADMIN;
96 break;
97 default:
98 result = ERR;
99 break;
100 }
101 }
102 if(buf != NULL)
103 NetApiBufferFree(buf);
104
105 return result;
106}
107
108/** @brief detects user permissions (only Windows at moment).
109 * @return a user readable string with the permission.
110 */
111QString System::userPermissionsString(void)
112{
113 QString result;
114 int perm = userPermissions();
115 switch(perm) {
116 case GUEST:
117 result = tr("Guest");
118 break;
119 case ADMIN:
120 result = tr("Admin");
121 break;
122 case USER:
123 result = tr("User");
124 break;
125 default:
126 result = tr("Error");
127 break;
128 }
129 return result;
130}
131#endif
132
133
134/** @brief detects current Username.
135 * @return string with Username.
136 */
137QString System::userName(void)
138{
139#if defined(Q_OS_WIN32)
140 wchar_t userbuf[UNLEN];
141 DWORD usersize = UNLEN;
142
143 if(GetUserNameW(userbuf, &usersize) == 0)
144 return QString();
145
146 return QString::fromWCharArray(userbuf);
147#endif
148#if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
149 struct passwd *user;
150 user = getpwuid(geteuid());
151 return QString(user->pw_name);
152#endif
153}
154
155
156/** @brief detects the OS Version
157 * @return String with OS Version.
158 */
159QString System::osVersionString(void)
160{
161 QString result;
162#if defined(Q_OS_WIN32)
163 SYSTEM_INFO sysinfo;
164 OSVERSIONINFO osvi;
165 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
166 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
167 GetVersionEx(&osvi);
168 GetSystemInfo(&sysinfo);
169
170 result = QString("Windows version %1.%2, ").arg(osvi.dwMajorVersion).arg(osvi.dwMinorVersion);
171 if(osvi.szCSDVersion)
172 result += QString("build %1 (%2)").arg(osvi.dwBuildNumber)
173 .arg(QString::fromWCharArray(osvi.szCSDVersion));
174 else
175 result += QString("build %1").arg(osvi.dwBuildNumber);
176 result += QString("<br/>CPU: %1, %2 processor(s)").arg(sysinfo.dwProcessorType)
177 .arg(sysinfo.dwNumberOfProcessors);
178#endif
179#if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
180 struct utsname u;
181 int ret;
182 ret = uname(&u);
183
184#if defined(Q_OS_MACX)
185 SInt32 cores;
186 Gestalt(gestaltCountOfCPUs, &cores);
187#else
188 long cores = sysconf(_SC_NPROCESSORS_ONLN);
189#endif
190 if(ret != -1) {
191 result = QString("CPU: %1, %2 processor(s)").arg(u.machine).arg(cores);
192 result += QString("<br/>System: %2<br/>Release: %3<br/>Version: %4")
193 .arg(u.sysname).arg(u.release).arg(u.version);
194 }
195 else {
196 result = QString("(Error when retrieving system information)");
197 }
198#if defined(Q_OS_MACX)
199 SInt32 major;
200 SInt32 minor;
201 SInt32 bugfix;
202 Gestalt(gestaltSystemVersionMajor, &major);
203 Gestalt(gestaltSystemVersionMinor, &minor);
204 Gestalt(gestaltSystemVersionBugFix, &bugfix);
205
206 result += QString("<br/>OS X %1.%2.%3 ").arg(major).arg(minor).arg(bugfix);
207 // 1: 86k, 2: ppc, 10: i386
208 SInt32 arch;
209 Gestalt(gestaltSysArchitecture, &arch);
210 switch(arch) {
211 case 1:
212 result.append("(86k)");
213 break;
214 case 2:
215 result.append("(ppc)");
216 break;
217 case 10:
218 result.append("(x86)");
219 break;
220 default:
221 result.append("(unknown)");
222 break;
223 }
224#endif
225#endif
226 result += QString("<br/>Qt version %1").arg(qVersion());
227 return result;
228}
229
230QList<uint32_t> System::listUsbIds(void)
231{
232 return listUsbDevices().keys();
233}
234
235/** @brief detect devices based on usb pid / vid.
236 * @return list with usb VID / PID values.
237 */
238QMultiMap<uint32_t, QString> System::listUsbDevices(void)
239{
240 QMultiMap<uint32_t, QString> usbids;
241 // usb pid detection
242 LOG_INFO() << "Searching for USB devices";
243#if defined(Q_OS_LINUX)
244 libusb_device **devs;
245 if(libusb_init(nullptr) != 0) {
246 LOG_ERROR() << "Initializing libusb-1 failed.";
247 return usbids;
248 }
249
250 if(libusb_get_device_list(nullptr, &devs) < 1) {
251 LOG_ERROR() << "Error getting device list.";
252 return usbids;
253 }
254 libusb_device *dev;
255 int i = 0;
256 while((dev = devs[i++]) != nullptr) {
257 QString name;
258 unsigned char buf[256];
259 uint32_t id;
260 struct libusb_device_descriptor descriptor;
261 if(libusb_get_device_descriptor(dev, &descriptor) == 0) {
262 id = descriptor.idVendor << 16 | descriptor.idProduct;
263
264 libusb_device_handle *dh;
265 if(libusb_open(dev, &dh) == 0) {
266 libusb_get_string_descriptor_ascii(dh, descriptor.iManufacturer, buf, 256);
267 name += QString::fromLatin1((char*)buf) + " ";
268 libusb_get_string_descriptor_ascii(dh, descriptor.iProduct, buf, 256);
269 name += QString::fromLatin1((char*)buf);
270 libusb_close(dh);
271 }
272 if(name.isEmpty())
273 name = tr("(no description available)");
274 if(id) {
275 usbids.insert(id, name);
276 LOG_INFO("USB: 0x%08x, %s", id, name.toLocal8Bit().data());
277 }
278 }
279 }
280
281 libusb_free_device_list(devs, 1);
282 libusb_exit(nullptr);
283#endif
284
285#if defined(Q_OS_MACX)
286 kern_return_t result = KERN_FAILURE;
287 CFMutableDictionaryRef usb_matching_dictionary;
288 io_iterator_t usb_iterator = IO_OBJECT_NULL;
289 usb_matching_dictionary = IOServiceMatching(kIOUSBDeviceClassName);
290 result = IOServiceGetMatchingServices(kIOMasterPortDefault, usb_matching_dictionary,
291 &usb_iterator);
292 if(result) {
293 LOG_ERROR() << "USB: IOKit: Could not get matching services.";
294 return usbids;
295 }
296
297 io_object_t usbCurrentObj;
298 while((usbCurrentObj = IOIteratorNext(usb_iterator))) {
299 uint32_t id;
300 QString name;
301 /* get vendor ID */
302 CFTypeRef vidref = NULL;
303 int vid = 0;
304 vidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idVendor"),
305 kCFAllocatorDefault, 0);
306 CFNumberGetValue((CFNumberRef)vidref, kCFNumberIntType, &vid);
307 CFRelease(vidref);
308
309 /* get product ID */
310 CFTypeRef pidref = NULL;
311 int pid = 0;
312 pidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idProduct"),
313 kCFAllocatorDefault, 0);
314 CFNumberGetValue((CFNumberRef)pidref, kCFNumberIntType, &pid);
315 CFRelease(pidref);
316 id = vid << 16 | pid;
317
318 /* get product vendor */
319 char vendor_buf[256];
320 CFIndex vendor_buflen = 256;
321 CFTypeRef vendor_name_ref = NULL;
322
323 vendor_name_ref = IORegistryEntrySearchCFProperty(usbCurrentObj,
324 kIOServicePlane, CFSTR("USB Vendor Name"),
325 kCFAllocatorDefault, 0);
326 if(vendor_name_ref != NULL) {
327 CFStringGetCString((CFStringRef)vendor_name_ref, vendor_buf, vendor_buflen,
328 kCFStringEncodingUTF8);
329 name += QString::fromUtf8(vendor_buf) + " ";
330 CFRelease(vendor_name_ref);
331 }
332 else {
333 name += QObject::tr("(unknown vendor name) ");
334 }
335
336 /* get product name */
337 char product_buf[256];
338 CFIndex product_buflen = 256;
339 CFTypeRef product_name_ref = NULL;
340
341 product_name_ref = IORegistryEntrySearchCFProperty(usbCurrentObj,
342 kIOServicePlane, CFSTR("USB Product Name"),
343 kCFAllocatorDefault, 0);
344 if(product_name_ref != NULL) {
345 CFStringGetCString((CFStringRef)product_name_ref, product_buf, product_buflen,
346 kCFStringEncodingUTF8);
347 name += QString::fromUtf8(product_buf);
348 CFRelease(product_name_ref);
349 }
350 else {
351 name += QObject::tr("(unknown product name)");
352 }
353
354 if(id) {
355 usbids.insertMulti(id, name);
356 LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16) << name;
357 }
358
359 }
360 IOObjectRelease(usb_iterator);
361#endif
362
363#if defined(Q_OS_WIN32)
364 HDEVINFO deviceInfo;
365 SP_DEVINFO_DATA infoData;
366 DWORD i;
367
368 // Iterate over all devices
369 // by doing it this way it's unneccessary to use GUIDs which might be not
370 // present in current MinGW. It also seemed to be more reliably than using
371 // a GUID.
372 // See KB259695 for an example.
373 deviceInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
374
375 infoData.cbSize = sizeof(SP_DEVINFO_DATA);
376
377 for(i = 0; SetupDiEnumDeviceInfo(deviceInfo, i, &infoData); i++) {
378 DWORD data;
379 LPTSTR buffer = NULL;
380 DWORD buffersize = 0;
381 QString description;
382
383 // get device descriptor first
384 // for some reason not doing so results in bad things (tm)
385 while(!SetupDiGetDeviceRegistryProperty(deviceInfo, &infoData,
386 SPDRP_DEVICEDESC, &data, (PBYTE)buffer, buffersize, &buffersize)) {
387 if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
388 if(buffer) free(buffer);
389 // double buffer size to avoid problems as per KB888609
390 buffer = (LPTSTR)malloc(buffersize * 2);
391 }
392 else {
393 break;
394 }
395 }
396 if(!buffer) {
397 LOG_WARNING() << "Got no device description"
398 << "(SetupDiGetDeviceRegistryProperty), item" << i;
399 continue;
400 }
401 description = QString::fromWCharArray(buffer);
402
403 // now get the hardware id, which contains PID and VID.
404 while(!SetupDiGetDeviceRegistryProperty(deviceInfo, &infoData,
405 SPDRP_HARDWAREID, &data, (PBYTE)buffer, buffersize, &buffersize)) {
406 if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
407 if(buffer) free(buffer);
408 // double buffer size to avoid problems as per KB888609
409 buffer = (LPTSTR)malloc(buffersize * 2);
410 }
411 else {
412 break;
413 }
414 }
415
416 if(buffer) {
417 // convert buffer text to upper case to avoid depending on the case of
418 // the keys (W7 uses different casing than XP at least), in addition
419 // XP may use "Vid_" and "Pid_".
420 QString data = QString::fromWCharArray(buffer).toUpper();
421 QRegExp rex("USB\\\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4}).*");
422 if(rex.indexIn(data) >= 0) {
423 uint32_t id;
424 id = rex.cap(1).toUInt(0, 16) << 16 | rex.cap(2).toUInt(0, 16);
425 usbids.insert(id, description);
426 LOG_INFO() << "USB:" << QString("0x%1").arg(id, 8, 16);
427 }
428 free(buffer);
429 }
430 }
431 SetupDiDestroyDeviceInfoList(deviceInfo);
432
433#endif
434 return usbids;
435}
436
437
438/** @brief detects current system proxy
439 * @return QUrl with proxy or empty
440 */
441QUrl System::systemProxy(void)
442{
443#if defined(Q_OS_LINUX)
444 return QUrl(getenv("http_proxy"));
445#elif defined(Q_OS_WIN32)
446 HKEY hk;
447 wchar_t proxyval[80];
448 DWORD buflen = 80;
449 long ret;
450 DWORD enable;
451 DWORD enalen = sizeof(DWORD);
452
453 ret = RegOpenKeyEx(HKEY_CURRENT_USER,
454 _TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
455 0, KEY_QUERY_VALUE, &hk);
456 if(ret != ERROR_SUCCESS) return QUrl("");
457
458 ret = RegQueryValueEx(hk, _TEXT("ProxyServer"), NULL, NULL, (LPBYTE)proxyval, &buflen);
459 if(ret != ERROR_SUCCESS) return QUrl("");
460
461 ret = RegQueryValueEx(hk, _TEXT("ProxyEnable"), NULL, NULL, (LPBYTE)&enable, &enalen);
462 if(ret != ERROR_SUCCESS) return QUrl("");
463
464 RegCloseKey(hk);
465
466 //LOG_INFO() << QString::fromWCharArray(proxyval) << QString("%1").arg(enable);
467 if(enable != 0)
468 return QUrl("http://" + QString::fromWCharArray(proxyval));
469 else
470 return QUrl("");
471#elif defined(Q_OS_MACX)
472
473 CFDictionaryRef dictref;
474 CFStringRef stringref;
475 CFNumberRef numberref;
476 int enable = 0;
477 int port = 0;
478 unsigned int bufsize = 0;
479 char *buf;
480 QUrl proxy;
481
482 dictref = SCDynamicStoreCopyProxies(NULL);
483 if(dictref == NULL)
484 return proxy;
485 numberref = (CFNumberRef)CFDictionaryGetValue(dictref, kSCPropNetProxiesHTTPEnable);
486 if(numberref != NULL)
487 CFNumberGetValue(numberref, kCFNumberIntType, &enable);
488 if(enable == 1) {
489 // get proxy string
490 stringref = (CFStringRef)CFDictionaryGetValue(dictref, kSCPropNetProxiesHTTPProxy);
491 if(stringref != NULL) {
492 // get number of characters. CFStringGetLength uses UTF-16 code pairs
493 bufsize = CFStringGetLength(stringref) * 2 + 1;
494 buf = (char*)malloc(sizeof(char) * bufsize);
495 if(buf == NULL) {
496 LOG_ERROR() << "can't allocate memory for proxy string!";
497 CFRelease(dictref);
498 return QUrl("");
499 }
500 CFStringGetCString(stringref, buf, bufsize, kCFStringEncodingUTF16);
501 numberref = (CFNumberRef)CFDictionaryGetValue(dictref, kSCPropNetProxiesHTTPPort);
502 if(numberref != NULL)
503 CFNumberGetValue(numberref, kCFNumberIntType, &port);
504 proxy.setScheme("http");
505 proxy.setHost(QString::fromUtf16((unsigned short*)buf));
506 proxy.setPort(port);
507
508 free(buf);
509 }
510 }
511 CFRelease(dictref);
512
513 return proxy;
514#else
515 return QUrl("");
516#endif
517}
518
519