ukui-biometric-auth/0000775000175000017500000000000015167732644013406 5ustar fengfengukui-biometric-auth/bioauth-bin/0000775000175000017500000000000015167732644015607 5ustar fengfengukui-biometric-auth/bioauth-bin/src/0000775000175000017500000000000015167732644016376 5ustar fengfengukui-biometric-auth/bioauth-bin/src/keywatcher.cpp0000664000175000017500000000411015167732630021237 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "keywatcher.h" #include KeyWatcher::KeyWatcher(QObject *parent) : QThread(parent) { } void KeyWatcher::run() { // 修改终端属性,ä¿�è¯�按键被立å�³æŽ¥æ”¶ struct termios current; tcgetattr(0, &save); current = save; current.c_lflag &= ~ICANON; current.c_lflag &= ~ECHO; current.c_cc[VMIN] = 1; current.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, ¤t); bool isInputEnd = false; while(!isInterruptionRequested()){ fd_set readfds; FD_ZERO(&readfds); FD_SET(0, &readfds); char ch; switch(select(32, &readfds, NULL, NULL, NULL)){ case 0: // printf("select time out\n"); break; case -1: // printf("select error\n"); break; default: // 'q' | 'Q' or Esc if((ch = getchar()) == 'q' || ch == 'Q' || ch == 27 || ch == EOF){ tcsetattr(0, TCSANOW, &save); emit exit(); if (ch == EOF) { isInputEnd = true; break; } } } if (isInputEnd) { break; } } tcsetattr(0, TCSANOW, &save); // æ�¢å¤�原æ�¥çš„终端属性,以å…�干扰shall和之å�Žçš„程åº�è¿�行 } void KeyWatcher::stop() { tcsetattr(0, TCSANOW, &save); requestInterruption(); terminate(); wait(); } ukui-biometric-auth/bioauth-bin/src/main.cpp0000664000175000017500000003144615167732644020036 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ //#include "mainwindow.h" #include #include #include #include #include #include #include #include "generic.h" #include "keywatcher.h" #include "bioauth.h" #include "biodevices.h" #define START_COLOR "\033[1;31m" #define RESULT_COLOR "\033[1;31m" #define PROMPT_COLOR "\033[33m" #define NOTIFY_COLOR //"\033[37m" #define QUESTION_COLOR //"\033[1;37m" #define RESET_COLOR "\033[0m" bool enableDebug; QString logPrefix; BioAuth bioAuth; enum MsgType { START, PROMPT, NOTIFY, QUESTION, RESULT }; enum _Option { OPTION_TRY_AGAIN, OPTION_SELECT_DEVICE, OPTION_CANCEL, OPTION_UNDEFINED }; typedef enum _Option Option; static QString lastMessage; void showMessage(const QString &message, int type) { // filter out the same message if(message == lastMessage) return; lastMessage = message; char *text = message.toLocal8Bit().data(); switch(type) { case START: fprintf(stdout, START_COLOR "=== %s ===\n", text); break; case PROMPT: fprintf(stdout, PROMPT_COLOR "%s\n", text); break; case NOTIFY: fprintf(stdout, NOTIFY_COLOR "%s\n", text); break; case QUESTION: fprintf(stdout, QUESTION_COLOR "%s", text); break; case RESULT: fprintf(stdout, RESULT_COLOR "=== %s ===\n", text); break; default: fprintf(stdout, "%s\n", text); break; } fprintf(stdout, RESET_COLOR); } static bool isQuickInput() { fd_set readfds; FD_ZERO(&readfds); FD_SET(0, &readfds); // stdin struct timeval timeout = {0, 10*1000}; switch (select(32, &readfds, NULL, NULL, &timeout)) { case 0: // time out break; case -1: // error break; default: return true; } return false; } QString inputPinCode() { struct termios current; struct termios save; tcgetattr(0, &save); current = save; // current.c_lflag &= ~ICANON; current.c_lflag &= ~ECHO; current.c_cc[VMIN] = 0; current.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, ¤t); QString password = ""; showMessage(QObject::tr("Enter the ukey password"), QUESTION); char line[1024] = {0}; fgets(line, sizeof(line), stdin); //scanf("%s",&line); showMessage("\n", QUESTION); line[1023] = '\0'; if(line[strnlen(line,1024) - 1] == '\n') line[strnlen(line,1024) - 1] = '\0'; QString str(line); tcsetattr(0, TCSANOW, &save); // æ�¢å¤�原æ�¥çš„终端属性,以å…�干扰shall和之å�Žçš„程åº�è¿�行 return line; } Option showOption(bool showSelectDevices) { QStringList optionList; QString message; optionList << QObject::tr("Try it again"); if(showSelectDevices) optionList << QObject::tr("Use other Devices"); optionList << QObject::tr("Cancel"); for(int i = 0; i < optionList.size(); i++){ message = QString(" %1. %2\n") .arg(QString::number(i+1)) .arg(optionList.at(i)); showMessage(message, QUESTION); } message = QString("%1 (1-%2):") .arg(QObject::tr("Choose the option")) .arg(QString::number(optionList.size())); showMessage(message, QUESTION); char line[1024]; fgets(line, sizeof(line), stdin); if(line[strnlen(line,1024) - 1] == '\n') line[strnlen(line,1024) - 1] = '\0'; if(!strcmp(line, "1")) return OPTION_TRY_AGAIN; else if(!strcmp(line, "2")) { if(showSelectDevices) return OPTION_SELECT_DEVICE; else return OPTION_CANCEL; } else if(showSelectDevices && !strcmp(line, "3")) return OPTION_CANCEL; else { showMessage(QObject::tr("Invaild response \"") + line + "\"" + "," + QObject::tr("authentication will be canceld") , NOTIFY); showMessage(QObject::tr("AUTHENTICATION CANCELED"), START); exit(BIO_FAILED); } return OPTION_UNDEFINED; } DeviceInfo showDevices(const QMap> &devicesMap) { int count = 0; QString message; showMessage(QObject::tr("=== BIOMETRIC DEVICES ==="), PROMPT); for(auto type : devicesMap.keys()) { for(auto deviceInfo : devicesMap[type]) { message = QString(" %1. [%2] %3") .arg(QString::number(++count)) .arg(BioDevices::bioTypeToString_tr(type)) .arg(deviceInfo.device_shortname); showMessage(message, NOTIFY); } } message = QString("%1 (1-%2):") .arg(QObject::tr("Choose the device")) .arg(QString::number(count)); showMessage(message, QUESTION); char line[1024]; fgets(line, sizeof(line), stdin); if(line[strnlen(line,1024) - 1] == '\n') line[strnlen(line,1024) - 1] = '\0'; for(auto ch : QString(line)) { if(!ch.isDigit()){ showMessage(QObject::tr("Invaild response \"") + line + "\"" + "," +QObject::tr("authentication will be canceld") , NOTIFY); showMessage(QObject::tr("AUTHENTICATION CANCELED"), START); exit(BIO_FAILED); } } int deviceIndex = QString(line).toInt(); if(deviceIndex > count) { showMessage(QObject::tr("Invaild response \"") + line + "\"" + "," + QObject::tr("authentication will be canceld"), NOTIFY); showMessage(QObject::tr("AUTHENTICATION CANCELED"), START); exit(BIO_FAILED); } int i = 0; for(auto type : devicesMap.keys()) { int size = devicesMap[type].size(); if(i + size >= deviceIndex) { return devicesMap[type][deviceIndex - i - 1]; } i += size; } return DeviceInfo(); } static void signal_handler(int signo) { if (signo == SIGHUP) { bioAuth.stopAuth(); } } int main(int argc, char *argv[]) { QCoreApplication::setSetuidAllowed(true); QCoreApplication a(argc, argv); QString locale = QLocale::system().name(); QTranslator translator, translator_bin; QString qmfile = QString("%1/i18n_qm/%2.qm").arg(GET_STR(UKUI_BIOMETRIC)).arg(locale); QString qmfile_bin = QString("%1/i18n_qm/bioauth-bin/%2.qm").arg(GET_STR(UKUI_BIOMETRIC)).arg(locale); qDebug() << "load translation file " << qmfile << qmfile_bin; translator.load(qmfile); translator_bin.load((qmfile_bin)); a.installTranslator(&translator); a.installTranslator(&translator_bin); QCommandLineParser parser; QCommandLineOption serviceOption({"s", "service"}, QObject::tr("Sevice Name"), "service", ""); QCommandLineOption displayOption({"x", "display"}, QObject::tr("DISPLAY env"), "display", ":0"); QCommandLineOption usernameOption({"u", "user"}, QObject::tr("User"), "user", ""); QCommandLineOption debugOption({"d", "debug"}, QObject::tr("Display debug information")); QCommandLineOption deviceOption({"e", "device"}, QObject::tr("Device short name"), ""); parser.addOptions({serviceOption, displayOption, usernameOption, debugOption, deviceOption}); parser.process(a); if(parser.isSet(debugOption)) enableDebug = true; else enableDebug = false; logPrefix = "[pam-diaglog]:"; qInstallMessageHandler(outputMessage); QString serverName = parser.value(serviceOption); if (serverName == "sudo" && isQuickInput()) { exit(BIO_ERROR); } QString userName = parser.value(usernameOption); if(userName.isEmpty()) exit(BIO_ERROR); qDebug() << "authentication user: " << userName; uid_t uid; struct passwd *pwd = getpwnam(userName.toLocal8Bit().data()); if(pwd) uid = pwd->pw_uid; else exit(BIO_ERROR); BioDevices bioDevices(true); bioDevices.setUId(uid); int maxFailedTimes = bioDevices.getFailedTimes(); DeviceInfoPtr deviceInfo = bioDevices.getDefaultDevice(uid); bool isHiddenSwitchButton = bioDevices.GetHiddenSwitchButton(); if(!deviceInfo){ // å�ªæ£€æŸ¥é»˜è®¤è®¾å¤‡ï¼Œä¸�å†�使用第一个设备 exit(BIO_ERROR); } if(bioDevices.getFeatureCount(uid)<1) exit(BIO_ERROR); if(deviceInfo->biotype == 6){ showMessage(QObject::tr("UKEY AUTHENTICATION"), START); }else{ showMessage(QObject::tr("BIOMETRIC AUTHENTICATION"), START); if(!isHiddenSwitchButton) showMessage(QObject::tr("Press Q or Esc to cancel"), PROMPT); } bioAuth.setUid(uid); bioAuth.setDevice(deviceInfo); KeyWatcher watcher; QMap m_failedTimes; QObject::connect(&bioAuth, &BioAuth::notify, &a, [&](const QString &msg){ showMessage(msg, NOTIFY); }); QObject::connect(&bioAuth, &BioAuth::authComplete, &a, [&](uid_t uid_, int result, int retErrNo){ Q_UNUSED(retErrNo); watcher.stop(); bool isBioEnable = bioDevices.GetBioAuthEnable(uid_); bool isUkeyDevice = false; if(deviceInfo && deviceInfo->biotype == 6){ isUkeyDevice = true; } if(!isBioEnable && !isUkeyDevice){ showMessage(QObject::tr("BIOMETRIC AUTHENTICATION IS CLOSED"), RESULT); exit(BIO_IGNORE); } if(result && uid == uid_) { showMessage(QObject::tr("AUTHENTICATION SUCCESS"), RESULT); exit(BIO_SUCCESS); } else { showMessage(QObject::tr("AUTHENTICATION FAILED"), RESULT); DeviceInfoPtr curDeviceInfo = bioAuth.getDevice(); if (m_failedTimes.contains(deviceInfo->device_id)) { m_failedTimes[curDeviceInfo->device_id] = m_failedTimes[curDeviceInfo->device_id] + 1; } else { m_failedTimes[curDeviceInfo->device_id] = 1; } if(m_failedTimes[curDeviceInfo->device_id]biotype)).arg(maxFailedTimes-m_failedTimes[deviceInfo->device_id]),RESULT); }else{ showMessage(QObject::tr("Unable to verify %1, please enter password.").arg(bioDevices.bioTypeToString_tr(curDeviceInfo->biotype)),RESULT); exit(BIO_IGNORE); } Option option = showOption(bioDevices.getAllDevices().count() > 1); switch(option) { case OPTION_TRY_AGAIN: if(deviceInfo->biotype == 6){ QString code = inputPinCode(); bioAuth.SetExtraInfo("pincode",code); } bioAuth.startAuth(); watcher.start(); break; case OPTION_SELECT_DEVICE: { deviceInfo = std::make_shared(); *deviceInfo = showDevices(bioDevices.getAllDevices()); bioAuth.setDevice(deviceInfo); if(deviceInfo->biotype == 6){ QString code = inputPinCode(); bioAuth.SetExtraInfo("pincode",code); } bioAuth.startAuth(); watcher.start(); break; } case OPTION_CANCEL: if(isHiddenSwitchButton) { exit(BIO_ERROR); }else{ if(deviceInfo->biotype == 6){ showMessage(QObject::tr("AUTHENTICATION END"), START); }else{ showMessage(QObject::tr("BIOMETRIC AUTHENTICATION END"), START); } exit(BIO_IGNORE); break; } default: break; } } }); if(deviceInfo->biotype == 6){ QString code = inputPinCode(); bioAuth.SetExtraInfo("pincode",code); } bioAuth.startAuth(); if (!isHiddenSwitchButton) { QObject::connect(&watcher, &KeyWatcher::exit, &a, [&]{ showMessage(QObject::tr("AUTHENTICATION CANCELED"), START); bioAuth.stopAuth(); exit(BIO_IGNORE); }); } watcher.start(); signal(SIGHUP, signal_handler); return a.exec(); } ukui-biometric-auth/bioauth-bin/src/keywatcher.h0000664000175000017500000000176215167732630020716 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef KEYWATCHER_H #define KEYWATCHER_H #include #include class KeyWatcher : public QThread { Q_OBJECT public: explicit KeyWatcher(QObject *parent = nullptr); void run() override; void stop(); signals: void exit(); private: struct termios save; }; #endif // KEYWATCHER_H ukui-biometric-auth/bioauth-bin/CMakeLists.txt0000664000175000017500000000222315167732644020346 0ustar fengfengproject(bioauth-bin) set(CMAKE_AUTOMOC ON) # 定义æº�文件 set(bin_SRCS src/main.cpp src/keywatcher.cpp ../common/generic.cpp ) # æ ¹æ�®Qt版本设置包å�«ç›®å½•和链接库 if(QT_VERSION_MAJOR EQUAL 6) include_directories( ../common ../bioauth/include ${Qt6Core_INCLUDE_DIRS} ${Qt6DBus_INCLUDE_DIRS} ) add_executable(bioauth ${bin_SRCS}) target_link_libraries(bioauth Qt6::Core BioAuth) else() include_directories( ../common ../bioauth/include ${Qt5Core_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ) add_executable(bioauth ${bin_SRCS}) target_link_libraries(bioauth Qt5::Core BioAuth) endif() install(TARGETS bioauth DESTINATION bin) file(GLOB ts_files i18n_ts/*.ts) # æ ¹æ�®Qt版本使用相应的翻译函数 if(QT_VERSION_MAJOR EQUAL 6) qt6_add_translation(qm_files ${ts_files}) else() qt5_add_translation(qm_files ${ts_files}) endif() add_custom_target(bioauth-bin_i18n DEPENDS ${qm_files} SOURCES ${ts_files}) add_dependencies(bioauth bioauth-bin_i18n) install(FILES ${qm_files} DESTINATION ${UKUI_BIOMETRIC_DIR}/i18n_qm/bioauth-bin) ukui-biometric-auth/bioauth-bin/i18n_ts/0000775000175000017500000000000015167732644017074 5ustar fengfengukui-biometric-auth/bioauth-bin/i18n_ts/ru.ts0000664000175000017500000001206215167732644020073 0ustar fengfeng BioDevices FingerPrint FingerPrint FingerVein FingerVein Iris ИриÑ� Face Лицо VoicePrint Voiceprint QObject Try it again Попробуйте Ñ�нова Use other Devices ИÑ�пользовать другие уÑ�тройÑ�тва Cancel Отмена Choose the option Выберите вариант Invaild response " Invaild response \ " AUTHENTICATION CANCELED Ð�ВТОРИЗÐ�ЦИЯ ОТМЕÐ�Ð� === BIOMETRIC DEVICES === === БИОМЕТРИЧЕСКИЕ УСТРОЙСТВÐ� === Choose the device Выберите уÑ�тройÑ�тво Sevice Name ИмÑ� Ñ�чейки DISPLAY env DISPLAY env User пользователь Display debug information Отображать отладочную информацию Device short name Краткое название уÑ�тройÑ�тва BIOMETRIC AUTHENTICATION БИОМЕТРИЧЕСКÐ�Я Ð�УТЕÐ�ТИФИКÐ�ЦИЯ Press Q or Esc to cancel Ð�ажмите Q или Esc, чтобы отменить AUTHENTICATION SUCCESS УСПЕХ Ð�УТЕÐ�ТИФИКÐ�ЦИИ AUTHENTICATION FAILED Ð�ВТОРИЗÐ�ЦИЯ Ð�ЕИСПРÐ�Ð’Ð�О BIOMETRIC AUTHENTICATION END КОÐ�ТРОЛЬ БИОМЕТРИЧЕСКОЙ Ð�ВТОРИЗÐ�ЦИИ authentication will be canceld Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. Enter the ukey password UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION END ukui-biometric-auth/bioauth-bin/i18n_ts/de.ts0000664000175000017500000002547215167732644020046 0ustar fengfeng BioAuthWidget More 更多 Retry wiederholen Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password Passwort Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 Es gibt zu viele fehlgeschlagene Versuche, bitte geben Sie Ihr Passwort ein. %1 authentication failure,there are still %2 remaining opportunities %1 Authentifizierung fehlgeschlagen und es sind noch %2 verbleibende Chancen Please use wechat to scan the code Bitte verwenden Sie WeChat, um den Code zu scannen BioDevices Unplugging of %1 device detected Das %1-Gerät wurde vom Stromnetz getrennt %1 device insertion detected %1 angeschlossenes Gerät erkannt ukui-biometric-manager Tools für die biometrische Verwaltung biometric Biologische Eigenschaften FingerPrint Fingerabdruck FingerVein Fingervenen Iris Iris Face Gesichtserkennung VoicePrint Stimmenausdruck ukey Sicherheitsschlüssel QRCode QR-Code Wechat 微信 BioDevicesWidget Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options Anmeldeoptionen Password Passwort Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password Try it again Use other Devices Cancel Choose the option Invaild response " authentication will be canceld AUTHENTICATION CANCELED === BIOMETRIC DEVICES === Choose the device Sevice Name DISPLAY env User Display debug information Device short name UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION Press Q or Esc to cancel BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION SUCCESS AUTHENTICATION FAILED Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. AUTHENTICATION END BIOMETRIC AUTHENTICATION END ukui-biometric-auth/bioauth-bin/i18n_ts/ky.ts0000664000175000017500000002755115167732644020101 0ustar fengfeng BioAuthWidget More 更多 Retry Ретри Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password СырÑ�өз Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 өтө көп ийгиликÑ�из аракеттер,, Ñ�ураныч, Ñ�ырÑ�өз киргизүү. %1 authentication failure,there are still %2 remaining opportunities %1 аутентификациÑ�лык жетишÑ�издик,дагы Ñ�ле %2 калган мүмкүнчүлүктөр бар Please use wechat to scan the code Кодду Ñ�канерлеу үчүн вечат колдонуңуз BioDevices Unplugging of %1 device detected %1 орнотмоÑ�унун өчүрүлүшү аныкталды %1 device insertion detected %1 түзмөк орнотмоÑ�у аныкталды ukui-biometric-manager укуи-биометриÑ�лык-менеджери biometric биометриÑ� FingerPrint Манжа изи FingerVein Манжавейн Iris ИриÑ� Face Бет VoicePrint VoicePrint ukey уики QRCode QRCode Wechat 微信 BioDevicesWidget Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options Кирүү параметрлери Password СырÑ�өз Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password ukey جاشىرۇۇن نومۇرۇن كىرگىزىڭ Try it again قايرا سىناڭ Use other Devices باشقا شايمان ىشتەتىش Cancel ارعادان قالتىرىش Choose the option تانداش تۉرۉ Invaild response " ۅنۉمسۉز ىنكاس authentication will be canceld اتۇۇلدۇق تەكشەرىش ارعادان قالتىرلات AUTHENTICATION CANCELED اتۇۇلدۇق تەكشەرىش ارعادان قالتىرىلدى === BIOMETRIC DEVICES === = = = بىيولوگىيەلىك ايىرمالاندىرىش جابدۇۇسۇ = = = Choose the device باشقا شايمان تانداڭ Sevice Name تەيلۅۅ ناامى DISPLAY env كۅرسۅتۉۉ چۅيرۅسۉ User كەرەكتۅۅچۉ ناامى Display debug information تەڭشۅۅ ۇچۇردۇ كۅرسۅتۉۉ Device short name جابدۇۇسۇنۇن قىسقا ناامى UKEY AUTHENTICATION UKEY تولۇمدۇۇلۇق دالىلدۅ BIOMETRIC AUTHENTICATION بىيولوگىيەلىك ۅزگۅچۅلۉك ىسپاتى Press Q or Esc to cancel Q كۅرۉنۉشتۅرۉ Esc نى باسىپ ارعادان قالتىرىڭ BIOMETRIC AUTHENTICATION IS CLOSED بىئولوگىيەلىك ۅزگۅچۅلۉگۉ دالىلدۅ تاقالدى AUTHENTICATION SUCCESS اتۇۇلدۇق تەكشەرىش جەڭىشتۉۉ بولدۇ AUTHENTICATION FAILED اتۇۇلدۇق تەكشەرىش جەڭىلۉۉ بولدۇ . Failed to verify %1, you still have %2 verification opportunities Ùª1 نى دالىلدۅ جەڭىلۉۉ بولدۇ ØŒ سىزدە داعى Û•Ù„Û• Ùª2 دالىلدۅ مۅۅرتۉ بار Unable to verify %1, please enter password. %1 نى دالىلدەگەلى بولبويت ØŒ جاشىرۇۇن نومۇردۇ كىرگىزىڭ. AUTHENTICATION END اتۇۇلدۇق تەكشەرىش سوڭۇنا چىقتى. BIOMETRIC AUTHENTICATION END بىئولوگىيەلىك ۅزگۅچۅلۉك ىسپات بەرۉۉ Û‡Ú†Û‡ ukui-biometric-auth/bioauth-bin/i18n_ts/zh_CN.ts0000664000175000017500000001374715167732644020461 0ustar fengfeng QObject Enter the ukey password 输入ukey密ç � Enter the ukey password 输入ukey密ç �\n Try it again å†�试一次 Use other Devices 使用其他设备 Cancel å�–消 Choose the option 选择选项 Invaild response " ä¸�能识别的å“�应 " authentication will be canceld 认è¯�å°†è¦�被å�–消 AUTHENTICATION CANCELED 认è¯�被å�–消 === BIOMETRIC DEVICES === === 生物识别设备 === Choose the device 选择设备 Sevice Name DISPLAY env User Display debug information Device short name UKEY AUTHENTICATION ukey认è¯� BIOMETRIC AUTHENTICATION 生物识别认è¯� Press Q or Esc to cancel 按Q或者Escå�–消 BIOMETRIC AUTHENTICATION IS CLOSED 生物识别认è¯�已关闭 AUTHENTICATION SUCCESS 认è¯�æˆ�功 AUTHENTICATION FAILED 认è¯�失败 Failed to verify %1, you still have %2 verification opportunities 验è¯�%1失败,您还有%2次å°�试机会 Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. AUTHENTICATION END 认è¯�结æ�Ÿ BIOMETRIC AUTHENTICATION END 生物识别认è¯�结æ�Ÿ ukui-biometric-auth/bioauth-bin/i18n_ts/kk.ts0000664000175000017500000003007515167732644020056 0ustar fengfeng BioAuthWidget Form Пішін More 更多 Retry ретри Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password құпиÑ�Ñ�өз Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. % 1 Қате әрекеттер тым көп, құпиÑ� Ñ�өзіңізді енгізіңіз. %1 authentication failure,there are still %2 remaining opportunities % 1 аутентификациÑ�Ñ�Ñ‹ жаңылыÑ�қан және әлі де% 2 мүмкіндігі бар Please use wechat to scan the code Кодты Ñ�канерлеу үшін WeChat пайдалануыңызды Ñ�ұраймын BioDevices Unplugging of %1 device detected % 1 құрылғы ажыратылды %1 device insertion detected % 1 құрылғы анықталды ukui-biometric-manager БиометриÑ�лық баÑ�қару құралдары biometric БиологиÑ�лық Ñ�ипаттамалары FingerPrint Ñ�ауÑ�ақ ізі FingerVein СауÑ�ақ көктамырлары Iris ириÑ� Face Бет тану VoicePrint ДауыÑ�тық із ukey ҚауіпÑ�іздік кілттері QRCode QR коды Wechat 微信 BioDevicesWidget Form Пішін Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options Кіру параметрлері Password құпиÑ�Ñ�өз Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password ukey قۇپيا نۇمىردى كىرگىزىڭىز Try it again قاتە سىناڭ Use other Devices باسقا اسباب ٸستەتۋ Cancel كۇشىنەن قالدىرۋ Choose the option تالداۋ تۇرى Invaild response " ونٸمسٸز جاۋاپ authentication will be canceld ازاماتتىق تەكسەرۋ كۇشىنەن قالدىرىلدى AUTHENTICATION CANCELED ازاماتتىق تەكسەرۋ كۇشىنەن قالدىرىلدى === BIOMETRIC DEVICES === = = = بىيولوگىيەلىك پارىقتاندىرۋ اسپابٸ = = = Choose the device باسقا اسباب تالدا Sevice Name قىزىمەت مى DISPLAY env كورسەتۋ ورتا User الارمان مى Display debug information تەڭشەۋ حاباردٸ كورسەتۋ Device short name اسبابٸتٸڭ قىسقا مى UKEY AUTHENTICATION UKEY سالاۋاتىن دالەلدەۋ BIOMETRIC AUTHENTICATION بىيولوگىيەلىك ەرەكشەلىك كۋالٸكتٸ Press Q or Esc to cancel Q ياكي Esc نى باسٸپ كۇشىنەن قالدىرىڭ BIOMETRIC AUTHENTICATION IS CLOSED بىئولوگىيەلىك ەرەكشەلىكتى دالەلدەۋ جابٸلدٸ AUTHENTICATION SUCCESS ازاماتتىق تەكسەرۋ ناتيجەلى قالدى AUTHENTICATION FAILED ازاماتتىق تەكسەرۋ جەڭىلىپ قالدى. Failed to verify %1, you still have %2 verification opportunities Ùª1 نى دالەلدەۋ جەڭىلىپ قالدى، سىزدە جانەدە Ùª2 دالەلدەۋ ورايى بار Unable to verify %1, please enter password. %1 نى دالەلى بولمايدى، قۇپيا نۇمىردى كىرگىزىڭىز. AUTHENTICATION END ازاماتتىق تەكسەرۋ اياقتاتادى. BIOMETRIC AUTHENTICATION END بىئولوگىيەلىك ەرەكشەلىك دالەل بەرۋ ۇشى ukui-biometric-auth/bioauth-bin/i18n_ts/tr.ts0000664000175000017500000001512415167732644020074 0ustar fengfeng BioDevices FingerPrint Parmak İzi FingerVein Damar İzi Iris Göz Face Yüz Tanıma VoicePrint Ses İzi QObject Enter the ukey password Try it again Yeniden Dene Use other Devices DiÄŸer Cihazları Kullan Cancel İptal Choose the option SeçeneÄŸi seçin Invaild response " Geçersiz cevap " authentication will be canceld AUTHENTICATION CANCELED KİMLİK DOÄžRULAMA === BIOMETRIC DEVICES === === BİYOMETRİK CİHAZLAR === Choose the device Cihazı seçin Sevice Name Servis Adı DISPLAY env EKRAN env User Kullanıcı Display debug information Hata ayıklama bilgilerini görüntüle Device short name Cihaz kısa adı UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION BİYOMETRİK KİMLİK DOÄžRULAMA Press Q or Esc to cancel İptal etmek için Q veya Esc tuÅŸuna basın BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION SUCCESS KİMLİK DOÄžRULAMA AUTHENTICATION FAILED KİMLİK DOÄžRULAMA BAÅžARISIZ OLDU Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. AUTHENTICATION END BIOMETRIC AUTHENTICATION END BİYOMETRİK KİMLİK DOÄžRULAMA SONU ukui-biometric-auth/bioauth-bin/i18n_ts/bo.ts0000664000175000017500000001347515167732644020056 0ustar fengfeng QObject Enter the ukey password Try it again Use other Devices Cancel Choose the option Invaild response " authentication will be canceld AUTHENTICATION CANCELED === BIOMETRIC DEVICES === Choose the device Sevice Name DISPLAY env User Display debug information Device short name UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION Press Q or Esc to cancel BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION SUCCESS AUTHENTICATION FAILED Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. AUTHENTICATION END BIOMETRIC AUTHENTICATION END ukui-biometric-auth/bioauth-bin/i18n_ts/ug.ts0000664000175000017500000003022515167732644020061 0ustar fengfeng BioAuthWidget More 更多 Retry قايتا سىناپ بىقىڭ Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password مەخپىي نومۇر Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. 1-نومۇر مەغلۇپ بولغان سىناق Ù‚Û�تىم سانى زىيادە كۆپ، مەخپىي نومۇرنى كىرگۈزۈڭ %1 authentication failure,there are still %2 remaining opportunities بىر كىملىك دەلىللەش مەغلۇپ بولدى، يەنىلا Ùª2 ئÛ�شىپ قالغان پۇرسەت بار Please use wechat to scan the code ئۈندىداردا كود سۈپۈرۈڭ BioDevices Unplugging of %1 device detected تەكشۈرۈپ بايقىغان 1 ئۈسكۈنىنى تارتىپ چىقارماق %1 device insertion detected Ùª1 ئۈسكۈنىنىڭ كىرگۈزۈلگەنلىكىنى تەكشۈرۈپ چىقماق ukui-biometric-manager بىئولوگىيەلىك ئالاھىدىلىك باشقۇرۇش قورالى biometric بىئولوگىيەلىك ئالاھىدىلىك FingerPrint بارماق ئىزى FingerVein Û‹Û�نانى كۆرسىتىدۇ Iris رەڭدار پەردە Face ئادەم يۈزىنى پەرقلەندۈرۈش VoicePrint ئاۋاز سىزىقى ukey بىخەتەر ئاچقۇچ QRCode ئىككى ئۆلچەملىك كود Wechat 微信 BioDevicesWidget Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options تاللاش تۈرىگە كىرمەك Password مەخپىي نومۇر Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password ukey مەخپىي نومۇرىنى كىرگۈزۈڭ Try it again قايتا سىناڭ Use other Devices باشقا ئۈسكۈنە ئىشلىتىش Cancel ئەمەلدىن قالدۇرۇش Choose the option تاللاش تۈرى Invaild response " ئۈنۈمسىز ئىنكاس authentication will be canceld سالاھىيەت تەكشۈرۈش ئەمەلدىن قالدۇرۇلىدۇ AUTHENTICATION CANCELED سالاھىيەت تەكشۈرۈش ئەمەلدىن قالدۇرۇلدى === BIOMETRIC DEVICES === = = = بىيولوگىيەلىك پەرقلەندۈرۈش ئۈسكۈنىسى = = = Choose the device باشقا ئۈسكۈنە تاللاڭ Sevice Name مۇلازىمەت نامى DISPLAY env كۆرسىتىش مۇھىتى User ئىشلەتكۈچى Display debug information تەڭشەش ئۇچۇرىنى كۆرسىتىش Device short name ئۈسكۈنىنىڭ قىسقا نامى UKEY AUTHENTICATION UKEY سالاھىيىتىنى دەلىللەش BIOMETRIC AUTHENTICATION بىيولوگىيەلىك ئالاھىدىلىك ئىسپاتى Press Q or Esc to cancel Q ياكى Esc نى بÛ�سىپ ئەمەلدىن قالدۇرۇڭ BIOMETRIC AUTHENTICATION IS CLOSED بىئولوگىيەلىك ئالاھىدىلىكنى دەلىللەش تاقالدى AUTHENTICATION SUCCESS سالاھىيەت تەكشۈرۈش مۇۋەپپەقىيەتلىك بولدى AUTHENTICATION FAILED سالاھىيەت تەكشۈرۈش مەغلۇپ بولدى. Failed to verify %1, you still have %2 verification opportunities Ùª1 دەلىللەش مەغلۇپ بولدى، سىزدە ÙŠÛ•Ù†Û• Ùª2 دەلىللەش پۇرسىتى بار Unable to verify %1, please enter password. %1 نى دەلىللىگىلى بولمايدۇ، مەخپىي نومۇرنى كىرگۈزۈڭ. AUTHENTICATION END سالاھىيەت تەكشۈرۈش ئاخىرلاشتى. BIOMETRIC AUTHENTICATION END بىئولوگىيەلىك ئالاھىدىلىك ئىسپات بÛ�رىش ئۇچى ukui-biometric-auth/bioauth-bin/i18n_ts/pt.ts0000664000175000017500000001140615167732644020071 0ustar fengfeng BioDevices FingerPrint Impressão digital FingerVein FingerVein Iris Ã�ris Face Cara VoicePrint VoicePrint QObject Try it again Tente de novo Use other Devices Use outros dispositivos Cancel Cancelar Choose the option Escolha a opção Invaild response " Resposta Inválida \ " AUTHENTICATION CANCELED AUTENTICAÇÃO CANCELADA === BIOMETRIC DEVICES === === DISPOSITIVOS BIOMÉTRICOS === Choose the device Escolha o dispositivo Sevice Name Nome do Sevice DISPLAY env DISPLAY env User Do utilizador Display debug information Exibir informações de depuração Device short name Nome abreviado do dispositivo BIOMETRIC AUTHENTICATION AUTENTICAÇÃO BIOMÉTRICA Press Q or Esc to cancel Pressione Q ou Esc para cancelar AUTHENTICATION SUCCESS SUCESSO DE AUTENTICAÇÃO AUTHENTICATION FAILED AUTENTICAÇÃO FALHOU BIOMETRIC AUTHENTICATION END ENDEREÇO ​​DE AUTENTICAÇÃO BIOMÉTRICA authentication will be canceld Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. Enter the ukey password UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION END ukui-biometric-auth/bioauth-bin/i18n_ts/bo_CN.ts0000664000175000017500000001361315167732644020430 0ustar fengfeng QObject DISPLAY env Choose the option གདམ་བྱ་འདེམ་པà¼� === BIOMETRIC DEVICES === === སà¾�ྱེ་དངོས་ངོས་འཛིན་སྒྲིག་ཆསà¼� === Display debug information བསྒྱུར་བཅོས་ཆ་འཕྲིན་མངོན་དུ་བཅུག་པà¼� Invaild response " ནུས་མེད་ཀྱི་དང་ལེན་ཨང་à¼� AUTHENTICATION SUCCESS བདེན་དཔང་ངོས་འཛིན་ལེགས་གྲུབà¼� Try it again ཡང་བསà¾�ྱར་ཚོད་ལྟ་à½�ེངས་གཅིག Cancel མེད་པར་བཟོ་བ authentication will be canceld བདེན་དཔང་ངོས་འཛིན་མི་འགྱངས་པར་རྩིས་མེད་གà½�ོང་à¼� AUTHENTICATION CANCELED བདེན་དཔང་ངོས་འཛིན་རྩིས་མེད་གà½�ོང་à¼� Sevice Name ཞབས་ཞུའི་མིང་à¼� Press Q or Esc to cancel Qམནན་པའམEscརྩིས་མེདà¼� BIOMETRIC AUTHENTICATION སà¾�ྱེ་དངོས་བརྟག་དཔྱད་བདེན་དཔང་ངོས་འཛིནà¼� AUTHENTICATION FAILED བདེན་དཔང་ངོས་འཛིན་ཕམ་ཉེས་བྱུང་à¼� Use other Devices སྒྲིག་ཆས་གཞན་བེད་སྤྱོད་བà½�ང་à¼� BIOMETRIC AUTHENTICATION END སà¾�ྱེ་དངོས་བརྟག་དཔྱད་བདེན་དཔང་ངོས་འཛིན་མཇུག་སྒྲིལà¼� Choose the device སྒྲིག་ཆས་འདེམ་པà¼� User སྤྱོད་མà½�ནà¼� Device short name སྒྲིག་ཆས་ཀྱི་བསྡུས་མིང་à¼� Failed to verify %1, you still have %2 verification opportunities ཚོད་ལྟས་ར་སྤྲོད་%1ཕམ་ཉེས་བྱུང་à¼�à½�ྱེད་རང་ད་དུང་ཡོདà¼�%2ཚོད་ལྟ་བྱེད་པའི་གོ་སà¾�བས་ཤིག་རེདà¼� Unable to verify %1, please enter password. ཚོད་ལྟས་ར་སྤྲོད་བྱེད་à½�བས་མེད%1,à½�ྱོད་ཀྱིས་གསང་གྲངས་ནང་འཇུག་བྱེད་རོགསà¼� UKEY AUTHENTICATION བདེ་འཇགས་ཀྱི་གསང་བའི་བདེན་དཔང་ར་སྤྲོདà¼� BIOMETRIC AUTHENTICATION IS CLOSED སà¾�ྱེ་དངོས་ཀྱི་ངོས་འཛིན་à½�ས་ལེན་བྱས་པ་སྒོ་བརྒྱབ་ཟིནà¼� AUTHENTICATION END བདེན་དཔང་ར་སྤྲོད་མཇུག་བསྒྲི Enter the ukey password བདེ་འཇགས་ཀྱི་གསང་བའི་གསང་བའི་ཨང་གྲངས་ནང་འཇུག་བྱེད་དགོསà¼� ukui-biometric-auth/bioauth-bin/i18n_ts/vi.ts0000664000175000017500000001430715167732644020067 0ustar fengfeng QObject Enter the ukey password Nhập mật khẩu UKey Enter the ukey password Nhập mật khẩu ukey Try it again Thá»­ lại má»™t lần nữa Use other Devices Sá»­ dụng thiết bị khác Cancel Há»§y Choose the option Chá»�n tùy chá»�n Invaild response " Phản hồi Invaild " authentication will be canceld Xác thá»±c sẽ bị há»§y bá»� AUTHENTICATION CANCELED XÃ�C THá»°C BỊ HỦY === BIOMETRIC DEVICES === === THIẾT BỊ SINH TRẮC HỌC === Choose the device Chá»�n thiết bị Sevice Name DISPLAY env User Tên ngưá»�i dùng Display debug information Device short name Tên ngắn thiết bị UKEY AUTHENTICATION XÃ�C THá»°C UKEY BIOMETRIC AUTHENTICATION XÃ�C THá»°C SINH TRẮC HỌC Press Q or Esc to cancel Ấn Q hoặc Esc để há»§y BIOMETRIC AUTHENTICATION IS CLOSED Xác thá»±c sinh trắc há»�c đã bị tắt AUTHENTICATION SUCCESS XÃ�C THá»°C THÀNH CÔNG AUTHENTICATION FAILED Xác thá»±c thất bại Failed to verify %1, you still have %2 verification opportunities Xác thá»±c %1 thất bại,bạn còn %2 lần thá»­ Unable to verify %1, please enter password. Không thể xác minh %1, vui lòng nhập mật khẩu. AUTHENTICATION END KẾT THÚC XÃ�C THá»°C BIOMETRIC AUTHENTICATION END Xác thá»±c sinh trắc há»�c đã kết thúc ukui-biometric-auth/bioauth-bin/i18n_ts/mn.ts0000664000175000017500000003231015167732644020055 0ustar fengfeng BioAuthWidget More 更多 Retry ᠳᠠᠬᠢᠨ ᠲᠤᠷᠰᠢᠬᠤ Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 ᠢᠯᠠᠭᠳᠠᠭᠰᠠᠨ ᠲᠤᠷᠰᠢᠬᠤ ᠤᠳᠠᠭ᠎ᠠ ᠲᠣᠭ᠎ᠠ ᠬᠡᠳᠦ ᠣᠯᠠᠨ á ‚ ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠣᠷᠣᠭᠤᠯᠤᠭᠠᠷᠠᠢ á ƒ %1 authentication failure,there are still %2 remaining opportunities %1 ᠪᠡᠶ᠎ᠡ᠎ᠶ᠋ᠢᠨ ᠬᠢᠷᠢ᠎ᠶ᠋ᠢᠨ ᠰᠢᠯᠭᠠᠨ ᠪᠠᠲᠤᠯᠠᠯᠲᠠ ᠢᠯᠠᠭᠳᠠᠪᠠ á ‚ ᠮᠥᠨ %2 ᠦᠯᠡᠳᠡᠬᠦ ᠲᠣᠬᠢᠶᠠᠯ ᠪᠣᠢ Please use wechat to scan the code ᠸᠢᠴᠠᠲ᠎ᠢ᠋ᠶ᠋ᠠᠷ ᠦᠰᠦᠭ ᠰᠢᠷᠪᠢᠬᠦ ᠪᠣᠯᠪᠠᠤ BioDevices Unplugging of %1 device detected %1 ᠲᠥᠬᠥᠭᠡᠷᠦᠮᠵᠢ᠎ᠶ᠋ᠢ ᠰᠤᠭᠤᠯᠵᠤ á ­á  á ·á ­á  á ¨ á   %1 device insertion detected %1 ᠲᠥᠬᠥᠭᠡᠷᠦᠮᠵᠢ ᠬᠠᠪᠴᠢᠭᠤᠯᠤᠭᠰᠠᠨ᠎ᠢ᠋ ᠪᠠᠢᠴᠠᠭᠠᠨ ᠣᠯᠪᠠ ukui-biometric-manager ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ᠎ᠤ᠋ᠨ ᠣᠨᠴᠠᠯᠢᠭ ᠬᠠᠮᠢᠶᠠᠷᠤᠯᠲᠠ᠎ᠶ᠋ᠢᠨ ᠪᠠᠭᠠᠵᠢ biometric ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ᠎ᠤ᠋ᠨ ᠣᠨᠴᠠᠯᠢᠭ FingerPrint ᠬᠤᠷᠤᠭᠤᠨ ᠬᠡ FingerVein ᠬᠤᠷᠤᠭᠤᠨ ᠨᠠᠮᠵᠢᠭᠤᠨ ᠰᠤᠳᠠᠰᠤ Iris ᠰᠣᠯᠣᠩᠭ᠎ᠠ ᠪᠦᠷᠬᠦᠭᠦᠯ Face ᠬᠥᠮᠦᠨ᠎ᠦ᠌ ᠨᠢᠭᠤᠷ ᠲᠠᠨᠢᠬᠤ VoicePrint ᠳᠠᠭᠤᠨ ᠡᠷᠢᠶᠡᠨ ukey ᠠᠶᠤᠯᠭᠦᠢ ᠨᠢᠭᠤᠴᠠ ᠲᠦᠯᠬᠢᠭᠦᠷ QRCode ᠬᠣᠶᠠᠷ ᠬᠡᠮᠵᠢᠯᠲᠦ ᠺᠣᠳ᠋ Wechat 微信 BioDevicesWidget Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options ᠲᠡᠮᠳᠡᠭᠯᠡᠬᠦ ᠰᠤᠩᠭᠤᠭᠳᠠᠬᠤᠨ Password ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password ukey ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠢ᠋ ᠣᠷᠣᠭᠤᠯᠬᠤ Try it again ᠳᠠᠬᠢᠵᠤ ᠳᠤᠷᠰᠢᠬᠤ Use other Devices ᠪᠤᠰᠤᠳ ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ ᠵᠢ ᠬᠡᠷᠡᠭᠯᠡᠬᠦ Cancel ᠦᠬᠡᠢᠰᠬᠡᠬᠦ Choose the option ᠰᠤᠩᠭᠤᠭᠳᠠᠬᠤᠨ ᠢ᠋ ᠰᠣᠩᠭᠣᠬᠤ Invaild response " ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠵᠤ ᠪᠣᠯᠬᠤ ᠥᠬᠡᠢ ᠳᠤᠰᠬᠠᠯ " authentication will be canceld ᠬᠡᠷᠡᠴᠢᠯᠡᠯ ᠤᠳᠠᠬᠤ ᠥᠬᠡᠢ ᠦᠬᠡᠢᠰᠬᠡᠭᠳᠡᠨ᠎ᠡ AUTHENTICATION CANCELED ᠬᠡᠷᠡᠴᠢᠯᠡᠯ ᠦᠬᠡᠢᠰᠬᠡᠭᠳᠡᠪᠡ === BIOMETRIC DEVICES === === ᠪᠢᠤᠯᠤᠬᠢ ᠵᠢᠨ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ=== Choose the device ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ ᠰᠣᠩᠭᠣᠬᠤ Sevice Name Sevice Name DISPLAY env DISPLAY env User ᠬᠡᠷᠡᠭᠯᠡᠭᠴᠢ Display debug information ᠳᠤᠬᠢᠷᠠᠭᠤᠯᠤᠭᠰᠠᠨ ᠰᠤᠷᠠᠭ ᠵᠠᠩᠬᠢ ᠢᠯᠡᠷᠡᠬᠦᠯᠬᠦ Device short name ᠨᠢᠭᠡ ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ ᠰᠤᠩᠭᠤᠨ ᠳᠤᠭᠳᠠᠭᠠᠭᠠᠷᠠᠢ UKEY AUTHENTICATION ukey ᠬᠡᠷᠡᠴᠢᠯᠡᠯ BIOMETRIC AUTHENTICATION ᠪᠢᠤᠯᠤᠬᠢ ᠵᠢ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠬᠡᠷᠡᠴᠢᠯᠡᠯ Press Q or Esc to cancel Q ᠪᠤᠶᠤEsc ᠢ᠋\ ᠵᠢ ᠳᠠᠷᠤᠵᠤ ᠦᠬᠡᠢᠰᠬᠡᠬᠦ BIOMETRIC AUTHENTICATION IS CLOSED ᠪᠢᠤᠯᠤᠬᠢ ᠵᠢ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠬᠡᠷᠡᠴᠢᠯᠡᠯ ᠢ᠋ ᠨᠢᠬᠡᠨᠳᠡ ᠬᠠᠭᠠᠪᠠ AUTHENTICATION SUCCESS ᠬᠡᠷᠡᠴᠢᠯᠡᠪᠡ AUTHENTICATION FAILED ᠬᠡᠷᠡᠴᠢᠯᠡᠵᠤ ᠴᠢᠳᠠᠭᠰᠠᠨ ᠥᠬᠡᠢ Failed to verify %1, you still have %2 verification opportunities %1 ᠢ᠋\ ᠵᠢ ᠪᠠᠳᠤᠯᠠᠭᠠᠵᠢᠭᠤᠯᠵᠤ ᠴᠢᠳᠠᠭᠰᠠᠨ ᠥᠬᠡᠢ᠂ ᠲᠠ ᠪᠠᠰᠠ %2 ᠤᠳᠠᠭᠠᠨ ᠤ᠋ ᠳᠤᠷᠰᠢᠬᠤ ᠵᠠᠪᠰᠢᠶᠠᠨ ᠪᠤᠢ Unable to verify %1, please enter password. %1 ᠢ᠋\ ᠵᠢ ᠪᠠᠳᠤᠯᠠᠭᠠᠵᠢᠭᠤᠯᠬᠤ ᠵᠢᠨ á  á ·á ­á Žá   ᠥᠬᠡᠢ᠂ ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠵᠢᠨᠨ ᠤᠷᠤᠭᠤᠯᠤᠨ᠎ᠠ ᠤᠤ᠃ AUTHENTICATION END ᠬᠡᠷᠡᠴᠢᠯᠡᠯ ᠳᠠᠭᠤᠰᠪᠠ BIOMETRIC AUTHENTICATION END ᠪᠢᠤᠯᠤᠬᠢ ᠵᠢ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠬᠡᠷᠡᠴᠢᠯᠡᠯ ᠳᠠᠭᠤᠰᠪᠠ ukui-biometric-auth/bioauth-bin/i18n_ts/fr.ts0000664000175000017500000002603215167732644020056 0ustar fengfeng BioAuthWidget Form Forme More 更多 Retry réessayer Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password mot de passe Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 Il y a trop de tentatives infructueuses, veuillez saisir votre mot de passe. %1 authentication failure,there are still %2 remaining opportunities %1 authentification a échoué et il reste encore %2 chances Please use wechat to scan the code Veuillez utiliser WeChat pour scanner le code BioDevices Unplugging of %1 device detected L’appareil %1 a été débranché %1 device insertion detected %1 périphérique branché détecté ukui-biometric-manager Outils de gestion biométrique biometric Caractéristiques biologiques FingerPrint empreinte digitale FingerVein Veines des doigts Iris iris Face Reconnaissance faciale VoicePrint Voiceprint ukey Clés de sécurité QRCode Code QR Wechat 微信 BioDevicesWidget Form Forme Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options Options de connexion Password mot de passe Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password Try it again Use other Devices Cancel Choose the option Invaild response " authentication will be canceld AUTHENTICATION CANCELED === BIOMETRIC DEVICES === Choose the device Sevice Name DISPLAY env User Display debug information Device short name UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION Press Q or Esc to cancel BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION SUCCESS AUTHENTICATION FAILED Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. AUTHENTICATION END BIOMETRIC AUTHENTICATION END ukui-biometric-auth/bioauth-bin/i18n_ts/es.ts0000664000175000017500000002571315167732644020063 0ustar fengfeng BioAuthWidget Form Forma More 更多 Retry Reintentar Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password Contraseña Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 Demasiados intentos fallidos, ingrese la contraseña. %1 authentication failure,there are still %2 remaining opportunities %1 error de autenticación, todavía quedan %2 oportunidades Please use wechat to scan the code Utilice wechat para escanear el código BioDevices Unplugging of %1 device detected Se ha detectado la desconexión del dispositivo %1 %1 device insertion detected %1 inserción de dispositivo detectada ukui-biometric-manager ukui-gestor-biométrico biometric biométrico FingerPrint Huellas FingerVein FingerVein Iris Iris Face Cara VoicePrint Huella de voz ukey ukey QRCode QRCode Wechat 微信 BioDevicesWidget Form Forma Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options Opciones de inicio de sesión Password Contraseña Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Enter the ukey password Try it again Use other Devices Cancel Choose the option Invaild response " authentication will be canceld AUTHENTICATION CANCELED === BIOMETRIC DEVICES === Choose the device Sevice Name DISPLAY env User Display debug information Device short name UKEY AUTHENTICATION BIOMETRIC AUTHENTICATION Press Q or Esc to cancel BIOMETRIC AUTHENTICATION IS CLOSED AUTHENTICATION SUCCESS AUTHENTICATION FAILED Failed to verify %1, you still have %2 verification opportunities Unable to verify %1, please enter password. AUTHENTICATION END BIOMETRIC AUTHENTICATION END ukui-biometric-auth/bioauth-bin/i18n_ts/zh_HK.ts0000664000175000017500000001405415167732644020453 0ustar fengfeng QObject Enter the ukey password 輸入 ukey 密碼 Enter the ukey password 輸入 ukey 密碼 Try it again å†�試一次 Use other Devices 使用其他設備 Cancel å�–消 Choose the option é�¸æ“‡é�¸é … Invaild response " Invaild 回應 â€� authentication will be canceld 身份驗證將被å�–消 AUTHENTICATION CANCELED 身份驗證已å�–消 === BIOMETRIC DEVICES === === 生物識別設備 === Choose the device é�¸æ“‡è¨­å‚™ Sevice Name æœ�å‹™å��稱 DISPLAY env 顯示環境 User 使用者 Display debug information 顯示調試資訊 Device short name 設備簡稱 UKEY AUTHENTICATION UKEY 身份驗證 BIOMETRIC AUTHENTICATION 生物識別身份驗證 Press Q or Esc to cancel 按 Q 或 Esc é�µå�–消 BIOMETRIC AUTHENTICATION IS CLOSED 生物識別身份驗證已關閉 AUTHENTICATION SUCCESS 身份驗證æˆ�功 AUTHENTICATION FAILED 身份驗證失敗 Failed to verify %1, you still have %2 verification opportunities é©—è­‰ %1 失敗,您ä»�有 %2 驗證機會 Unable to verify %1, please enter password. 無法驗證 %1,請輸入密碼。 AUTHENTICATION END 鑒權çµ�æ�Ÿ BIOMETRIC AUTHENTICATION END 生物識別èª�è­‰çµ�æ�Ÿ ukui-biometric-auth/polkit-agent/0000775000175000017500000000000015167732644016004 5ustar fengfengukui-biometric-auth/polkit-agent/src/0000775000175000017500000000000015167732644016573 5ustar fengfengukui-biometric-auth/polkit-agent/src/mainwindow.cpp0000664000175000017500000016615715167732644021473 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../common/qt_matrix_compat.h" #include "bioauthwidget.h" #include #include #include #include "generic.h" #include "biotypes.h" #include "modeButton.h" #include #define _(string) gettext(string) extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); MainWindow::MainWindow(QWidget *parent) : kdk::KDialog(parent) , ui(new Ui::MainWindow) , users(new Users(this)) , enableBioAuth(false) , receiveBioPAM(false) , authMode(UNDEFINED) , useDoubleAuth(false) , m_timer(nullptr) , w_timer(nullptr) , isLockingFlg(false) , m_nCurLockMin(0) , isbioSuccess(false) { ui->setupUi(this); mainLayout()->addLayout(ui->verticalLayout_2); pam_tally_init(); // // 登录选项 m_labelTip = new KALabel(); m_labelTip->setText(""); m_labelTip->setFixedHeight(30); m_labelTip->hide(); m_loginOptsWidget = new LoginOptionsWidget(); m_loginOptsWidget->hide(); ui->titleTipLayout->addWidget(m_labelTip); ui->loginOptionsLayout->setAlignment(Qt::AlignTop | Qt::AlignCenter); ui->loginOptionsLayout->addWidget(m_loginOptsWidget); ui->loadingUkeyWidget->adjustSize(); ui->loadingUkeyWidget->hide(); ui->widgetUkeyAuth->hide(); ui->loadingUkeyBtn->setAttribute(Qt::WA_TransparentForMouseEvents, true); ui->ukeyPassword->setEchoMode(QLineEdit::Password); ui->loadingUkeyLbl->setText(tr("Insert the ukey into the USB port")); ui->loadingUkeyLbl->setAlignment(Qt::AlignTop | Qt::AlignHCenter); ui->ukeyTipLbl->setText(tr("Enter the ukey password")); ui->ukeyPassword->setPlaceholderText(tr("Input Password")); ui->btnCancel->setAutoDefault(false); ui->btnCancel->setDefault(false); maxFailedTimes = bioDevices.getFailedTimes(); isHiddenSwitchButton = bioDevices.GetHiddenSwitchButton(); closeButton()->setToolTip(tr("Close")); // 连接登录选项信å�·å“�应槽 connect(m_loginOptsWidget, &LoginOptionsWidget::optionSelected, this, &MainWindow::onOptionSelected); connect(m_loginOptsWidget, &LoginOptionsWidget::notifyOptionsChange, this, &MainWindow::onNotifyOptionsChanged); connect(m_loginOptsWidget, &LoginOptionsWidget::authComplete, this, &MainWindow::onLoginOptionsAuthCompleted); connect(m_loginOptsWidget, &LoginOptionsWidget::updateAuthMsg, this, &MainWindow::onUpdateBioAuthMsg); connect(m_loginOptsWidget, &LoginOptionsWidget::updateWndSize, this, &MainWindow::onUpdateWndSize); QFile qssFile(":/qss/src/main.qss"); qssFile.open(QIODevice::ReadOnly); setStyleSheet(qssFile.readAll()); qssFile.close(); ui->lePassword->installEventFilter(this); // åˆ�始化UI状æ€� switchWidget(UNDEFINED); editIcon(); ui->lblContent->adjustSize(); ui->lblContent->hide(); ui->lblMessage->setFixedSize(372, 30); ui->widgetPasswdAuth->adjustSize(); ui->widgetUkeyAuth->adjustSize(); ui->cmbUsers->view()->setTextElideMode(Qt::ElideRight); ui->cmbUsers->setFixedHeight(36); ui->lePassword->setFixedHeight(36); ui->btnBioAuth->hide(); ui->returnButton->hide(); ui->btnAuth->setProperty("isImportant", true); ui->btnCancel->setProperty("useButtonPalette", true); settings = new QGSettings("org.ukui.style", "", this); fontSize = settings->get("system-font-size").toInt(); connect(settings, &QGSettings::changed, this, &MainWindow::onConfigurationChanged); QDBusInterface *interfaceScreensaver = new QDBusInterface("org.ukui.ScreenSaver", "/", "org.ukui.ScreenSaver", QDBusConnection::sessionBus()); connect(interfaceScreensaver, SIGNAL(lock()), this, SLOT(onLockStatus())); connect(interfaceScreensaver, SIGNAL(unlock()), this, SLOT(onUnlockStatus())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::onConfigurationChanged(QString key) { if (key == "systemFontSize") { m_loginOptsWidget->updateUIStatus(false); fontSize = settings->get("system-font-size").toInt(); } if (key == "iconThemeName") { setIcon(app_IconName); } if (key == "styleName") { QPalette pe; if (no_changes) { pe.setColor(QPalette::Text, Qt::red); m_labelTip->setPalette(pe); } else { QColor color = palette().color(QPalette::Text); QPalette pal(this->palette()); pal.setColor(QPalette::Text, QColor(color)); m_labelTip->setPalette(pal); } } } void MainWindow::restart_bio_identify() { DeviceInfoPtr device = bioDevices.getDefaultDevice(getUid(userName)); if (device) { m_loginOptsWidget->startAuth(device, getUid(userName)); setMessage(tr("Please enter your password or enroll your fingerprint ")); } } void MainWindow::closeEvent(QCloseEvent *event) { if (m_loginOptsWidget) { m_loginOptsWidget->stopAuth(); } m_failMap.clear(); emit canceled(); return kdk::KDialog::closeEvent(event); } void MainWindow::setUkeyTypeTip(QString text) { QString textTip = text; if (!textTip.isEmpty()) { QPalette pe; pe.setColor(QPalette::Text, Qt::red); ui->ukeyMessage->setPalette(pe); ui->ukeyMessage->setText(textTip); ui->ukeyMessage->setToolTip(text); ui->ukeyMessage->show(); } else { ui->ukeyMessage->hide(); } } void MainWindow::startLoadingUkey() { m_loadingPixmap = QIcon::fromTheme("ukui-loading-0-symbolic").pixmap(27, 27); ui->loadingUkeyBtn->setIcon(m_loadingPixmap); ui->loadingUkeyBtn->setIconSize(QSize(27, 27)); ui->loadingUkeyWidget->adjustSize(); ui->cmbUsers->hide(); ui->widgetUkeyAuth->hide(); ui->lePassword->hide(); ui->widgetPasswdAuth->hide(); isLoadingUkey = true; ui->loadingUkeyWidget->show(); if (!m_loadingTimer) { m_loadingTimer = new QTimer(this); m_loadingTimer->setInterval(150); connect(m_loadingTimer, &QTimer::timeout, this, &MainWindow::updateLoadingPixmap); } m_loadingTimer->start(); } void MainWindow::stopLoadingUkey() { isLoadingUkey = false; if (m_loadingTimer) { m_loadingTimer->stop(); } ui->loadingUkeyWidget->hide(); // ui->cmbUsers->show(); // ui->widgetUkeyAuth->show(); } void MainWindow::updateLoadingPixmap() { QMatrix matrix; matrix.rotate(90.0); m_loadingPixmap = QtPixmapCompat::transformedPixmap(m_loadingPixmap, matrix, Qt::FastTransformation); ui->loadingUkeyBtn->setIcon(QIcon(m_loadingPixmap)); } void MainWindow::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QStyleOption *option = new QStyleOption(); QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QPainterPath rectPath; rectPath.addRoundedRect(this->rect().adjusted(0, 0, 0, 0), 0, 0); // 画一个黑底 QPixmap pixmap(this->rect().size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHint(QPainter::Antialiasing); pixmapPainter.setPen(Qt::transparent); pixmapPainter.setBrush(QColor(0, 0, 0, 100)); pixmapPainter.drawPath(rectPath); pixmapPainter.end(); // 模糊这个黑底 QImage img = pixmap.toImage(); qt_blurImage(img, 10, false, false); // 挖掉中心 pixmap = QPixmap::fromImage(img); QPainter pixmapPainter2(&pixmap); pixmapPainter2.setRenderHint(QPainter::Antialiasing); pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear); pixmapPainter2.setPen(Qt::transparent); pixmapPainter2.setBrush(Qt::transparent); pixmapPainter2.drawPath(rectPath); // 绘制阴影 p.drawPixmap(this->rect(), pixmap, pixmap.rect()); // 绘制一个背景 p.save(); p.fillPath(rectPath, option->palette.color(QPalette::Base)); p.restore(); } bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (obj == ui->lePassword) { if (event->type() == QEvent::KeyPress) { // ç¦�æ­¢å¤�制粘贴功能。 QKeyEvent *keyEvent = static_cast(event); if (keyEvent->matches(QKeySequence::Copy) || keyEvent->matches(QKeySequence::Cut) || keyEvent->matches(QKeySequence::Paste)) { event->ignore(); return true; } } if (event->type() == QEvent::MouseButtonRelease) { // ç¦�用鼠标中键 QMouseEvent *mouseevent = static_cast(event); #if QT_VERSION_MAJOR == 6 if (mouseevent->button() == Qt::MiddleButton) { #else if (mouseevent->button() == Qt::MidButton) { #endif event->ignore(); return true; } } } return kdk::KDialog::eventFilter(obj, event); } void MainWindow::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: { break; } default: { kdk::KDialog::keyPressEvent(event); break; } } } /*** main ***/ void MainWindow::on_cmbUsers_currentTextChanged(const QString &userName) { qDebug() << "user changed to " << userName; m_loginOptsWidget->stopAuth(); if (m_bioTimer && m_bioTimer->isActive()) m_bioTimer->stop(); authMode = UNDEFINED; QList accountUsers = users->getUsers(); this->userName = userName; for (UserItem user : accountUsers) { if (user.realName == userName) { this->userName = user.name; } } m_deviceInfo = DeviceInfoPtr(); ui->lblMessage->clear(); ui->lblMessage->setToolTip(""); setMessage(""); isLockingFlg = false; emit userChanged(this->userName); } int MainWindow::enable_biometric_authentication() { char conf_file[] = GET_STR(CONFIG_FILE); FILE *file; char line[1024], is_enable[16]; int i; if ((file = fopen(conf_file, "r")) == NULL) { return 0; } while (fgets(line, sizeof(line), file)) { i = sscanf(line, "EnableAuth=%s\n", is_enable); if (i > 0) { break; } } fclose(file); if (!strcmp(is_enable, "true")) return 1; return 0; } void MainWindow::on_btnDetails_clicked() { /* if(ui->widgetDetails->isHidden()) { ui->widgetDetails->show(); ui->btnDetails->setIcon(QIcon(":/image/assets/arrow_down.svg")); // resize(width(), height() + ui->widgetDetails->height()); } else { ui->widgetDetails->hide(); ui->btnDetails->setIcon(QIcon(":/image/assets/arrow_right.svg")); // resize(width(), height() - ui->widgetDetails->height()); } adjustSize();*/ } void MainWindow::on_btnCancel_clicked() { close(); } void MainWindow::on_btnAuth_clicked() { if (doNotNeedAuth) { emit yesPrompted(); return; } if (ui->widgetUkeyAuth->isVisible()) { on_ukeyPassword_returnPressed(); } else { on_lePassword_returnPressed(); } } void MainWindow::onShowYesPrompt() { doNotNeedAuth = true; ui->widgetPasswdAuth->hide(); ui->cmbUsers->hide(); ui->btnBioAuth->hide(); ui->returnButton->hide(); ui->btnAuth->show(); } void MainWindow::onLockStatus() { // m_loginOptsWidget->stopAuth(); m_loginOptsWidget->lockStatusChanged(true); } void MainWindow::onUnlockStatus() { // m_loginOptsWidget->readDevicesInfo(); m_loginOptsWidget->lockStatusChanged(false); startBioAuth(); } /*** pagePassword ***/ void MainWindow::editIcon() { m_modeButton = new ModeButton(ui->lePassword); m_modeButton->setFocusPolicy(Qt::NoFocus); connect(m_modeButton, &QPushButton::clicked, this, [=]() { if (ui->lePassword->echoMode() == QLineEdit::Password) { ui->lePassword->setEchoMode(QLineEdit::Normal); } else { ui->lePassword->setEchoMode(QLineEdit::Password); } }); QHBoxLayout *layout = new QHBoxLayout(ui->lePassword); layout->addStretch(); layout->addWidget(m_modeButton); layout->setContentsMargins(0, 0, 8, 0); ui->lePassword->setTextMargins(1, 1, 4 + m_modeButton->width(), 1); } void MainWindow::on_ukeyPassword_returnPressed() { if (m_loginOptsWidget && m_deviceInfo) { m_loginOptsWidget->SetExtraInfo(ui->ukeyPassword->text(), "pincode"); m_loginOptsWidget->startAuth(m_deviceInfo, getUid(userName)); } } void MainWindow::on_lePassword_returnPressed() { emit accept(ui->lePassword->text()); ui->btnAuth->hide(); ui->btnLoading->show(); setMessage(""); if (!w_timer) { w_timer = new QTimer(this); w_timer->setInterval(150); connect(w_timer, &QTimer::timeout, this, &MainWindow::updatePixmap); } m_waitingPixmap = QIcon::fromTheme("ukui-loading-0-symbolic").pixmap(24, 24); ui->btnLoading->setIcon(QIcon(m_waitingPixmap)); w_timer->start(); // switchWidget(UNDEFINED); // setMessage(tr("in authentication, please wait...")); hasSendPassword = true; } void MainWindow::on_btnBioAuth_clicked() { emit switchToBiometric(); authMode = BIOMETRIC; } void MainWindow::on_returnButton_clicked() { m_loginOptsWidget->stopAuth(); accept(BIOMETRIC_IGNORE); } /*** end of control's slot ***/ /*** public member ***/ void MainWindow::setIcon(const QString &iconName) { // QIcon::setThemeName("ukui-icon-theme"); app_IconName = iconName; if (!QIcon::hasThemeIcon("ukui-polkit")) { QDir iconsDir("/usr/share/icons"); auto themesList = iconsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); qDebug() << themesList; for (auto theme : themesList) { QIcon::setThemeName(theme); if (QIcon::hasThemeIcon("ukui-polkit")) { qDebug() << theme << "has ukui-polkit icon"; break; } } } QPixmap icon = QIcon::fromTheme("ukui-polkit").pixmap(64, 64); QPixmap actionIcon = QIcon::fromTheme(app_IconName).pixmap(32, 32); QPainter painter; painter.begin(&icon); QRect rect(32, 32, 32, 32); painter.drawPixmap(rect, actionIcon); painter.end(); setWindowIcon(icon); // ui->lblIcon->setPixmap(icon); } void MainWindow::setHeader(const QString &text) { if (is_Mavis) ui->lblHeader->setText(tr("This operation requires the administrator's authorization. " "Please enter your password to allow this operation.")); else ui->lblHeader->setText(text); ui->lblHeader->adjustSize(); ui->lblContent->setText(tr("A program is attempting to perform an action that requires privileges." "It requires authorization to perform the action.")); ui->lblContent->adjustSize(); } void MainWindow::setUsers(const QStringList &usersList) { if (usersList.isEmpty()) return; if (usersList.size() == 1) { UserItem user = users->getUserByName(usersList.at(0)); if (user.realName != "") { userName = user.realName; } else { userName = usersList.at(0); } } QList accountUsers = users->getUsers(); for (QString identifyUser : usersList) { bool isFoundAccount = false; for (UserItem user : accountUsers) { if (identifyUser == user.name) { if (user.realName != "") ui->cmbUsers->addItem(user.realName); else ui->cmbUsers->addItem(user.name); isFoundAccount = true; break; } } if (!isFoundAccount) { ui->cmbUsers->addItem(identifyUser); } } ui->cmbUsers->show(); // ui->cmbUsers->adjustSize(); } /* void MainWindow::setDetails(const QString &subPid, const QString &callerPid, const QString &actionId, const QString &actionDesc, const QString vendorName, const QString vendorUrl) { ui->lblSubjectPid->setText(subPid); ui->lblCallerPid->setText(callerPid); ui->lblActionId->setText(actionId); ui->lblActionDesc->setText(actionDesc); QString vendor = QString("%2").arg(vendorUrl).arg(vendorName); ui->lblVendor->setText(vendor); } */ void MainWindow::setPrompt(const QString &text, bool echo) { QString prompt = text; if (text == "Input Password") { prompt = tr("Input Password"); } else if (text == "Password: " || text == "Password:") { prompt = tr("Password: "); } else if (text == "_Password: ") { prompt = tr("_Password: "); } else if (text == "_Password:") { prompt = tr("_Password:"); } if (!m_timer) { m_timer = new QTimer(this); m_timer->setInterval(200); connect(m_timer, &QTimer::timeout, this, &MainWindow::unlock_countdown); } // qDebug() << "6666"; m_timer->start(); unlock_countdown(); ui->lePassword->clear(); ui->lePassword->setPlaceholderText(prompt); // switchWidget(PASSWORD); } /* 转æ�¢pam英文æ��示,目å‰�转æ�¢çš„å°±3个翻译 Authenticated failed, account locked! Authenticated failed, 1 login attemps left Account locked, 4 minutes left */ QString MainWindow::check_is_pam_message(QString text) { if (text.isEmpty()) { return text; } setlocale(LC_ALL, ""); bindtextdomain("Linux-PAM", "/usr/share/locale"); bind_textdomain_codeset("Linux-PAM", "UTF-8"); textdomain("Linux-PAM"); char *str; QString strTrans = ""; QByteArray ba = text.toLocal8Bit(); // must str = ba.data(); char l_str[1024]; int a, b; // 兼容旧版本翻译,以å�Šé€‚é…�新版本翻译 // 因为ä¸�知é�“什么原因,pamå�‘过æ�¥çš„始终为英文,因此这里主动加载pam的翻译文件,使用gettext获å�–翻译 if (text.contains("attemps", Qt::CaseSensitive) && sscanf(str, "Authenticated failed, %d login attemps left", &a)) snprintf(l_str, 1024, _("Authenticated failed, %d login attemps left"), a); else if ( text.contains("attempts", Qt::CaseSensitive) && sscanf(str, "Authenticated failed, %d login attempts left", &a)) snprintf(l_str, 1024, _("Authenticated failed, %d login attempts left"), a); else if ( text.contains("attempt", Qt::CaseSensitive) && sscanf(str, "Authenticated failed, %d login attempt left", &a)) snprintf(l_str, 1024, _("Authenticated failed, %d login attempt left"), a); else if (text.contains("days", Qt::CaseSensitive) && sscanf(str, "Account locked, %d days left", &a)) { // 这里的消æ�¯æ˜¯å¤šä¸ªå­—符串拼接起æ�¥çš„,无法在翻译文件中找到对应的å�¥å­�,å�ªèƒ½è‡ªå·±ç¿»è¯‘ strTrans = tr("Account locked,") + QString("%1 ").arg(a) + tr("days left"); return strTrans; } else if (text.contains("hours", Qt::CaseSensitive) && sscanf(str, "Account locked, %d hours left", &a)) { strTrans = tr("Account locked,") + QString("%1 ").arg(a) + tr("hours left"); return strTrans; } else if (text.contains("minutes", Qt::CaseSensitive) && sscanf(str, "Account locked, %d minutes left", &a)) { strTrans = tr("Account locked,") + QString("%1 ").arg(a) + tr("minutes left"); return strTrans; } else if (text.contains("seconds", Qt::CaseSensitive) && sscanf(str, "Account locked, %d seconds left", &a)) { strTrans = tr("Account locked,") + QString("%1 ").arg(a) + tr("seconds left"); return strTrans; } else if ( text.contains("Warning: ", Qt::CaseSensitive) && sscanf(str, "Warning: your password will expire in %d day", &a)) { snprintf(l_str, 1024, _("Warning: your password will expire in %d day"), a); } else if ( text.contains("Warning: ", Qt::CaseSensitive) && sscanf(str, "Warning: your password will expire in %d days", &a)) { snprintf(l_str, 1024, _("Warning: your password will expire in %d days"), a); } else { return _(str); } qDebug() << "l_str = " << l_str; return QString(l_str); } void MainWindow::setMessage(const QString &text, situation situat) { if (situat == ERROR) { QPalette pe; pe.setColor(QPalette::Text, Qt::red); ui->lblMessage->setPalette(pe); // ui->lePassword->setStyleSheet("QLineEdit{background-color: palette(Button);" // "border-radius: 6px;border: 1px solid #F3222D;}"); } else if (situat == TRUE) { QColor color = palette().color(QPalette::Text); QPalette pal(this->palette()); pal.setColor(QPalette::Text, QColor(color)); ui->lblMessage->setPalette(pal); } // qDebug()<<"receive:text = "<setInterval(800); connect(m_timer, &QTimer::timeout, this, &MainWindow::unlock_countdown); } m_timer->start(); } else if (text.indexOf("No password received, please input password") != -1) { ui->lblMessage->setText(tr("Password cannot be empty")); ui->lblMessage->setToolTip(tr("Password cannot be empty")); } else { ui->lblMessage->setText(text); ui->lblMessage->setToolTip(text); } // ui->lblMessage->adjustSize(); // ui->widgetPasswdAuth->adjustSize(); // ui->lblMessage->setText(text); } void MainWindow::setAuthResult(bool result, const QString &text) { QString message = text; if (!result && text.isEmpty()) { message = tr("Authentication failed, please try again."); } if (authMode == PASSWORD) { switchWidget(PASSWORD); setMessage(message, ERROR); } else if (authMode == BIOMETRIC) setMessage(message, ERROR); } void MainWindow::clearEdit() { ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); ui->ukeyPassword->setText(""); ui->btnAuth->setDisabled(true); } void MainWindow::switchAuthMode(Mode mode) { if (isbioSuccess) { accept(BIOMETRIC_SUCCESS); return; } int uid = getUid(userName); m_loginOptsWidget->setUser(uid); int count = m_loginOptsWidget->getLoginOptCount(); enableBioAuth = count > 0; if (count < 1) { setLoginTypeTip(tr("Input your password to authentication")); m_loginOptsWidget->hide(); } else { m_loginOptsWidget->show(); m_loginOptsWidget->setEnabled(true); } if (m_loginOptsWidget->getHasUkeyOptions()) { setLoginTypeTip(tr("Input your password to authentication")); m_loginOptsWidget->show(); } switch (mode) { case PASSWORD: { qDebug() << "switch to password"; authMode = mode; if (!enableBioAuth || !receiveBioPAM || useDoubleAuth) { ui->btnBioAuth->hide(); } else { ui->btnBioAuth->show(); } if (isHiddenSwitchButton) { ui->btnBioAuth->hide(); } if (hasSendPassword && authMethod == "otp") { if (checkIsAdmin(userName)) { setLoginTypeTip( tr("Enter the two-factor authentication (2FA) OTP token for the administrator \"%1\"") .arg(userName)); } else { setLoginTypeTip( tr("Enter the two-factor authentication (2FA) OTP dynamic token for the user \"%1\"") .arg(userName)); } ui->cmbUsers->hide(); } else if (hasSendPassword && authMethod == "ukey") { if (checkIsAdmin(userName)) { setLoginTypeTip( tr("Enter the two-factor authentication (2FA) security key for the administrator \"%1\"") .arg(userName)); } else { setLoginTypeTip( tr("Enter the two-factor authentication (2FA) security key for the user \"%1\"").arg(userName)); } ui->cmbUsers->hide(); } } break; case BIOMETRIC: { if (authMode == PASSWORD) { emit accept(BIOMETRIC_IGNORE); isFirstAuth = false; return; } authMode = mode; qDebug() << "switch to biometric"; unlock_countdown(); if (m_deviceInfo) { if (!m_loginOptsWidget->findDeviceById(m_deviceInfo->device_id) || m_loginOptsWidget->isDeviceDisable(m_deviceInfo->device_id)) { m_deviceInfo = DeviceInfoPtr(); } } if (!enableBioAuth) { qDebug() << "It doesn't meet the condition for enabling biometric authentication, switch to password."; emit accept(BIOMETRIC_IGNORE); isFirstAuth = false; return; } else if (authMode == BIOMETRIC) { QString strDeviceName; if (isLoadingUkey) { strDeviceName = m_loginOptsWidget->GetDefaultDevice(uid, UniT_General_Ukey); } else { strDeviceName = m_loginOptsWidget->GetDefaultDevice(uid); } // 如果默认设备为空的è¯�,第一次ä¸�å�¯åŠ¨ç”Ÿç‰©è¯†åˆ«è®¤è¯� if (strDeviceName.isEmpty() && !m_deviceInfo) { qDebug() << "No default device"; emit accept(BIOMETRIC_IGNORE); isFirstAuth = false; return; } // 第一次,获å�–默认设备的设备信æ�¯ï¼Œä¹‹å�Žä½¿ç”¨çš„则是从设备选择窗å�£ä¼ å‡ºçš„设备信æ�¯ if (!m_deviceInfo) { m_deviceInfo = m_loginOptsWidget->findDeviceByName(strDeviceName); } if (!m_deviceInfo) { emit accept(BIOMETRIC_IGNORE); isFirstAuth = false; return; } if (m_failMap.contains(uid) && m_failMap[uid].contains(m_deviceInfo->device_id) && m_failMap[uid][m_deviceInfo->device_id] >= maxFailedTimes) { emit accept(BIOMETRIC_IGNORE); isFirstAuth = false; m_deviceInfo = DeviceInfoPtr(); return; } if (m_deviceInfo && m_loginOptsWidget->isDeviceDisable(m_deviceInfo->device_id)) { emit accept(BIOMETRIC_IGNORE); isFirstAuth = false; m_deviceInfo = DeviceInfoPtr(); return; } if (m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { if (isFirstAuth) { isFirstAuth = false; m_deviceInfo = nullptr; emit accept(BIOMETRIC_IGNORE); return; } switchLoginOptType(LOGINOPT_TYPE_GENERAL_UKEY); stopLoadingUkey(); startBioAuth(); m_loginOptsWidget->setCurrentDevice(m_deviceInfo); m_loginOptsWidget->updateUIStatus(false); return; } isFirstAuth = false; switchLoginOptType(m_loginOptsWidget->convertDeviceType(m_deviceInfo->biotype)); startBioAuth(); emit accept(BIOMETRIC_IGNORE); return; } } break; default: break; } switchWidget(mode); } /*** end of public memeber ***/ /*** private member ***/ uid_t MainWindow::getUid(const QString &userName) { struct passwd *pwd = getpwnam(userName.toStdString().c_str()); if (pwd == NULL) { qWarning() << "getpwnam error: " << strerror(errno); return -1; } return pwd->pw_uid; } void MainWindow::setDoubleAuth(bool val) { useDoubleAuth = val; } void MainWindow::stopDoubleAuth() { // if(useDoubleAuth && widgetBioAuth) // widgetBioAuth->stopAuth(); } void MainWindow::switchWidget(Mode mode) { ui->widgetPasswdAuth->hide(); ui->btnAuth->hide(); ui->btnLoading->hide(); ui->btnAuth->setText(tr("Authenticate")); ui->btnBioAuth->setText(tr("Biometric")); ui->btnCancel->setText(tr("Cancel")); ui->returnButton->setText(tr("Use password")); ui->btnLoading->setDisabled(true); if (is_Mavis) { ui->cmbUsers->setFixedHeight(48); ui->lePassword->setFixedHeight(48); ui->ukeyPassword->setFixedHeight(48); ui->btnAuth->setFixedHeight(48); ui->btnCancel->setFixedHeight(48); } else { ui->cmbUsers->setFixedHeight(36); ui->lePassword->setFixedHeight(36); ui->ukeyPassword->setFixedHeight(36); ui->btnAuth->setFixedHeight(36); ui->btnBioAuth->setFixedHeight(36); ui->btnCancel->setFixedHeight(36); ui->returnButton->setFixedHeight(36); } switch (mode) { case PASSWORD: { setFixedWidth(420); if (m_deviceInfo && m_loginOptsWidget->findDeviceById(m_deviceInfo->device_id)) { switchLoginOptType(m_loginOptsWidget->convertDeviceType(m_deviceInfo->biotype)); } else { switchLoginOptType(LOGINOPT_TYPE_PASSWORD); m_loginOptsWidget->setSelectedPassword(); } // 标题+é—´éš”+内容头+é—´éš”+类型æ��示+é—´éš”+用户列表+é—´éš”+ // (密ç �输入框+é—´éš”+验è¯�æ��示+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/ --仅密ç �æ–¹å¼� // (密ç �输入框+é—´éš”+验è¯�æ��示+é—´éš”+登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/ --密ç �+生物识别 选择密ç � // (登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/ --密ç �+生物识别 选择生物识别 // (ukey加载页+é—´éš”+登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/(ukey认è¯�页+é—´éš”+登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�) // --选择Ukey int height = 40 + 8 + ui->lblHeader->height() + 8 + m_labelTip->height() + 8; switch (m_uCurLoginOptType) { case LOGINOPT_TYPE_PASSWORD: { height += ui->cmbUsers->height() + 8 + ui->lePassword->height() + 8 + ui->lblMessage->height() + 8; } break; case LOGINOPT_TYPE_FACE: case LOGINOPT_TYPE_FINGERPRINT: case LOGINOPT_TYPE_FINGERVEIN: case LOGINOPT_TYPE_IRIS: case LOGINOPT_TYPE_VOICEPRINT: case LOGINOPT_TYPE_QRCODE: { height += ui->cmbUsers->height() + 8; } break; case LOGINOPT_TYPE_GENERAL_UKEY: case LOGINOPT_TYPE_ADVANCED_UKEY: { if (!ui->widgetUkeyAuth->isHidden()) { height += ui->widgetUkeyAuth->height() + 8; } else if (!ui->loadingUkeyWidget->isHidden()) { height += ui->loadingUkeyWidget->height() + 8; } } break; default: break; } if (!m_loginOptsWidget->isHidden()) { height += m_loginOptsWidget->height() + 8; } height += ui->btnAuth->height() + 24; setFixedSize(width(), height); qInfo() << "MainWindow geometry:" << geometry() << height; // m_loginOptsWidget->updateUIStatus(); ui->btnBioAuth->setStyleSheet("QPushButton{font-size:14px;}QPushButton:hover{border:none;color:#3E6CE5;}" "QPushButton:pressed{border:none;}"); ui->btnBioAuth->setFlat(true); ui->btnBioAuth->setText(tr("Biometric")); ui->btnBioAuth->setAttribute(Qt::WA_UnderMouse, false); ui->btnBioAuth->adjustSize(); if (m_uCurLoginOptType == LOGINOPT_TYPE_PASSWORD) { ui->widgetPasswdAuth->show(); ui->lePassword->setFocus(); // ui->lePassword->setAttribute(Qt::WA_InputMethodEnabled, false); if (m_modeButton && m_modeButton->isShowPwd()) { ui->lePassword->setEchoMode(QLineEdit::Normal); } else { ui->lePassword->setEchoMode(QLineEdit::Password); } } ui->btnAuth->show(); ui->btnLoading->hide(); if (w_timer && w_timer->isActive()) { w_timer->stop(); } ui->btnCancel->show(); // ui->lblContent->show(); ui->returnButton->hide(); ui->lblContent->hide(); } break; case BIOMETRIC: setFixedWidth(420); ui->btnCancel->hide(); ui->lblContent->hide(); ui->btnBioAuth->hide(); break; default: break; } // adjustSize(); } void MainWindow::unlock_countdown() { int failed_count = 0; int time_left = 0; int deny = 0; int fail_time = 0; int unlock_time = 0; pam_tally_unlock_time_left(getUid(userName), &failed_count, &time_left, &deny, &fail_time, &unlock_time); // qDebug() << "failed_count:" << failed_count << "time_left:" <= 60) // 请多少分钟å�Žé‡�试 { int nMinuteleft = time_left / 60; if (isLockingFlg == false) { m_nCurLockMin = unlock_time / 60; // 获å�–当å‰�需è¦�é”�定的分钟数 } // 如果当å‰�设置的ä¸�是1miné’Ÿé”�定,那么1min显示æˆ�2min,由2min直接跳到59s || // 剩余分钟数å°�于当å‰�设置的é”�定时间,并且大于1min,自增+1 if ((nMinuteleft == 1 && m_nCurLockMin != 1) || (nMinuteleft > 1 && nMinuteleft < m_nCurLockMin)) { nMinuteleft = nMinuteleft + 1; } setMessage(tr("Please try again in %1 minutes.").arg(nMinuteleft), ERROR); // ui->lblMessage->setToolTip(tr("Please try again in %1 minutes.").arg(nMinute)); ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); ui->btnAuth->setDisabled(true); isLockingFlg = true; setBiometricAuthDisabledStatus(isLockingFlg); return; } else if (time_left > 0 && time_left < 60) // 请多少秒å�Žé‡�试 { char ch[100] = { 0 }; setMessage(tr("Please try again in %1 seconds.").arg(time_left % 60), ERROR); // ui->lblMessage->setToolTip(tr("Please try again in %1 seconds.").arg(time_left%60)); ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); ui->btnAuth->setDisabled(true); isLockingFlg = true; setBiometricAuthDisabledStatus(isLockingFlg); return; } else if (failed_count == 0xFFFF) // è´¦å�·è¢«æ°¸ä¹…é”�定 { ui->lblMessage->setText(tr("Account locked permanently.")); ui->lblMessage->setToolTip(tr("Account locked permanently.")); ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); ui->btnAuth->setDisabled(true); isLockingFlg = true; setBiometricAuthDisabledStatus(isLockingFlg); return; } else { if (ui->lePassword) { ui->lePassword->setDisabled(false); ui->lePassword->setReadOnly(false); ui->lePassword->setFocus(); } if (ui->btnAuth) { ui->btnAuth->setDisabled(false); } if (isLockingFlg) { // setMessage(tr("Authentication failed, please try again."),ERROR); setMessage(""); isLockingFlg = false; setBiometricAuthDisabledStatus(isLockingFlg); } if (m_timer) { m_timer->stop(); } } return; } void MainWindow::root_unlock_countdown() { int failed_count = 0; int time_left = 0; int deny = 0; int fail_time = 0; int unlock_time = 0; pam_tally_root_unlock_time_left(&failed_count, &time_left, &deny, &fail_time, &unlock_time); // qDebug() << "failed_count:" << failed_count << "time_left:" <= 60) // 请多少分钟å�Žé‡�试 { int nMinuteleft = time_left / 60; if (isLockingFlg == false) { m_nCurLockMin = unlock_time / 60; // 获å�–当å‰�需è¦�é”�定的分钟数 } // 如果当å‰�设置的ä¸�是1miné’Ÿé”�定,那么1min显示æˆ�2min,由2min直接跳到59s || // 剩余分钟数å°�于当å‰�设置的é”�定时间,并且大于1min,自增+1 if ((nMinuteleft == 1 && m_nCurLockMin != 1) || (nMinuteleft > 1 && nMinuteleft < m_nCurLockMin)) { nMinuteleft = nMinuteleft + 1; } ui->lblMessage->setText(tr("Please try again in %1 minutes.").arg(nMinuteleft)); ui->lblMessage->setToolTip(tr("Please try again in %1 minutes.").arg(nMinuteleft)); ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); ui->btnAuth->setDisabled(true); isLockingFlg = true; setBiometricAuthDisabledStatus(isLockingFlg); return; } else if (time_left > 0 && time_left < 60) // 请多少秒å�Žé‡�试 { char ch[100] = { 0 }; ui->lblMessage->setText(tr("Please try again in %1 seconds.").arg(time_left % 60)); ui->lblMessage->setToolTip(tr("Please try again in %1 seconds.").arg(time_left % 60)); ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); ui->btnAuth->setDisabled(true); isLockingFlg = true; setBiometricAuthDisabledStatus(isLockingFlg); return; } else if (failed_count == 0xFFFF) // è´¦å�·è¢«æ°¸ä¹…é”�定 { ui->lblMessage->setText(tr("Account locked permanently.")); ui->lblMessage->setToolTip(tr("Account locked permanently.")); ui->lePassword->setText(""); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(false); ui->btnAuth->setDisabled(true); isLockingFlg = true; setBiometricAuthDisabledStatus(isLockingFlg); return; } else { if (ui->lePassword) { ui->lePassword->setDisabled(false); ui->lePassword->setReadOnly(false); ui->lePassword->setFocus(); } if (ui->btnAuth) { ui->btnAuth->setDisabled(false); } if (isLockingFlg) { // setMessage(tr("Authentication failed, please try again."),ERROR); setMessage(""); isLockingFlg = false; setBiometricAuthDisabledStatus(isLockingFlg); } m_timer->stop(); } return; } void MainWindow::setBiometricAuthDisabledStatus(bool locked) { if (locked) { if (m_loginOptsWidget) { m_loginOptsWidget->stopAuth(); m_loginOptsWidget->setAllDeviceDisable(true); if (m_bioTimer && m_bioTimer->isActive()) m_bioTimer->stop(); } if (m_deviceInfo && m_deviceInfo->biotype == BIOTYPE_FACE) { QImage imgFailed; m_loginOptsWidget->setFaceImg(imgFailed, 1); } else if (m_deviceInfo && m_deviceInfo->biotype == REMOTE_QRCODE_TYPE) { QImage nullImage; m_loginOptsWidget->setQRCode(nullImage); } } else { if (m_loginOptsWidget) { if (m_deviceInfo) { m_loginOptsWidget->startAuth(m_deviceInfo, getUid(userName)); } m_loginOptsWidget->setAllDeviceDisable(false); } } } void MainWindow::onRespondUkey(const QString &text) { if (m_loginOptsWidget) { m_loginOptsWidget->SetExtraInfo(text, "pincode"); } } void MainWindow::switchLoginOptType(unsigned uLoginOptType) { switch (uLoginOptType) { case LOGINOPT_TYPE_PASSWORD: { // m_loginOptsWidget->hide(); ui->lePassword->show(); ui->cmbUsers->show(); ui->widgetPasswdAuth->show(); ui->widgetUkeyAuth->hide(); ui->ukeyPassword->clearFocus(); ui->loadingUkeyWidget->hide(); setFocusProxy(ui->lePassword); ui->cmbUsers->show(); if (hasSendPassword && (authMethod == "ukey" || authMethod == "otp")) { ui->cmbUsers->hide(); } m_loginOptsWidget->stopBioWaiting(); } break; case LOGINOPT_TYPE_FACE: case LOGINOPT_TYPE_FINGERPRINT: case LOGINOPT_TYPE_IRIS: case LOGINOPT_TYPE_VOICEPRINT: case LOGINOPT_TYPE_FINGERVEIN: case LOGINOPT_TYPE_QRCODE: { switch (uLoginOptType) { case LOGINOPT_TYPE_FINGERPRINT: case LOGINOPT_TYPE_IRIS: case LOGINOPT_TYPE_VOICEPRINT: case LOGINOPT_TYPE_FINGERVEIN: { m_loginOptsWidget->startBioWaiting(uLoginOptType); } break; default: m_loginOptsWidget->stopBioWaiting(); break; } // 延迟检查错误状æ€� m_isNetworkErr = false; QTimer::singleShot(500, this, [&, this]() { if (!this->m_isNetworkErr) { m_loginOptsWidget->setQRCodeMsg(""); } }); ui->lePassword->show(); ui->widgetUkeyAuth->hide(); ui->loadingUkeyWidget->hide(); ui->ukeyPassword->clearFocus(); setFocusProxy(ui->lePassword); ui->cmbUsers->show(); ui->widgetPasswdAuth->hide(); } break; case LOGINOPT_TYPE_GENERAL_UKEY: { ui->lePassword->hide(); ui->cmbUsers->hide(); if (m_deviceInfo) { stopLoadingUkey(); ui->widgetUkeyAuth->show(); } else { startLoadingUkey(); } setFocusProxy(ui->ukeyPassword); ui->ukeyPassword->setFocusPolicy(Qt::StrongFocus); ui->ukeyPassword->setFocus(); ui->widgetPasswdAuth->hide(); m_loginOptsWidget->stopBioWaiting(); } break; default: return; } qDebug() << "CurOptType:" << uLoginOptType; if (m_deviceInfo && m_failMap.contains(getUid(userName)) && m_failMap[getUid(userName)].contains(m_deviceInfo->device_id) && m_failMap[getUid(userName)][m_deviceInfo->device_id] >= maxFailedTimes) { if (m_deviceInfo->biotype == BIOTYPE_FACE) { QImage imgFailed; m_loginOptsWidget->setFaceImg(imgFailed, 1); } no_changes = true; if (m_deviceInfo->biotype == REMOTE_QRCODE_TYPE) { setLoginTypeTip(tr("Failed to verify %1, please enter password to unlock") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype))); } else if (m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { setUkeyTypeTip(tr("Failed to verify %1, please enter password to unlock") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype))); } else { setLoginTypeTip(tr("Unable to verify %1, please enter password to unlock") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype))); m_loginOptsWidget->stopBioWaiting(true); } m_loginOptsWidget->setDeviceDisable(m_deviceInfo->device_id, true); } else { no_changes = false; if (uLoginOptType != m_uCurLoginOptType || (m_deviceInfo && m_deviceInfo->device_id != m_nLastDeviceId)) { switch (uLoginOptType) { case LOGINOPT_TYPE_PASSWORD: { setLoginTypeTip(tr("Input your password to authentication")); } break; case LOGINOPT_TYPE_FACE: { setLoginTypeTip(tr("Facial recognition to authorization")); } break; case LOGINOPT_TYPE_FINGERPRINT: { setLoginTypeTip(tr("Fingerprint recognition to authorization")); } break; case LOGINOPT_TYPE_VOICEPRINT: { setLoginTypeTip(tr("Voiceprint recognition to authorization")); } break; case LOGINOPT_TYPE_FINGERVEIN: { setLoginTypeTip(tr("Finger veins recognition to authorization")); } break; case LOGINOPT_TYPE_IRIS: { setLoginTypeTip(tr("Iris recognition to authorization")); } break; case LOGINOPT_TYPE_QRCODE: { QString strDrivName = tr("wechat"); if (m_deviceInfo && m_deviceInfo->device_shortname != "wechat_driver") { strDrivName = m_deviceInfo->device_shortname; } setLoginTypeTip(tr("Use the bound %1 scanning code to authorization").arg(strDrivName)); } break; case LOGINOPT_TYPE_GENERAL_UKEY: { setLoginTypeTip(""); } break; default: return; } } } if (m_deviceInfo) { m_nLastDeviceId = m_deviceInfo->device_id; } else { m_nLastDeviceId = -1; } m_uCurLoginOptType = uLoginOptType; m_loginOptsWidget->updateUIStatus(true, m_uCurLoginOptType); } void MainWindow::setLoginTypeTip(QString strLoginTypeTip) { m_strLoginTypeTip = strLoginTypeTip; if (m_strLoginTypeTip.isEmpty()) { m_labelTip->hide(); } else { QPalette pe; if (no_changes) { pe.setColor(QPalette::Text, Qt::red); m_labelTip->setPalette(pe); } else { QColor color = palette().color(QPalette::Text); QPalette pal(this->palette()); pal.setColor(QPalette::Text, QColor(color)); m_labelTip->setPalette(pal); } m_labelTip->setText(m_strLoginTypeTip); m_labelTip->show(); } } void MainWindow::startBioAuthDelay() { if (m_deviceInfo) { if (m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { } else { m_loginOptsWidget->startAuth(m_deviceInfo, getUid(userName)); } switchLoginOptType(m_loginOptsWidget->convertDeviceType(m_deviceInfo->biotype)); } else { switchLoginOptType(LOGINOPT_TYPE_PASSWORD); } m_bioTimer->stop(); } void MainWindow::startBioAuth(unsigned uTimeout) { m_loginOptsWidget->stopAuth(); if (m_deviceInfo && m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { switchLoginOptType(m_loginOptsWidget->convertDeviceType(m_deviceInfo->biotype)); } if (!m_bioTimer) { m_bioTimer = new QTimer(this); connect(m_bioTimer, SIGNAL(timeout()), this, SLOT(startBioAuthDelay())); } ui->lblMessage->clear(); ui->lblMessage->setToolTip(""); m_bioTimer->start(uTimeout); } void MainWindow::onUpdateBioAuthMsg(QString strMsg) { setMessage(strMsg, TRUE); } void MainWindow::updatePixmap() { ui->btnAuth->hide(); ui->btnAuth->setDisabled(true); ui->btnLoading->show(); ui->lePassword->setDisabled(true); ui->lePassword->setReadOnly(true); QMatrix matrix; matrix.rotate(90.0); m_waitingPixmap = QtPixmapCompat::transformedPixmap(m_waitingPixmap, matrix, Qt::FastTransformation); ui->btnLoading->setIcon(m_waitingPixmap); } void MainWindow::onUpdateWndSize(unsigned uLoginOptType, unsigned uLoginOptSize) { ui->lblContent->hide(); ui->lblHeader->adjustSize(); // 标题+é—´éš”+内容头+é—´éš”+类型æ��示+é—´éš”+用户列表+é—´éš”+ // (密ç �输入框+é—´éš”+验è¯�æ��示+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/ --仅密ç �æ–¹å¼� // (密ç �输入框+é—´éš”+验è¯�æ��示+é—´éš”+登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/ --密ç �+生物识别 选择密ç � // (登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/ --密ç �+生物识别 选择生物识别 // (ukey加载页+é—´éš”+登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�)/(ukey认è¯�页+é—´éš”+登录选项+é—´éš”+授æ�ƒæŒ‰é’®+è¾¹è·�) // --选择Ukey int height = 40 + 8 + ui->lblHeader->height() + 8 + m_labelTip->height() + 8; switch (m_uCurLoginOptType) { case LOGINOPT_TYPE_PASSWORD: { height += ui->cmbUsers->height() + 8 + ui->lePassword->height() + 8 + ui->lblMessage->height() + 8; } break; case LOGINOPT_TYPE_FACE: case LOGINOPT_TYPE_FINGERPRINT: case LOGINOPT_TYPE_FINGERVEIN: case LOGINOPT_TYPE_IRIS: case LOGINOPT_TYPE_VOICEPRINT: case LOGINOPT_TYPE_QRCODE: { height += ui->cmbUsers->height() + 8; } break; case LOGINOPT_TYPE_GENERAL_UKEY: case LOGINOPT_TYPE_ADVANCED_UKEY: { if (!ui->widgetUkeyAuth->isHidden()) { height += ui->widgetUkeyAuth->height() + 8; } else if (!ui->loadingUkeyWidget->isHidden()) { height += ui->loadingUkeyWidget->height() + 8; } } break; default: break; } if (!m_loginOptsWidget->isHidden()) { height += m_loginOptsWidget->height() + 8; } height += ui->btnAuth->height() + 24; setFixedSize(width(), height); qInfo() << "MainWindow geometry update:" << geometry() << height; } void MainWindow::setEditInputMethod(bool bEnable) { qDebug() << "setEditInputMethod:" << bEnable; if (bEnable) { ui->lePassword->setAttribute(Qt::WA_InputMethodEnabled, true); } else { ui->lePassword->setAttribute(Qt::WA_InputMethodEnabled, false); } } void MainWindow::setCurProject(bool isMavis) { is_Mavis = isMavis; } void MainWindow::onOptionSelected(unsigned uCurLoginOptType, const DeviceInfoPtr &deviceInfo) { isLoadingUkey = false; if (uCurLoginOptType == LOGINOPT_TYPE_GENERAL_UKEY) { stopLoadingUkey(); } if (uCurLoginOptType == LOGINOPT_TYPE_PASSWORD) { switchLoginOptType(uCurLoginOptType); if (m_loginOptsWidget) { m_loginOptsWidget->stopAuth(); } m_deviceInfo = nullptr; authMode = PASSWORD; emit restartAuth(); return; } if (uCurLoginOptType != LOGINOPT_TYPE_GENERAL_UKEY && !deviceInfo) return; if (deviceInfo) qDebug() << "device changed: " << deviceInfo->biotype; if (deviceInfo && m_failMap[getUid(userName)][deviceInfo->device_id] >= maxFailedTimes) { qDebug() << "Failed MAX!!"; return; } if (uCurLoginOptType == LOGINOPT_TYPE_GENERAL_UKEY && !deviceInfo) { isLoadingUkey = true; startLoadingUkey(); m_loginOptsWidget->updateUkeyUIStatus(LOGINOPT_TYPE_GENERAL_UKEY); } else if (uCurLoginOptType == LOGINOPT_TYPE_GENERAL_UKEY && deviceInfo) { stopLoadingUkey(); m_loginOptsWidget->updateUkeyUIStatus(LOGINOPT_TYPE_GENERAL_UKEY); } if (deviceInfo == m_deviceInfo) { return; } if (uCurLoginOptType != LOGINOPT_TYPE_GENERAL_UKEY && deviceInfo == m_deviceInfo) { return; } if (m_bioTimer) m_bioTimer->stop(); m_deviceInfo = deviceInfo; switchLoginOptType(uCurLoginOptType); if (!isbioSuccess && m_deviceInfo) { startBioAuth(); } } void MainWindow::onNotifyOptionsChanged(unsigned uOptionsCount) { if (uOptionsCount > 0) { m_loginOptsWidget->show(); } else { // m_loginOptsWidget->hide(); } if (m_deviceInfo && m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { stopLoadingUkey(); } if (!m_deviceInfo || !m_loginOptsWidget->findDeviceById(m_deviceInfo->device_id) || m_loginOptsWidget->isDeviceDisable(m_deviceInfo->device_id)) { m_loginOptsWidget->stopAuth(); if (authMode != UNDEFINED) { authMode = UNDEFINED; emit switchToBiometric(); } } } void MainWindow::onLoginOptionsAuthCompleted(uid_t uid, bool ret, int nStatus) { qDebug() << "biometric authentication complete: " << uid << ret << nStatus; if (m_deviceInfo && m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY && ui->widgetUkeyAuth->isVisible()) { ui->ukeyPassword->setText(""); } if (uid == getUid(userName) && ret) { isbioSuccess = true; emit switchToBiometric(); authMode = UNDEFINED; } else { if (nStatus == 5 && m_deviceInfo) { if (w_timer && w_timer->isActive()) w_timer->stop(); QImage imgFailed; m_loginOptsWidget->setFaceImg(imgFailed, 2); return; } else if (nStatus >= 2 && nStatus != 5) if (nStatus >= 2) { if (m_deviceInfo) { uid_t curUid = getUid(userName); if (m_failMap.contains(curUid) && m_failMap[curUid].contains(m_deviceInfo->device_id)) { m_failMap[curUid][m_deviceInfo->device_id] = m_failMap[curUid][m_deviceInfo->device_id] + 1; } else { m_failMap[curUid][m_deviceInfo->device_id] = 1; } qDebug() << "Failed count:" << m_failMap[curUid][m_deviceInfo->device_id] << ",Max:" << maxFailedTimes; if (m_deviceInfo->biotype == BIOTYPE_FACE) { QImage imgFailed; m_loginOptsWidget->setFaceImg(imgFailed, 1); } if (m_failMap[curUid][m_deviceInfo->device_id] >= maxFailedTimes) { no_changes = true; if (m_deviceInfo->biotype == REMOTE_QRCODE_TYPE) { setLoginTypeTip(tr("Failed to verify %1, please enter password to unlock") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype))); QImage nullImage; m_loginOptsWidget->setQRCode(nullImage); } else if (m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { ui->ukeyPassword->setReadOnly(true); setUkeyTypeTip(tr("Unable to verify %1, please enter password to unlock") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype))); } else { setLoginTypeTip(tr("Unable to verify %1, please enter password to unlock") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype))); m_loginOptsWidget->stopBioWaiting(true); } m_loginOptsWidget->setDeviceDisable(m_deviceInfo->device_id, true); useDoubleAuth = false; return; } no_changes = false; if (m_deviceInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { setUkeyTypeTip(tr("Failed to verify %1, you still have %2 verification opportunities") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype)) .arg(maxFailedTimes - m_failMap[curUid][m_deviceInfo->device_id])); } else { setLoginTypeTip(tr("Failed to verify %1, you still have %2 verification opportunities") .arg(BioDevices::bioTypeToString_tr(m_deviceInfo->biotype)) .arg(maxFailedTimes - m_failMap[curUid][m_deviceInfo->device_id])); } } } if (!isbioSuccess) { // dbus error if (nStatus == -1) { qDebug() << "Biometric dbus error:" << authMode; } if (m_uCurLoginOptType == LOGINOPT_TYPE_QRCODE && nStatus == 1) { m_isNetworkErr = true; m_loginOptsWidget->setQRCodeMsg(tr("Abnormal network")); startBioAuth(10000); } else if (m_uCurLoginOptType == LOGINOPT_TYPE_QRCODE && nStatus == -4) { m_isNetworkErr = true; m_loginOptsWidget->setQRCodeMsg(tr("Acquisition failure")); startBioAuth(10000); } else { startBioAuth(); } if (nStatus >= 2 && m_deviceInfo) { if (m_deviceInfo->biotype == BIOTYPE_FACE) { QImage imgFailed; m_loginOptsWidget->setFaceImg(imgFailed, 1); } } } } } void MainWindow::updateAuthMethod() { authMethod = getAuthMethod(); } QString MainWindow::getAuthMethod() { QDBusInterface interface( "com.kylin.pwdless.daemon", "/", "com.kylin.pwdless.daemon", QDBusConnection::systemBus(), this); if (!interface.isValid()) { return ""; } QDBusMessage result = interface.call(QStringLiteral("mfaStatus")); if (result.type() == QDBusMessage::ErrorMessage) { qWarning() << "mfaStatus error:" << result.errorMessage(); return ""; } int ret = result.arguments().at(0).toInt(); QString method = result.arguments().at(1).toString(); if (ret == 0) return ""; else return method; } void MainWindow::resetSendPassword() { hasSendPassword = false; } bool MainWindow::checkIsAdmin(QString userName) { int ngroups = 512; struct passwd *pw; struct group *gr; gid_t groups[512]; pw = getpwnam(userName.toLocal8Bit().data()); if (pw == NULL) { qDebug() << userName << "is not exists"; return false; } if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1) { qDebug() << userName << "get group failed"; return false; } for (size_t j = 0; j < ngroups; j++) { gr = getgrgid(groups[j]); if (gr != NULL) { if (strcmp("sudo", gr->gr_name) == 0) return true; } } return false; } /*** end of private member ***/ ukui-biometric-auth/polkit-agent/src/types.h0000664000175000017500000000406215167732630020105 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef TYPES_H #define TYPES_H /* https://www.narf.ssji.net/~shtrom/wiki/projets/gnomescreensavernosession */ enum SessionStatus { SESSION_AVAILABLE = 0, SESSION_INVISIBLE = 1, SESSION_BUSY = 2, SESSION_IDLE = 3 }; enum ScreenStatus { UNDEFINED = 0x00, SCREEN_SAVER = 0x01, SCREEN_LOCK = 0x02 }; #define SM_DBUS_SERVICE "org.gnome.SessionManager" #define SM_DBUS_PATH "/org/gnome/SessionManager/Presence" #define SM_DBUS_INTERFACE "org.gnome.SessionManager.Presence" #define DM_DBUS_SERVICE "org.freedesktop.DisplayManager" #define DM_DBUS_PATH "/org/freedesktop/DisplayManager" #define DM_DBUS_INTERFACE "org.freedesktop.DisplayManager" #define DM_SEAT_INTERFACE "org.freedesktop.DisplayManager.Seat" #define ACT_DBUS_SERVICE "org.freedesktop.Accounts" #define ACT_DBUS_PATH "/org/freedesktop/Accounts" #define ACT_DBUS_INTERFACE "org.freedesktop.Accounts" #define ACT_USER_INTERFACE "org.freedesktop.Accounts.User" #define DBUS_PROP_INTERFACE "org.freedesktop.DBus.Properties" #define SS_DBUS_SERVICE "org.ukui.ScreenSaver" #define SS_DBUS_PATH "/" #define SS_DBUS_INTERFACE "org.ukui.ScreenSaver" #define BIO_ERROR -1 #define BIO_FAILED 0 #define BIO_SUCCESS 1 #define BIO_IGNORE 2 #define BIOMETRIC_PAM "BIOMETRIC_PAM" #define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" #define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS" #define BIOMETRIC_FAILED "BIOMETRIC_FAILED" #endif // TYPES_H ukui-biometric-auth/polkit-agent/src/kalabel.h0000664000175000017500000000213515167732630020333 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef KALABEL_H #define KALABEL_H #include class KALabel : public QLabel { Q_OBJECT public: KALabel(QWidget *parent = nullptr); KALabel(QString strText, QWidget *parent = nullptr); QString getElidedText(QFont font, int width, QString strInfo); public slots: void setText(const QString &); protected: void paintEvent(QPaintEvent *event); private: QString m_strText; }; #endif // KALABEL_H ukui-biometric-auth/polkit-agent/src/modeButton.cpp0000664000175000017500000001154315167732630021416 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "modeButton.h" #include #include #include #include #include ModeButton::ModeButton(QWidget *parent) : QPushButton(parent) { m_strIcon = ""; m_strText = ""; this->setFlat(true); initUI(); initStyleTheme(); } ModeButton::ModeButton(QString strIcon, QWidget *parent) : QPushButton(parent) { m_strIcon = strIcon; this->setFlat(true); initUI(); initStyleTheme(); } ModeButton::~ModeButton() { if (m_styleSettings) { delete m_styleSettings; m_styleSettings = nullptr; } } void ModeButton::initUI() { installEventFilter(this); setModeIcon(); setFixedSize(QSize(24, 24)); setModeIcon(); setCursor(Qt::ArrowCursor); setStyleSheet("QPushButton::pressed{border:none;background-color:transparent}" "QPushButton::hover::!pressed{border:none;background-color:transparent}"); connect(this, &QPushButton::clicked, this, [=](){ if (!pwdShow) { pwdShow = true; setModeIcon(); } else { pwdShow = false; setModeIcon(); } }); } void ModeButton::initStyleTheme() { const QByteArray idd("org.ukui.style"); if(QGSettings::isSchemaInstalled(idd)) { m_styleSettings = new QGSettings(idd); } if (m_styleSettings) { connect(m_styleSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { auto styleNameValue = m_styleSettings->get("styleName"); if (styleNameValue.isValid()) { m_strThemeName = styleNameValue.toString(); setModeIcon(); } } }); auto styleNameValue = m_styleSettings->get("styleName"); if (styleNameValue.isValid()) { m_strThemeName = styleNameValue.toString(); } } } void ModeButton::setModeIcon() { QIcon icon; QPixmap pixmap; if(pwdShow){ icon = QIcon::fromTheme("ukui-eye-display-symbolic"); pixmap = icon.pixmap(QSize(24,24)); } else{ icon = QIcon::fromTheme("ukui-eye-hidden-symbolic"); pixmap = icon.pixmap(QSize(24,24)); } if(m_isHover) pixmap = drawSymbolicColoredPixmap(pixmap, "white"); else pixmap = drawSymbolicColoredPixmap(pixmap, "gray"); if(m_strThemeName == "ukui-dark" || m_strThemeName == "ukui-black") this->setIcon(pixmap); else this->setIcon(icon); } bool ModeButton::eventFilter(QObject *obj, QEvent *event) { if(obj == this){ if(event->type() == QEvent::Enter){ m_isHover = true; setModeIcon(); } else if(event->type() == QEvent::Leave){ m_isHover = false; setModeIcon(); } } return QPushButton::eventFilter(obj, event); } QPixmap ModeButton::drawSymbolicColoredPixmap(QPixmap &source, QString cgColor) { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if ( "white" == cgColor) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else if( "black" == cgColor) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } else if ("gray"== cgColor) { color.setRed(152); color.setGreen(163); color.setBlue(164); img.setPixelColor(x, y, color); } else if ("blue" == cgColor){ color.setRed(61); color.setGreen(107); color.setBlue(229); img.setPixelColor(x, y, color); } else { return source; } } } } return QPixmap::fromImage(img); } bool ModeButton::isShowPwd() { return pwdShow; } ukui-biometric-auth/polkit-agent/src/PolkitAgent.cpp0000664000175000017500000000473615167732644021532 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include "PolkitListener.h" #include "generic.h" #include "sessionmanager.h" #include "biodevices.h" #include bool enableDebug; QString logPrefix; int main(int argc, char *argv[]) { enableDebug = true; logPrefix = "[ukui-polkit]:"; //qInstallMessageHandler(outputMessage); initUkuiLog4qt("ukui-polkit"); qDebug() << "Polkit Agent Started"; #if(QT_VERSION>=QT_VERSION_CHECK(5,6,0)) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif QApplication agent(argc, argv); QString locale = QLocale::system().name(); qDebug() << "Language: " <. * **/ #include "pam-tally.h" #include #include #include #include #include #include #include #include #include #include char shm_tally_real[128]; #define FILE_MODE (S_IRUSR | S_IWUSR) #define CONFIG_FILE "/usr/share/lightdm/lightdm.conf.d/96-kylin-setting.conf" struct tallylog { char fail_line[52]; /* rhost or tty of last failure */ uint16_t reserved; /* reserved for future use */ uint16_t fail_cnt; /* failures since last success */ uint64_t fail_time; /* time of last failure */ }; static int get_is_open_other_authentication() { char buf[128]; FILE *config_file; if( (config_file = fopen(CONFIG_FILE, "r")) == NULL) { return 0; } int open_other_authentication = 0; while(fgets(buf, sizeof(buf), config_file)) { if(strnlen(buf,1024) == 0 || buf[0] == '#') { memset(buf, sizeof(buf), 0); continue; } if(buf[strnlen(buf,1024)-1] == '\n') buf[strnlen(buf,1024)-1] = '\0'; char *p = strchr(buf, '='); if(!p) continue; *p = '\0'; size_t len = strnlen(buf,1024); if(len == 0) continue; //去掉=之å‰�的空格 while(len--) if(buf[len] == ' ' || buf[len] == '\t') buf[len] = '\0'; if(strcmp(buf, "open-other-authentication") != 0) continue; p++; len = strnlen(p,1024); if(len == 0) break; //去掉等å�·ä¹‹å�Žçš„空格 while(*p == ' ' || *p == '\t') { p++; len--; } //去掉尾部空格 while(len--) if(*(p+len) == ' ' || *(p+len) == '\t') *(p+len) = '\0'; if(*p == '0') break; if(*p == '1') { open_other_authentication = 1; break; } } fclose(config_file); return open_other_authentication; } static int get_pam_tally(int *deny, int *unlock_time , int *root_unlock_time) { char buf[128]; FILE *auth_file = NULL; if( (auth_file = fopen("/etc/pam.d/common-auth", "r")) == NULL) return -1; while(fgets(buf, sizeof(buf), auth_file)) { if(strnlen(buf,1024) == 0 || buf[0] == '#') continue; if(!strstr(buf, "deny")) continue; char *ptr = strtok(buf, " \t"); while(ptr) { if(strncmp(ptr, "deny=", 5)==0){ sscanf(ptr, "deny=%d", deny); } if(strncmp(ptr, "unlock_time=", 12)==0){ sscanf(ptr, "unlock_time=%d", unlock_time); } if(strncmp(ptr, "root_unlock_time=", 17)==0){ sscanf(ptr, "root_unlock_time=%d", root_unlock_time); } ptr = strtok(NULL, " \t"); } fclose(auth_file); auth_file = NULL; return 1; } fclose(auth_file); auth_file = NULL; return 0; } static void set_shm_tally_real() { snprintf(shm_tally_real, sizeof(shm_tally_real), "%s_%d", SHM_TALLY, getuid()); } int pam_tally_init() { int fd; int deny = 0, unlock_time = 0 , root_unlock_time = 0; pam_tally *tally_ptr; set_shm_tally_real(); printf("shm path : %s\n", shm_tally_real); shm_unlink(shm_tally_real); if(get_is_open_other_authentication()) { return 0; } if(!get_pam_tally(&deny, &unlock_time,&root_unlock_time)) { return 0; } if(deny <= 0) deny = 0; if(unlock_time <= 0) unlock_time = 0; if( (fd = shm_open(shm_tally_real, O_RDWR | O_CREAT, FILE_MODE)) == -1) { printf("shm_open error: %s\n", strerror(errno)); return -1; } ftruncate(fd, sizeof(pam_tally)); if( (tally_ptr = mmap(NULL, sizeof(pam_tally), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); return -1; } close(fd); tally_ptr->deny = deny; tally_ptr->unlock_time = unlock_time; tally_ptr->failed = 0; tally_ptr->lock_start_time = 0; tally_ptr->root_unlock_time = root_unlock_time; return 1; } static pam_tally* pam_tally_memory() { int fd; pam_tally *tally_ptr; set_shm_tally_real(); if( (fd = shm_open(shm_tally_real, O_RDWR, FILE_MODE)) == -1) { return NULL; } if( (tally_ptr = mmap(NULL, sizeof(pam_tally), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); return NULL; } close(fd); return tally_ptr; } int pam_tally_is_enbled() { int fd; set_shm_tally_real(); if( (fd = shm_open(shm_tally_real, O_RDONLY, FILE_MODE)) == -1) { printf("shm_open error: %s\n", strerror(errno)); close(fd); return 0; } pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL){ close(fd); return -1; } if(tally_ptr->deny == 0 || tally_ptr->unlock_time == 0){ close(fd); return 0; } close(fd); return 1; } int pam_tally_add_failed() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; tally_ptr->failed++; //如果失败次数达到上é™�,开始计时 if(tally_ptr->failed >= tally_ptr->deny) tally_ptr->lock_start_time = time(NULL); return 0; } int pam_tally_clear_failed() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; tally_ptr->failed = 0; tally_ptr->lock_start_time = 0; return 0; } int pam_tally_failure_is_out() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return (tally_ptr->failed >= tally_ptr->deny ? 1 : 0); } int pam_tally_deny() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return tally_ptr->deny; } int pam_tally_failed_count() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return tally_ptr->failed; } int pam_tally_unlock_time() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; printf("unlock time = %d\n", tally_ptr->unlock_time); return tally_ptr->unlock_time; } int pam_tally_is_canUnlock() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; if(tally_ptr->failed >= tally_ptr->deny && time(NULL) - tally_ptr->lock_start_time < tally_ptr->unlock_time) return 0; return 1; } int pam_modutil_read(int fd, char *buffer, int count) { int block, offset = 0; while (count > 0) { block = read(fd, &buffer[offset], count); if (block < 0) { if (errno == EINTR) continue; return block; } if (block == 0) return offset; offset += block; count -= block; } return offset; } void get_tally(uid_t uid, int *tfile, struct tallylog *tally) { char filename[50]={0}; snprintf(filename, sizeof(filename), "/tmp/.tallylog.d/.%d", uid); void *void_tally = tally; if ((*tfile = open(filename, O_RDONLY)) == -1){ snprintf(filename, sizeof(filename), "/tmp/.tallylog"); if ((*tfile = open(filename, O_RDONLY)) == -1){ fprintf(stderr, "open tallylog failed \n"); return ; } } if (lseek(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET) == (off_t)-1) { fprintf(stderr, "lseek tallylog failed \n"); close(*tfile); return ; } if (pam_modutil_read(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) { fprintf(stderr, "read tallylog failed \n"); memset(tally, 0, sizeof(*tally)); } close(*tfile); tally->fail_line[sizeof(tally->fail_line)-1] = '\0'; } int pam_tally_unlock_time_left(int uid, int *fail_cnt,int *left_time, int *deny, int *fail_time, int *unlock_time1) { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return 0; int unlock_time = tally_ptr->unlock_time; *deny = tally_ptr->deny; if(unlock_time == 0) return 0; int tfile = -1; struct tallylog tally; tally.reserved = 0; tally.fail_cnt = 0; tally.fail_time = 0; get_tally(uid,&tfile,&tally); if(tally.fail_cnt<*deny) return 0; //连续输错,时间累加 if (tally.fail_cnt >= (*deny)*2 && tally.fail_cnt < (*deny)*3){ unlock_time = unlock_time*2; } else if(tally.fail_cnt >= (*deny)*3 && tally.fail_cnt < (*deny)*4){ unlock_time = unlock_time*8; } else if (tally.fail_cnt >= (*deny)*4){ *fail_cnt = 0xFFFF;//永久é”�定 return 0; } int unlock_time_left = unlock_time - ((long)time(NULL) - tally.fail_time); *fail_time = tally.fail_time; *unlock_time1 = unlock_time; *left_time = unlock_time_left > 0 ? unlock_time_left : 0; *fail_cnt = tally.fail_cnt; return *left_time; } int pam_tally_root_unlock_time_left(int *fail_cnt,int *left_time, int *deny1, int *fail_time, int *unlock_time1) { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL){ return 0; } int root_unlock_time = tally_ptr->root_unlock_time; int deny = tally_ptr->deny; if(root_unlock_time == 0) return 0; int tfile = -1; uid_t uid = getuid(); struct tallylog tally; tally.reserved = 0; tally.fail_cnt = 0; tally.fail_time = 0; get_tally(uid,&tfile,&tally); if(tally.fail_cnt= (deny)*2 && tally.fail_cnt < (deny)*3){ root_unlock_time = root_unlock_time*2; } else if(tally.fail_cnt >= (deny)*3 && tally.fail_cnt < (deny)*4){ root_unlock_time = root_unlock_time*8; } else if (tally.fail_cnt >= (deny)*4){ *fail_cnt = 0xFFFF;//永久é”�定 return 0; } int root_unlock_time_left = root_unlock_time - ((long)time(NULL) - tally.fail_time); *fail_time = tally.fail_time; *unlock_time1 = root_unlock_time; *left_time = root_unlock_time_left > 0 ? root_unlock_time_left : 0; *fail_cnt = tally.fail_cnt; return *left_time; } ukui-biometric-auth/polkit-agent/src/fullscreenbackground.h0000664000175000017500000001125715167732644023154 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef FULLSCREENMANAGER_H #define FULLSCREENMANAGER_H #include #include #include #include #include #include "usdblockshortcut.h" #include #include class MainWindow; class FullScreenBackground : public QWidget { Q_OBJECT public: explicit FullScreenBackground(QWidget *parent = nullptr); virtual ~FullScreenBackground(); /** * @brief getMainWindow 获å�–认è¯�对è¯�框 * @return 认è¯�对è¯�框指针 */ inline MainWindow *getMainWindow() { return m_wndMain; } /** * @brief initMainWindow åˆ�始化认è¯�对è¯�框 * @param strIconName 认è¯�图标å��ç§° * @param strMsg 认è¯�消æ�¯ * @param listUsers 认è¯�用户列表 * @param subjectPid 项目进程å�· * @param callerPid 调用者进程å�· * @param actionDesc 动作æ��è¿° * @param isMavis 是å�¦ä¸ºmaviså¹³å�° * @param isSupportTableMode 是å�¦æ”¯æŒ�å¹³æ�¿æ¨¡å¼� */ void initMainWindow( const QString &strIconName, const QString &strMsg, const QStringList &listUsers, const QString &subjectPid, const QString &callerPid, const PolkitQt1::ActionDescription &actionDesc, const bool &isMavis, const bool &isSupportTableMode); /** * @brief showDialog 显示认è¯�对è¯�框 */ void showDialog(); /** * @brief closeDialog 关闭认è¯�对è¯�框 */ void closeDialog(); protected: /** * @brief paintEvent 绘制事件处ç�† * @param event 事件指针 */ void paintEvent(QPaintEvent *event); /** * @brief closeEvent 窗å�£å…³é—­äº‹ä»¶å¤„ç�† * @param event 事件指针 */ void closeEvent(QCloseEvent *event); /** * @brief resizeEvent 窗å�£å¤§å°�改å�˜äº‹ä»¶å¤„ç�† * @param event 事件指针 */ void resizeEvent(QResizeEvent *event); bool eventFilter(QObject *obj, QEvent *event); private Q_SLOTS: /** * @brief onScreenCountChanged å±�幕数å�˜åŒ–处ç�† */ #if QT_VERSION_MAJOR == 6 void onScreenCountChanged(); #else void onScreenCountChanged(int); #endif /** * @brief onDesktopResized 桌é�¢å¤§å°�å�˜åŒ–处ç�† */ void onDesktopResized(); /** * @brief onPrimaryScreenChanged 主å±�å�˜åŒ–处ç�† */ void onPrimaryScreenChanged(); /** * @brief onWorkAreaResized 工作区大å°�å�˜åŒ–处ç�† */ void onWorkAreaResized(); void onCurrentScreenChanged(QScreen *screen); private: /** * @brief initUI åˆ�始化UI */ void initUI(); /** * @brief initConnections åˆ�始化信å�·æ§½è¿žæŽ¥ */ void initConnections(); /** * @brief isSupportCompositing 是å�¦æ”¯æŒ�窗å�£å¤�å�ˆ * @return true 支æŒ�,å�¦åˆ™ä¸�支æŒ� */ bool isSupportCompositing(); /** * @brief getBackground 获å�–背景 * @return 背景pixmap */ QPixmap getBackground(); /** * @brief getAccountBackground 获å�–账户背景 * @return 背景路径 */ QString getAccountBackground(); /** * @brief moveToScreen 移动认è¯�弹窗到指定å±�幕 * @param screen å±�幕信æ�¯æŒ‡é’ˆ */ void moveToScreen(QScreen *screen); /** * @brief moveToCursorScreen 移动认è¯�窗å�£åˆ°å…‰æ ‡å±�幕 */ void moveToCursorScreen(); /** * @brief blockSomeShortCut ç¦�å�¯ç”¨å¿«æ�·é”® * @param isBlock 是å�¦ä¸ºç¦�用 */ void blockSomeShortCut(bool isBlock = false); private: MainWindow *m_wndMain = nullptr; // 认è¯�对è¯�框 QPixmap m_pixmapBackground; // 背景图 bool m_isFirstShow = true; // 第一次显示æ‰�主动移动对è¯�框居中 USDBlockShortCut *m_usdBlockShortCut = nullptr; // usdç¦�å�¯ç”¨å¿«æ�·é”®å®žä¾‹ bool m_isWayland = false; UkuiWindowHelper *m_windowHelper = nullptr; QString m_curScreenName = ""; }; #endif // FULLSCREENMANAGER_H ukui-biometric-auth/polkit-agent/src/kalabel.cpp0000664000175000017500000000332115167732644020671 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "kalabel.h" KALabel::KALabel(QWidget *parent) : QLabel(parent) { m_strText = ""; } KALabel::KALabel(QString strText, QWidget *parent) : QLabel(strText, parent) { m_strText = strText; } void KALabel::setText(const QString &strText) { m_strText = strText; QLabel::setText(strText); } void KALabel::paintEvent(QPaintEvent *event) { QString strEText = getElidedText(font(), width(), m_strText); if (strEText != m_strText) { QLabel::setText(strEText); setToolTip(m_strText); } else { QLabel::setText(m_strText); setToolTip(""); } QLabel::paintEvent(event); } QString KALabel::getElidedText(QFont font, int width, QString strInfo) { QFontMetrics fontMetrics(font); //如果当å‰�字体下,字符串长度大于指定宽度 #if QT_VERSION_MAJOR == 6 if (fontMetrics.horizontalAdvance(strInfo) > width) { #else if (fontMetrics.width(strInfo) > width) { #endif strInfo = QFontMetrics(font).elidedText(strInfo, Qt::ElideRight, width); } return strInfo; } ukui-biometric-auth/polkit-agent/src/usdblockshortcut.h0000664000175000017500000000301715167732630022342 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef USDBLOCKSHORTCUT_H #define USDBLOCKSHORTCUT_H #include #include #include #include class USDBlockShortCut : public QObject, public QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.settingsDaemon.shortcut") Q_PROPERTY(QStringList blockShortcuts READ blockShortcuts) public: USDBlockShortCut(QObject *parent = nullptr); virtual ~USDBlockShortCut(); public slots: /** * @brief blockShortcuts ç¦�用按键列表 * @return ç¦�用按键字符串列表 */ QStringList blockShortcuts(); private: bool m_isRegistService = false; /**是å�¦å·²æ³¨å†Œæœ�务*/ bool m_isRegistObject = false; /**是å�¦å·²æ³¨å†Œå¯¹è±¡*/ QString m_strDbusPath; /**dbusæœ�务路径*/ }; #endif // USDBLOCKSHORTCUT_H ukui-biometric-auth/polkit-agent/src/usdblockshortcut.cpp0000664000175000017500000000445215167732644022706 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "usdblockshortcut.h" #include #include #include #include USDBlockShortCut::USDBlockShortCut(QObject *parent) : QObject(parent) { QString displayNum = QString(qgetenv("DISPLAY")).replace(":", "").replace(".", "_"); m_strDbusPath = QString("%1%2").arg(QString("org.ukui.settingsDaemon.shortcut.ukui-polkit")).arg(displayNum); m_isRegistService = QDBusConnection::sessionBus().registerService(m_strDbusPath); if (!m_isRegistService) { qInfo() << "registerService " << m_strDbusPath << " failed!!"; } else { m_isRegistObject = QDBusConnection::sessionBus().registerObject( "/org/ukui/settingsDaemon/shortcut", "org.ukui.settingsDaemon.shortcut", this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllProperties); if (!m_isRegistObject) { qInfo() << "registerObject /org/ukui/settingsDaemon/shortcut failed!!"; } } } USDBlockShortCut::~USDBlockShortCut() { if (m_isRegistObject) { QDBusConnection::sessionBus().unregisterObject("/org/ukui/settingsDaemon/shortcut"); m_isRegistObject = false; } if (m_isRegistService) { QDBusConnection::sessionBus().unregisterService(m_strDbusPath); m_isRegistService = false; } } QStringList USDBlockShortCut::blockShortcuts() { QStringList listShortCut = { "WINDOWSWITCH_KEY", "WLCOM_SWITCH_WORKSPACE", "WLCOM_WINDOW_ACTION", "WLCOM_MAXIMIZED_VIEWS", "WLCOM_CTRL_VIEWS", "KDS_KEY" }; return listShortCut; } ukui-biometric-auth/polkit-agent/src/fullscreenbackground.cpp0000664000175000017500000005167215167732644023514 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "fullscreenbackground.h" #include "mainwindow.h" #include #include #include #include #include "../common/qt_desktop_compat.h" #include #include #include #include #if QT_VERSION_MAJOR == 6 #include #else #include #endif #include using namespace kdk; #define PERSONALSIE_SCHEMA "org.mate.background" #define PERSONALSIE_TRAN_KEY "picture-filename" #define USD_MEDIA_KEYS_SCHEMA "org.ukui.SettingsDaemon.plugins.media-keys" #define USD_MEDIA_KEYS_WINDOW_SWTICH_KEY "ukuiWindowSwitch" #define USD_MEDIA_KEYS_WINDOW_SWTICH2_KEY "ukuiWindowSwitch2" FullScreenBackground::FullScreenBackground(QWidget *parent) : QWidget(parent) { m_isWayland = QString(qgetenv("XDG_SESSION_TYPE")) == "wayland"; initUI(); initConnections(); } FullScreenBackground::~FullScreenBackground() { closeDialog(); } void FullScreenBackground::initMainWindow( const QString &strIconName, const QString &strMsg, const QStringList &listUsers, const QString &subjectPid, const QString &callerPid, const PolkitQt1::ActionDescription &actionDesc, const bool &isMavis, const bool &isSupportTableMode) { if (!m_wndMain) { if (m_isWayland) { m_wndMain = new MainWindow(); m_wndMain->setWindowFlags(windowFlags() | Qt::Tool | Qt::WindowStaysOnTopHint); #if QT_VERSION_MAJOR < 6 KWindowSystem::setState(m_wndMain->winId(), NET::State::KeepAbove | NET::State::SkipTaskbar); #endif } else { m_wndMain = new MainWindow(this); m_wndMain->setModal(true); } setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint & ~Qt::WindowMinimizeButtonHint); m_wndMain->setWindowTitle(tr("Authentication")); WindowManager::setSkipTaskBar(m_wndMain->windowHandle(), true); m_wndMain->setIcon(strIconName); m_wndMain->setCurProject(isMavis); m_wndMain->setHeader(strMsg); m_wndMain->setUsers(listUsers); m_wndMain->setEditInputMethod(isSupportTableMode); m_wndMain->setFixedSize(420, 337); /* * mainWindow->setDetails(subjectPid, callerPid, actionDesc.actionId(), actionDesc.description(), actionDesc.vendorName(), actionDesc.vendorUrl()); */ connect(m_wndMain, &MainWindow::finished, this, [=](int nResult) { qDebug() << "auth dialog finished:" << nResult; }); } m_windowHelper = new UkuiWindowHelper(m_wndMain); m_windowHelper->setWindowRole(UkuiWindowHelper::WindowRole::Authentication); if (m_isWayland) { hide(); connect(m_windowHelper, &UkuiWindowHelper::currentScreenChanged, this, &FullScreenBackground::onCurrentScreenChanged); QTimer::singleShot(0, this, [&, this]() { m_windowHelper->requestGetCurrentScreen();}); } else { show(); } } void FullScreenBackground::initUI() { setWindowTitle(tr("Authentication")); if (m_isWayland) { setAttribute(Qt::WA_TranslucentBackground); setGeometry(0, 0, 0, 0); } else { setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); setWindowOpacity(0.25); #if QT_VERSION_MAJOR == 6 // Qt6/KF6中使用KX11Extras::setWindowState方法 KX11Extras::setState(winId(), NET::KeepAbove | NET::SkipTaskbar); #else KWindowSystem::setState(winId(), NET::State::KeepAbove | NET::State::SkipTaskbar); #endif WindowManager::setSkipTaskBar(this->windowHandle(), true); installEventFilter(this); if (!isSupportCompositing()) { m_pixmapBackground = getBackground(); } setGeometry(0, 0, 7680, 4320); } qDebug() << "Window geometry:" << geometry(); } void FullScreenBackground::initConnections() { // 使用兼容性函数连接å±�幕å�˜åŒ–ä¿¡å�· #if QT_VERSION_MAJOR == 6 connectScreenSignals(this, &FullScreenBackground::onScreenCountChanged); #else connectScreenSignals(this, SLOT(onScreenCountChanged())); #endif } #if QT_VERSION_MAJOR == 6 void FullScreenBackground::onScreenCountChanged() #else void FullScreenBackground::onScreenCountChanged(int) #endif { qDebug() << "onScreenCountChanged----"; if (m_isWayland) { m_windowHelper->requestGetCurrentScreen(); update(); QTimer::singleShot(100, this, [&, this]() { moveToCursorScreen();}); return; } // 使用兼容性函数获å�–桌é�¢å‡ ä½•ä¿¡æ�¯ QRect screenGeometry = getDesktopGeometry(); if ((screenGeometry.x() != 0 || screenGeometry.y() != 0) && this->geometry().contains(screenGeometry) && (getScreenCount() == 1)) { return; } if (screenGeometry.height() > height() || screenGeometry.width() > width()) { setGeometry( screenGeometry.x(), screenGeometry.y(), screenGeometry.width() + 1, screenGeometry.height() + 1); } update(); moveToCursorScreen(); qDebug() << screenGeometry; } void FullScreenBackground::onWorkAreaResized() { qDebug() << "onWorkAreaResized----"; update(); } void FullScreenBackground::onPrimaryScreenChanged() { qDebug() << "onPrimaryScreenChanged----"; if (m_isWayland) { m_windowHelper->requestGetCurrentScreen(); } update(); QTimer::singleShot(100, this, [&, this]() { moveToCursorScreen();}); } void FullScreenBackground::onDesktopResized() { qDebug() << "onDesktopResized----"; if (m_isWayland) { m_windowHelper->requestGetCurrentScreen(); update(); QTimer::singleShot(100, this, [&, this]() { moveToCursorScreen();}); return; } // 使用兼容性函数获å�–桌é�¢å‡ ä½•ä¿¡æ�¯ QRect screenGeometry = getDesktopGeometry(); if ((screenGeometry.x() != 0 || screenGeometry.y() != 0) && this->geometry().contains(screenGeometry) && (getScreenCount() == 1)) { return; } if (screenGeometry.height() > height() || screenGeometry.width() > width()) { setGeometry( screenGeometry.x(), screenGeometry.y(), screenGeometry.width() + 1, screenGeometry.height() + 1); } update(); moveToCursorScreen(); qDebug() << screenGeometry; } void FullScreenBackground::showDialog() { if (m_isFirstShow) { m_isFirstShow = false; blockSomeShortCut(true); if (!m_isWayland) { show(); } if (m_wndMain) { qDebug() << "DialogGeometry:" << m_wndMain->geometry(); m_wndMain->show(); m_wndMain->activateWindow(); // move auth dialog to cursor screen moveToCursorScreen(); } } } void FullScreenBackground::closeDialog() { blockSomeShortCut(false); if (m_wndMain) { m_wndMain->hide(); m_wndMain->stopDoubleAuth(); m_wndMain->close(); m_wndMain->deleteLater(); m_wndMain = nullptr; } } bool FullScreenBackground::isSupportCompositing() { if (QString(qgetenv("XDG_SESSION_TYPE")) == "wayland") { return true; } QDBusInterface kwinCompositor( "org.ukui.KWin", "/Compositor", "org.freedesktop.DBus.Properties", QDBusConnection::sessionBus()); QDBusReply sessionReply = kwinCompositor.call("Get", "org.kde.kwin.Compositing", "compositingType"); if (!sessionReply.isValid()) { qWarning() << sessionReply.error(); } else { QString strType = sessionReply.value().variant().toString(); if (strType.isEmpty() || strType == "none") return false; } return true; } QPixmap FullScreenBackground::getBackground() { QPixmap pixmapBackground; QString strPicName = ""; // 获å�–桌é�¢å£�纸路径 QGSettings *personalGSettings = nullptr; if (QGSettings::isSchemaInstalled(PERSONALSIE_SCHEMA)) { personalGSettings = new QGSettings(PERSONALSIE_SCHEMA, QByteArray(), this); QStringList keys = personalGSettings->keys(); if (keys.contains(PERSONALSIE_TRAN_KEY)) { strPicName = personalGSettings->get(PERSONALSIE_TRAN_KEY).toString(); } delete personalGSettings; personalGSettings = nullptr; } // 文件存在且å�¯è¯»åˆ™åŠ è½½å›¾ç‰‡ QFileInfo fileInfo(strPicName); if (fileInfo.exists() && fileInfo.isReadable()) { // do nothing } else { strPicName = getAccountBackground(); } if (!strPicName.isEmpty()) { QImageReader reader; reader.setFileName(strPicName); reader.setAutoTransform(true); reader.setDecideFormatFromContent(true); pixmapBackground = QPixmap::fromImageReader(&reader); } return pixmapBackground; } QString FullScreenBackground::getAccountBackground() { QString strTmpPicName = "/usr/share/backgrounds/ubuntukylin-default-settings.jpg"; uid_t uid = getuid(); QDBusInterface iface( "org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", QDBusConnection::systemBus()); QDBusReply userPath = iface.call("FindUserById", (qint64)uid); if (!userPath.isValid()) { return strTmpPicName; } else { QDBusInterface userIface( "org.freedesktop.Accounts", userPath.value().path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); QDBusReply backgroundReply = userIface.call("Get", "org.freedesktop.Accounts.User", "BackgroundFile"); if (backgroundReply.isValid()) { QString strPicName = backgroundReply.value().variant().toString(); if (!strPicName.isEmpty()) { QFileInfo fileInfo(strPicName); if (fileInfo.exists() && fileInfo.isReadable()) { return strPicName; } } } } return strTmpPicName; } void FullScreenBackground::moveToScreen(QScreen *screen) { // 将主全å±�更新到新å±�幕上,并é‡�新将对è¯�框居中 if (!screen) { return; } if (m_wndMain) { QRect rectParent = screen->geometry(); QRect rectDes = QRect( rectParent.x() + (rectParent.width() - m_wndMain->width()) / 2, rectParent.y() + (rectParent.height() - m_wndMain->height()) / 2, m_wndMain->width(), m_wndMain->height()); m_wndMain->setGeometry(rectDes); qDebug() << "new rect:" << rectParent << "," << rectDes << "," << m_wndMain->geometry(); } } void FullScreenBackground::moveToCursorScreen() { bool isFoundScreen = false; if (m_isWayland) { QString strCurScreen = WindowManager::currentOutputName(); if(!m_curScreenName.isEmpty()){ strCurScreen = m_curScreenName; } for (auto screen : QApplication::screens()) { qDebug() << "Screen:" << screen->name() << "," << screen->geometry(); if (screen && screen->name() == strCurScreen) { isFoundScreen = true; moveToScreen(screen); break; } } } else { QPoint cursor = QCursor::pos(); for (auto screen : QApplication::screens()) { qDebug() << "Screen:" << screen->name() << "," << screen->geometry(); if (screen && screen->geometry().contains(cursor)) { isFoundScreen = true; moveToScreen(screen); break; } } } if (!isFoundScreen) { if (QApplication::primaryScreen()) { moveToScreen(QApplication::primaryScreen()); } isFoundScreen = true; } } void FullScreenBackground::paintEvent(QPaintEvent *event) { if (!m_isWayland) { for (auto screen : QApplication::screens()) { QPainter painter(this); if (!m_pixmapBackground.isNull()) { painter.drawPixmap(screen->geometry(), m_pixmapBackground); } } } return QWidget::paintEvent(event); } void FullScreenBackground::closeEvent(QCloseEvent *event) { qDebug() << "FullScreenBackground::closeEvent"; if (!m_isWayland) { // 使用兼容性函数断开å±�幕å�˜åŒ–ä¿¡å�· #if QT_VERSION_MAJOR == 6 disconnectScreenSignals(this, &FullScreenBackground::onScreenCountChanged); #else disconnectScreenSignals(this, SLOT(onScreenCountChanged())); #endif } return QWidget::closeEvent(event); } void FullScreenBackground::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); qDebug() << "WndSize:" << this->size(); } void FullScreenBackground::blockSomeShortCut(bool isBlock /* = false*/) { static bool sIsBlocked = false; if (sIsBlocked == isBlock) { return; } QStringList listBlockShortCut = { "Minimize All Window", // 最å°�化所有窗å�£ "Minimize Or Unminimize All Window Besides Active Window", // 最å°�化或还原é�žç„¦ç‚¹çª—å�£ "Multitask View show", // 显示工作区 "Show/Hide Desktop", // 显示/éš�è—�桌é�¢ "ShowDesktopGrid", // Show Desktop Grid "ShowMultitaskView", // Show Multitask View "Switch One Desktop Down", // 切æ�¢åˆ°ä¸‹é�¢çš„æ¡Œé�¢ "Switch One Desktop Up", // 切æ�¢åˆ°ä¸Šé�¢çš„æ¡Œé�¢ "Switch One Desktop to the Left", // 切æ�¢åˆ°å·¦è¾¹çš„工作区 "Switch One Desktop to the Right", // 切æ�¢åˆ°å�³è¾¹çš„工作区 "Switch to Desktop 1", // 切æ�¢åˆ°æ¡Œé�¢ 1 "Switch to Desktop 2", // 切æ�¢åˆ°æ¡Œé�¢ 2 "Switch to Desktop 3", // 切æ�¢åˆ°æ¡Œé�¢ 3 "Switch to Desktop 4", // 切æ�¢åˆ°æ¡Œé�¢ 4 "Switch to Next Screen", // 切æ�¢åˆ°ä¸‹ä¸€å±�幕 "Switch to Previous Screen", // 切æ�¢åˆ°ä¸Šä¸€ä¸ªå±�幕 "Toggle Window Raise/Lower", // 窗å�£ç½®å‰�或置å�Ž "Unminimize All Window", // 还原所有最å°�化窗å�£ "Walk Through Desktop List", // é��历桌é�¢åˆ—表 "Walk Through Desktop List (Reverse)", // é��历桌é�¢åˆ—表(å��å�‘) "Walk Through Desktops", // é��历桌é�¢ "Walk Through Desktops (Reverse)", // é��历桌é�¢(å��å�‘) "Walk Through Windows", // é��历窗å�£ "Walk Through Windows (Reverse)", // é��历窗å�£(å��å�‘) "Walk Through Windows Alternative", // é��历窗å�£å€™é€‰ "Walk Through Windows Alternative (Reverse)", // é��历窗å�£å€™é€‰(å��å�‘) "Walk Through Windows of Current Application", // é��历当å‰�应用程åº�窗å�£ "Walk Through Windows of Current Application (Reverse)", // é��历当å‰�应用程åº�窗å�£(å��å�‘) "Walk Through Windows of Current Application Alternative", // é��历当å‰�应用程åº�窗å�£å€™é€‰ "Walk Through Windows of Current Application Alternative (Reverse)", // é��历当å‰�应用程åº�窗å�£å€™é€‰(å��å�‘) "Walk Through fullscreenWindows", // é��历所有最大化或全å±�窗å�£ "Window Lower", // é™�低窗å�£ "Window Maximize", // 最大化窗å�£ "Window Maximize Horizontal", // 水平最大化窗å�£ "Window Maximize Vertical", // 垂直最大化窗å�£ "Window Minimize", // 最å°�化窗å�£ "Window On All Desktops", // 将窗å�£æ”¾åˆ°å…¨éƒ¨æ¡Œé�¢ "Window One Desktop Down", // 窗å�£ä¸‹ç§»ä¸€ä¸ªæ¡Œé�¢ "Window One Desktop Up", // 窗å�£ä¸Šç§»ä¸€ä¸ªæ¡Œé�¢ "Window One Desktop to the Left", // 窗å�£å·¦ç§»ä¸€ä¸ªæ¡Œé�¢ "Window One Desktop to the Right", // 窗å�£å�³ç§»ä¸€ä¸ªæ¡Œé�¢ "Window Operations Menu", // 窗å�£æ“�作è�œå�• "Window Quick Move And Maximize Left Screen", // 窗å�£å¿«é€Ÿç§»åŠ¨å¹¶æœ€å¤§åŒ–åˆ°ä¸‹ä¸€ä¸ªå±�幕 "Window Quick Move And Maximize Right Screen", // 窗å�£å¿«é€Ÿç§»åŠ¨å¹¶æœ€å¤§åŒ–åˆ°ä¸Šä¸€ä¸ªå±�幕 "Window Quick Move Left Screen", // 窗å�£å¿«é€Ÿç§»åŠ¨åˆ°ä¸‹ä¸€ä¸ªå±�幕 "Window Quick Move Right Screen", // 窗å�£å¿«é€Ÿç§»åŠ¨åˆ°ä¸Šä¸€ä¸ªå±�幕 "Window to Desktop 1", // 窗å�£åˆ°æ¡Œé�¢ 1 "Window to Desktop 2", // 窗å�£åˆ°æ¡Œé�¢ 2 "Window to Desktop 3", // 窗å�£åˆ°æ¡Œé�¢ 3 "Window to Desktop 4", // 窗å�£åˆ°æ¡Œé�¢ 4 "Window to Next Desktop", // 窗å�£åˆ°ä¸‹ä¸€æ¡Œé�¢ "Window to Next Screen", // 窗å�£åˆ°ä¸‹ä¸€å±�幕 "Window to Previous Desktop", // 窗å�£åˆ°å‰�一桌é�¢ "Window to Previous Screen", // 窗å�£åˆ°å‰�一å±�幕 "Window to Screen 0", // 窗å�£åˆ°å±�幕 0 "Window to Screen 1", // 窗å�£åˆ°å±�幕 1 "Window to Screen 2", // 窗å�£åˆ°å±�幕 2 "Window to Screen 3", // 窗å�£åˆ°å±�幕 3 "Window to Screen 4", // 窗å�£åˆ°å±�幕 4 }; sIsBlocked = isBlock; if (sIsBlocked) { if (!m_isWayland) { // kwin shortcut QDBusInterface kwinInterface("org.ukui.KWin", "/KWin", "org.kde.KWin", QDBusConnection::sessionBus()); for (QString strShortCut : listBlockShortCut) { QDBusMessage blockMessage = kwinInterface.call("blockShortcut", strShortCut, true); if (blockMessage.type() == QDBusMessage::ErrorMessage) { qWarning() << "Kwin dbus error:" << blockMessage.errorMessage(); break; } } } // usd shortcut if (!m_usdBlockShortCut) { m_usdBlockShortCut = new USDBlockShortCut(this); } } else { if (!m_isWayland) { // kwin shortcut QDBusInterface kwinInterface("org.ukui.KWin", "/KWin", "org.kde.KWin", QDBusConnection::sessionBus()); for (QString strShortCut : listBlockShortCut) { QDBusMessage blockMessage = kwinInterface.call("blockShortcut", strShortCut, false); if (blockMessage.type() == QDBusMessage::ErrorMessage) { qWarning() << "Kwin dbus error1:" << blockMessage.errorMessage(); break; } } } // usd shortcut if (m_usdBlockShortCut) { delete m_usdBlockShortCut; m_usdBlockShortCut = nullptr; } } } bool FullScreenBackground::eventFilter(QObject *obj, QEvent *event) { return QWidget::eventFilter(obj, event); } void FullScreenBackground::onCurrentScreenChanged(QScreen *screen) { if(screen){ qDebug()<<"onCurrentScreenChanged "<geometry(); m_curScreenName = screen->name(); } } ukui-biometric-auth/polkit-agent/src/mainwindow.h0000664000175000017500000001426015167732644021123 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include "biometric.h" #include "users.h" #include "pam-tally.h" #include #include #include #include "bioauthwidget.h" #include "loginoptionswidget.h" #include "modeButton.h" #include "kalabel.h" #include #include using namespace kdk; namespace Ui { class MainWindow; } class MainWindow : public kdk::KDialog { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *obj, QEvent *event); void paintEvent(QPaintEvent *event); void keyPressEvent(QKeyEvent *event); //å±�蔽esc按钮 enum Mode { UNDEFINED, PASSWORD, BIOMETRIC, DEVICES }; enum situation { TRUE, ERROR }; void setIcon(const QString &iconName); void setHeader(const QString &text); void setUsers(const QStringList &usersList); void setDetails( const QString &subPid, const QString &callerPid, const QString &actionId, const QString &actionDesc, const QString vendorName, const QString vendorUrl); void setPrompt(const QString &text, bool echo); void setMessage(const QString &text, situation situat = ERROR); void setAuthResult(bool result, const QString &text = ""); void clearEdit(); void switchAuthMode(Mode mode); void setDoubleAuth(bool val); void stopDoubleAuth(); QString check_is_pam_message(QString text); void switchLoginOptType(unsigned uLoginOptType); void setEditInputMethod(bool bEnable); void setCurProject(bool isMavis); void setUkeyTypeTip(QString text); void startLoadingUkey(); void stopLoadingUkey(); void updateLoadingPixmap(); void updateAuthMethod(); void resetSendPassword(); bool checkIsAdmin(QString userName); private: uid_t getUid(const QString &userName); void setMovie(); void setPixmap(); void startBioAuth(unsigned uTimeout = 200); void switchWidget(Mode mode); int enable_biometric_authentication(); void root_unlock_countdown(); void unlock_countdown(); void editIcon(); void setLoginTypeTip(QString strLoginTypeTip); void setMavisSheel(); void updatePixmap(); void setBiometricAuthDisabledStatus(bool locked); QString getAuthMethod(); public slots: void onUpdateBioAuthMsg(QString strMsg); void onUpdateWndSize(unsigned uLoginOptType, unsigned uLoginOptSize); void onShowYesPrompt(); private slots: /** * @brief onOptionSelected * @param uCurLoginOptType * @param deviceInfo */ void onOptionSelected(unsigned uCurLoginOptType, const DeviceInfoPtr &deviceInfo); /** * @brief onNotifyOptionsChanged * @param uOptionsCount */ void onNotifyOptionsChanged(unsigned uOptionsCount); /** * @brief onLoginOptionsAuthCompleted * @param uid * @param ret * @param nStatus */ void onLoginOptionsAuthCompleted(uid_t uid, bool ret, int nStatus); void on_btnDetails_clicked(); void on_lePassword_returnPressed(); void on_ukeyPassword_returnPressed(); void on_btnBioAuth_clicked(); void on_returnButton_clicked(); void on_cmbUsers_currentTextChanged(const QString &userName); void on_btnCancel_clicked(); void on_btnAuth_clicked(); void restart_bio_identify(); void startBioAuthDelay(); void onConfigurationChanged(QString key); void onLockStatus(); void onUnlockStatus(); void onRespondUkey(const QString &text); signals: void accept(const QString &text); void canceled(); void switchToPassword(); void switchToBiometric(); void userChanged(const QString &userName); void restartAuth(); void yesPrompted(); private: Ui::MainWindow *ui; Users *users; QString userName; bool enableBioAuth; bool receiveBioPAM; BioDevices bioDevices; Mode authMode; bool isFirst; bool useDoubleAuth; bool isbioSuccess; QMap> m_failMap; int maxFailedTimes; bool isHiddenSwitchButton; ModeButton *m_modeButton; QIcon modeIcon; bool pwdShow = false; bool isHover = false; // ukey优先级比密ç �低,该å�˜é‡�用于判断是å�¦ç¬¬ä¸€æ¬¡è®¤è¯�,并选中密ç � bool isFirstAuth = true; QTimer *m_timer; // const DeviceInfo *device = NULL; bool isLockingFlg; //判断当å‰�是å�¦æ­£åœ¨é”�定倒计时 int m_nCurLockMin; //当å‰�é”�定的分钟数 // 登录选项 KALabel *m_labelTip = nullptr; LoginOptionsWidget *m_loginOptsWidget = nullptr; unsigned m_uCurLoginOptType = LOGINOPT_TYPE_PASSWORD; // 当å‰�登录验è¯�æ–¹å¼� QString m_strLoginTypeTip = ""; QTimer *m_bioTimer = nullptr; DeviceInfoPtr m_deviceInfo = nullptr; bool m_isNetworkErr = false; //标题æ � QHBoxLayout *headerLayout; QLabel *logoLabel; QLabel *titleLabel; QPushButton *closeBtn; QGSettings *settings; int fontSize; QString app_IconName; int m_nLastDeviceId = -1; bool no_changes = false; bool is_Mavis = false; QTimer *w_timer; QPixmap m_waitingPixmap; QTimer *m_loadingTimer = nullptr; QPixmap m_loadingPixmap; bool isLoadingUkey = false; bool doNotNeedAuth = false; bool hasSendPassword = false; QString authMethod = ""; UkuiWindowHelper *m_windowHelper = nullptr; }; #endif // MAINWINDOW_H ukui-biometric-auth/polkit-agent/src/users.cpp0000664000175000017500000001125415167732630020436 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "users.h" #include #include #include #include #include #include "types.h" #include #include QDebug operator<<(QDebug stream, const UserItem &user) { stream << user.name << user.realName << user.uid << user.icon << user.path; return stream; } Users::Users(QObject *parent) : QObject(parent) { defaultIcon = ":/image/assets/iconFace.png"; loadUsers(); } QList Users::getUsers() { return users; } UserItem Users::getUserByName(const QString &name) { for (int i = 0; i < users.size(); i++) { if (users.at(i).name == name) { return users.at(i); } } UserItem user; if (name == "root") { user.icon = "/root/.face"; if (!QFile(user.icon).exists()) { user.icon = defaultIcon; } } else { user.icon = qgetenv("HOME") + "/.face"; if (!QFile(user.icon).exists()) { user.icon = defaultIcon; } } user.name = name; user.path = ""; user.uid = getuid(); return user; } QString Users::getDefaultIcon() { return defaultIcon; } // https://stackoverflow.com/questions/20206376/ // how-do-i-extract-the-returned-data-from-qdbusmessage-in-a-qt-dbus-call void Users::loadUsers() { qDebug() << "loadUsers"; actService = new QDBusInterface(ACT_DBUS_SERVICE, ACT_DBUS_PATH, ACT_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(actService, SIGNAL(UserAdded(const QDBusObjectPath &)), this, SLOT(onUserAdded(const QDBusObjectPath &))); connect( actService, SIGNAL(UserDeleted(const QDBusObjectPath &)), this, SLOT(onUserDeleted(const QDBusObjectPath &))); QDBusMessage ret = actService->call("ListCachedUsers"); QList outArgs = ret.arguments(); //(QVariant(QDBusArgument,)) QVariant first = outArgs.at(0); // QVariant(QDBusArgument,) const QDBusArgument &dbusArgs = first.value(); QDBusObjectPath path; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> path; getUser(path.path()); } dbusArgs.endArray(); } UserItem Users::getUser(const QString &path) { QDBusInterface iface(ACT_DBUS_SERVICE, path, DBUS_PROP_INTERFACE, QDBusConnection::systemBus()); QDBusMessage ret = iface.call("GetAll", ACT_USER_INTERFACE); QList outArgs = ret.arguments(); QVariant first = outArgs.at(0); const QDBusArgument &dbusArgs = first.value(); UserItem user; user.path = path; dbusArgs.beginMap(); while (!dbusArgs.atEnd()) { QString key; QVariant value; dbusArgs.beginMapEntry(); dbusArgs >> key >> value; if (key == "UserName") { user.name = value.toString(); } else if (key == "RealName") { user.realName = value.toString(); } else if (key == "IconFile") { user.icon = value.toString(); if (!QFile(user.icon).exists()) { user.icon = defaultIcon; } } else if (key == "Uid") { user.uid = value.toUInt(); } dbusArgs.endMapEntry(); } dbusArgs.endMap(); if (user.realName.isEmpty()) { user.realName = user.name; } users.push_back(user); return user; } void Users::onUserAdded(const QDBusObjectPath &path) { int index = findUserByPath(path.path()); if (index >= 0 && index < users.count()) { UserItem user = getUser(path.path()); Q_EMIT userAdded(user); } } void Users::onUserDeleted(const QDBusObjectPath &path) { int index = findUserByPath(path.path()); if (index >= 0 && index < users.count()) { UserItem user = users.at(index); users.removeAt(index); Q_EMIT userDeleted(user); } } int Users::findUserByPath(const QString &path) { auto iter = std::find_if(users.begin(), users.end(), [&](const UserItem &user) { return user.path == path; }); int index = iter - users.begin(); return index; } ukui-biometric-auth/polkit-agent/src/main.qss0000664000175000017500000000000015167732630020230 0ustar fengfengukui-biometric-auth/polkit-agent/src/mainwindow.ui0000664000175000017500000003266315167732644021320 0ustar fengfeng MainWindow 0 0 459 716 0 0 430 0 Form 8 QLayout::SetDefaultConstraint 0 8 0 24 8 24 0 24 0 382 0 382 16777215 75 true true true 0 0 0 0 116 8 0 0 0 0 true true 0 116 0 0 0 9 8 0 0 0 Qt::AlignCenter Qt::NoContextMenu 0 25 Qt::LeftToRight Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true 0 80 0 0 0 8 0 Qt::NoContextMenu 0 25 Qt::LeftToRight Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true 0 24 0 24 0 Qt::Vertical 20 40 16 24 0 24 0 36 ArrowCursor Biometric Qt::Horizontal 10 36 0 0 0 36 ArrowCursor Cancel 0 0 0 36 ArrowCursor Authenticate 0 36 true 0 36 use password KALabel QLabel
./src/kalabel.h
ukui-biometric-auth/polkit-agent/src/pam-tally.h0000664000175000017500000000350515167732630020642 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef PAM_TALLY_H #define PAM_TALLY_H #include #ifdef __cplusplus extern "C" { #endif #define SHM_TALLY "/shm_tally" struct _pam_tally { int deny; //失败次数上é™� int unlock_time; //普通用户失败次数达到上é™�å�Žï¼Œå¤šå°‘秒之å�Žæ‰�能解é”� int root_unlock_time; // root用户失败次数达到上é™�å�Žï¼Œå¤šå°‘秒之å�Žæ‰�能解é”� int failed; //当å‰�失败的次数 time_t lock_start_time; //失败次数达到上é™�å�Žï¼Œå¼€å§‹è®¡æ—¶ }; typedef struct _pam_tally pam_tally; int pam_tally_init(); int pam_tally_add_failed(); int pam_tally_clear_failed(); int pam_tally_falure_is_out(); int pam_tally_deny(); int pam_tally_failed_count(); int pam_tally_unlock_time(); int pam_tally_is_enbled(); int pam_tally_is_canUnlock(); int pam_tally_unlock_time_left(int uid, int *fail_cnt, int *left_time, int *deny, int *fail_time, int *unlock_time); int pam_tally_root_unlock_time_left(int *fail_cnt, int *left_time, int *deny, int *fail_time, int *unlock_time1); #ifdef __cplusplus } #endif #endif // PAM_TALLY_H ukui-biometric-auth/polkit-agent/src/sessionmanager.cpp0000664000175000017500000000547415167732630022322 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "sessionmanager.h" #include #include #include #include #define SM_DBUS_SERVICE "org.gnome.SessionManager" #define SM_DBUS_PATH "/org/gnome/SessionManager" #define SM_DBUS_INTERFACE "org.gnome.SessionManager" #define SM_DBUS_CLIENT_INTERFACE "org.gnome.SessionManager.ClientPrivate" SessionManager::SessionManager(QObject *parent) : QObject(parent) { smInterface = new QDBusInterface(SM_DBUS_SERVICE, SM_DBUS_PATH, SM_DBUS_INTERFACE, QDBusConnection::sessionBus()); QString appId("polkit-ukui-authentication-agent-1.desktop"); QString clientStartupId(qgetenv("DESKTOP_AUTOSTART_ID")); QDBusReply reply = smInterface->call("RegisterClient", appId, clientStartupId); if (!reply.isValid()) { qWarning() << "Register Client to gnome session failed"; } clientId = reply.value().path(); qDebug() << "Register Client to gnome session: " << reply.value().path(); clientInterface = new QDBusInterface(SM_DBUS_SERVICE, clientId, SM_DBUS_CLIENT_INTERFACE, QDBusConnection::sessionBus()); qDebug() << clientInterface->isValid(); QDBusConnection conn = clientInterface->connection(); conn.connect(SM_DBUS_SERVICE, clientId, SM_DBUS_CLIENT_INTERFACE, "Stop", this, SLOT(onStop())); conn.connect( SM_DBUS_SERVICE, clientId, SM_DBUS_CLIENT_INTERFACE, "EndSession", this, SLOT(onEndSession(unsigned int))); conn.connect(SM_DBUS_SERVICE, clientId, SM_DBUS_CLIENT_INTERFACE, "QueryEndSession", this, SLOT(onQueryEndSession(unsigned int))); } void SessionManager::onStop() { QApplication::quit(); } void SessionManager::onEndSession(unsigned int flag) { endSessionResponse(); } void SessionManager::onQueryEndSession(unsigned int flag) { endSessionResponse(); QApplication::quit(); } void SessionManager::endSessionResponse() { QDBusMessage msg = clientInterface->call("EndSessionResponse", true, ""); if (msg.type() == QDBusMessage::ErrorMessage) qDebug() << "Failed to call EndSessionResponse " << msg.errorMessage(); } ukui-biometric-auth/polkit-agent/src/modeButton.h0000664000175000017500000000274415167732630021066 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef MODEBUTTON_H #define MODEBUTTON_H #include #include #include #include #include class ModeButton : public QPushButton { Q_OBJECT public: explicit ModeButton(QWidget *parent = nullptr); ModeButton(QString strIcon, QWidget *parent = nullptr); virtual ~ModeButton(); QPixmap drawSymbolicColoredPixmap(QPixmap &source, QString cgColor); void initUI(); void setModeIcon(); bool isShowPwd(); protected: bool eventFilter(QObject *obj, QEvent *event) override; //事件过滤 private: void initStyleTheme(); private: QString m_strIcon; QString m_strText; QGSettings *m_styleSettings = nullptr; QString m_strThemeName = ""; bool pwdShow = false; bool m_isHover = false; }; #endif // MODEBUTTON_H ukui-biometric-auth/polkit-agent/src/users.h0000664000175000017500000000316715167732630020107 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef USERS_H #define USERS_H #include struct UserItem { QString name; QString realName; QString icon; quint64 uid; QString path; // accounts service path friend QDebug operator<<(QDebug stream, const UserItem &user); }; class QDBusInterface; class QDBusObjectPath; class Users : public QObject { Q_OBJECT public: explicit Users(QObject *parent = nullptr); QList getUsers(); UserItem getUserByName(const QString &name); QString getDefaultIcon(); private: void loadUsers(); UserItem getUser(const QString &path); int findUserByPath(const QString &path); private Q_SLOTS: void onUserAdded(const QDBusObjectPath &path); void onUserDeleted(const QDBusObjectPath &path); Q_SIGNALS: void userAdded(const UserItem &user); void userDeleted(const UserItem &user); private: QDBusInterface *actService; QList users; QString defaultIcon; }; #endif // USERS_H ukui-biometric-auth/polkit-agent/src/PolkitListener.h0000664000175000017500000000473215167732644021722 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef POLKITLISTENER_H #define POLKITLISTENER_H #include #include "mainwindow.h" #include "fullscreenbackground.h" #include #include #include #include #include #include #include using namespace PolkitQt1::Agent; class PolkitListener : public Listener { Q_OBJECT public: PolkitListener(QObject *parent = 0); virtual ~PolkitListener(); private: bool isSupportTableMode(); bool isMavis(); public slots: void initiateAuthentication( const QString &actionId, const QString &message, const QString &iconName, const PolkitQt1::Details &details, const QString &cookie, const PolkitQt1::Identity::List &identities, PolkitQt1::Agent::AsyncResult *result); bool initiateAuthenticationFinish(); void cancelAuthentication(); void finishObtainPrivilege(); private: bool gainedAuthorization = false; bool wasCancelled = false; bool wasSwitchToBiometric = false; bool inProgress; int numTries; QString implicitActiveStr; QPointer session; PolkitQt1::Identity::List identities; PolkitQt1::Identity currentIdentity; PolkitQt1::Agent::AsyncResult *result; QString cookie; FullScreenBackground *m_managerFullScreen; bool unacknowledged_messages = false; bool m_isSupportTableMode = false; bool m_isMavis = false; private slots: void startAuthentication(); void onShowPrompt(const QString &prompt, bool echo); void onShowError(const QString &text); void onShowInfo(const QString &text); void onResponse(const QString &text); void onAuthCompleted(bool); }; #endif /* POLKITLISTENER_H */ ukui-biometric-auth/polkit-agent/src/sessionmanager.h0000664000175000017500000000225615167732630021762 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SESSIONMANAGER_H #define SESSIONMANAGER_H #include #include class SessionManager : public QObject { Q_OBJECT public: explicit SessionManager(QObject *parent = nullptr); signals: private slots: void onStop(); void onEndSession(unsigned int flag); void onQueryEndSession(unsigned int flag); void endSessionResponse(); private: QDBusInterface *smInterface; QDBusInterface *clientInterface; QString clientId; }; #endif // SESSIONMANAGER_H ukui-biometric-auth/polkit-agent/src/PolkitListener.cpp0000664000175000017500000003266615167732644022264 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include "PolkitListener.h" #include "mainwindow.h" #include "generic.h" #include PolkitListener::PolkitListener(QObject *parent) : Listener(parent), inProgress(false), currentIdentity(0), m_managerFullScreen(nullptr) { m_isSupportTableMode = isSupportTableMode(); m_isMavis = isMavis(); qDebug() << "isSupportTableMode:" << m_isSupportTableMode; } PolkitListener::~PolkitListener() {} bool PolkitListener::isMavis() { char *prjName = kdk_system_get_projectName(); if (prjName) { QString strFeature = QString(prjName); free(prjName); if (!strFeature.isEmpty()) { if(strFeature == "V10SP1-edu"){ m_isSupportTableMode = true; return true; } } } return false; } bool PolkitListener::isSupportTableMode() { unsigned int nFeature = kdk_system_get_productFeatures(); if (nFeature&0x02) { // 支æŒ�å¹³æ�¿æ¨¡å¼� return true; } return false; } /* initiateAuthentication message from polkit */ void PolkitListener::initiateAuthentication( const QString &actionId, const QString &message, const QString &iconName, const PolkitQt1::Details &details, const QString &cookie, const PolkitQt1::Identity::List &identities, PolkitQt1::Agent::AsyncResult *result) { if (inProgress) { result->setError(tr("Another client is already authenticating, please try again later.")); result->setCompleted(); qDebug() << "Another client is already authenticating, please try again later."; return; } QStringList usersList; QString subjectPid, callerPid; PolkitQt1::ActionDescription actionDesc; QString username = getenv("USER"); for(auto identity : identities){ if(identity.toString().remove("unix-user:") == username) usersList.prepend(identity.toString().remove("unix-user:")); else usersList.append(identity.toString().remove("unix-user:")); } subjectPid = details.lookup("polkit.subject-pid"); callerPid = details.lookup("polkit.caller-pid"); implicitActiveStr = details.lookup("implicit_authorization"); /* find action description for actionId */ foreach (const PolkitQt1::ActionDescription &desc, PolkitQt1::Authority::instance()->enumerateActionsSync()) { if (actionId == desc.actionId()) { actionDesc = desc; qDebug() << "Action description has been found"; break; } } qDebug() << "Initiating authentication"; qDebug() << "icon name: " << iconName; qDebug() << "identities: " << usersList; qDebug() << "message: " << message; qDebug() << "action id: " << actionId; qDebug() << "polkit.subject-pid" << subjectPid; qDebug() << "polkit.caller-pid" << callerPid; qDebug() << "action: " << actionDesc.description(); qDebug() << "Vendor:" << actionDesc.vendorName() << actionDesc.vendorUrl(); this->inProgress = true; this->identities = identities; this->cookie = cookie; this->result = result; session.clear(); if (identities.length() == 1) { this->currentIdentity = identities[0]; } else { currentIdentity = identities[0]; } /* Create the polkit window */ m_managerFullScreen = new FullScreenBackground(); m_managerFullScreen->initMainWindow( iconName, message, usersList, subjectPid, callerPid, actionDesc, m_isMavis, m_isSupportTableMode); if (m_managerFullScreen && m_managerFullScreen->getMainWindow()) { connect(m_managerFullScreen->getMainWindow(), &MainWindow::accept, this, &PolkitListener::onResponse); connect(m_managerFullScreen->getMainWindow(), &MainWindow::canceled, this, [&] { if (inProgress && !gainedAuthorization) { wasCancelled = true; unacknowledged_messages = false; if (!session.isNull()) { session.data()->cancel(); } finishObtainPrivilege(); } }); connect(m_managerFullScreen->getMainWindow(), &MainWindow::switchToBiometric, this, [&] { wasSwitchToBiometric = true; startAuthentication(); }); connect(m_managerFullScreen->getMainWindow(), &MainWindow::yesPrompted, this, [=] { result->setCompleted(); this->gainedAuthorization = true; finishObtainPrivilege(); }); connect(m_managerFullScreen->getMainWindow(), &MainWindow::restartAuth, this, [&] { startAuthentication(); }); connect(m_managerFullScreen->getMainWindow(), &MainWindow::userChanged, this, [&](const QString &userName) { for (int i = 0; i < this->identities.size(); i++) { auto identity = this->identities.at(i); if (identity.toString().remove("unix-user:") == userName) { this->currentIdentity = this->identities.at(i); numTries = 0; startAuthentication(); break; } } }); numTries = 0; wasCancelled = false; wasSwitchToBiometric = false; if (implicitActiveStr == "yes_prompt") { m_managerFullScreen->getMainWindow()->onShowYesPrompt(); m_managerFullScreen->getMainWindow()->setFixedSize(m_managerFullScreen->getMainWindow()->width(), 200); m_managerFullScreen->getMainWindow()->show(); m_managerFullScreen->getMainWindow()->activateWindow(); return; } m_managerFullScreen->getMainWindow()->userChanged(usersList.at(0)); } } static int get_pam_tally(int *deny, int *unlock_time) { char buf[128]; FILE *auth_file = NULL; if ((auth_file = fopen("/etc/pam.d/common-auth", "r")) == NULL) return -1; while (fgets(buf, sizeof(buf), auth_file)) { if (strnlen(buf,1024) == 0 || buf[0] == '#') continue; if (!strstr(buf, "deny")) continue; char *ptr = strtok(buf, " \t"); while (ptr) { if (strncmp(ptr, "deny=", 5) == 0) { sscanf(ptr, "deny=%d", deny); // gs_debug("-------------------- deny=%d", *deny); } if (strncmp(ptr, "unlock_time=", 12) == 0) { sscanf(ptr, "unlock_time=%d", unlock_time); // gs_debug("-------------------- unlock_time=%d", *unlock_time); } ptr = strtok(NULL, " \t"); } fclose(auth_file); auth_file = NULL; return 1; } fclose(auth_file); auth_file = NULL; return 0; } void PolkitListener::finishObtainPrivilege() { /* Number of tries increase only when some user is selected */ if (currentIdentity.isValid()) { numTries++; } qDebug().noquote() << QString("Finishing obtaining " "privileges (G:%1, C:%2, D:%3).") .arg(gainedAuthorization) .arg(wasCancelled) .arg(m_managerFullScreen && m_managerFullScreen->getMainWindow()); if (!gainedAuthorization && !wasCancelled && (m_managerFullScreen && m_managerFullScreen->getMainWindow())) { int deny = 0, unlock_time = 0; m_managerFullScreen->getMainWindow()->stopDoubleAuth(); if (!get_pam_tally(&deny, &unlock_time) || (deny == 0 && unlock_time == 0)) { // if(!wasSwitchToBiometric){ if (!unacknowledged_messages) m_managerFullScreen->getMainWindow()->setAuthResult( gainedAuthorization, tr("Authentication failure, please try again.")); //} startAuthentication(); return; } else { if (!unacknowledged_messages) { m_managerFullScreen->getMainWindow()->setAuthResult(gainedAuthorization, tr("Password input error!")); } startAuthentication(); return; } startAuthentication(); return; } if (m_managerFullScreen) { m_managerFullScreen->closeDialog(); m_managerFullScreen->deleteLater(); m_managerFullScreen = nullptr; } if ((implicitActiveStr == "yes_prompt") && wasCancelled) { result->setError("polkit-ukui-authentication-agent-1 cancel"); } if (!session.isNull()) { session.data()->result()->setCompleted(); session.data()->deleteLater(); session.clear(); } else { result->setCompleted(); } this->inProgress = false; implicitActiveStr = ""; qDebug() << "Finish obtain authorization:" << gainedAuthorization; gainedAuthorization = false; } void establishToBioPAM() { FILE *file; const char *data = "polkit-ukui-authentication-agent-1"; if ((file = fopen(BIO_COM_FILE, "w")) == NULL) { qWarning() << "open communication file failed: " << strerror(errno); return; } if (fputs(data, file) == EOF) { qWarning() << "write to communication file error: " << strerror(errno); } fclose(file); } void PolkitListener::startAuthentication() { qDebug() << "start authenticate user " << currentIdentity.toString(); unacknowledged_messages = false; if (!session.isNull()) { session.data()->deleteLater(); } /* We will create a new session only when some user is selected */ if (currentIdentity.isValid()) { establishToBioPAM(); session = new Session(currentIdentity, cookie, result); connect(session.data(), SIGNAL(request(QString, bool)), this, SLOT(onShowPrompt(QString, bool))); connect(session.data(), SIGNAL(completed(bool)), this, SLOT(onAuthCompleted(bool))); connect(session.data(), SIGNAL(showError(QString)), this, SLOT(onShowError(QString))); connect(session.data(), SIGNAL(showInfo(QString)), this, SLOT(onShowError(QString))); session.data()->initiate(); } if (m_managerFullScreen && m_managerFullScreen->getMainWindow()) { m_managerFullScreen->getMainWindow()->clearEdit(); m_managerFullScreen->getMainWindow()->updateAuthMethod(); m_managerFullScreen->getMainWindow()->resetSendPassword(); } } void PolkitListener::onShowPrompt(const QString &prompt, bool echo) { qDebug() << "Prompt: " << prompt << "echo: " << echo; if (!m_managerFullScreen || !m_managerFullScreen->getMainWindow()) { return; } if (prompt == BIOMETRIC_PAM || prompt == BIOMETRIC_PAM_QRCODE) { m_managerFullScreen->getMainWindow()->setDoubleAuth(false); m_managerFullScreen->getMainWindow()->switchAuthMode(MainWindow::BIOMETRIC); } else if (prompt == BIOMETRIC_PAM_DOUBLE) { m_managerFullScreen->getMainWindow()->setDoubleAuth(true); m_managerFullScreen->getMainWindow()->switchAuthMode(MainWindow::BIOMETRIC); //这时候ä¸�需è¦�显示授æ�ƒå¼¹çª—,下一次收到prompt请求的时候å†�显示 return; } else { unacknowledged_messages = false; m_managerFullScreen->getMainWindow()->switchAuthMode(MainWindow::PASSWORD); m_managerFullScreen->getMainWindow()->setPrompt(prompt, echo); m_managerFullScreen->showDialog(); } } //ç›®å‰�返回的pam错误就onShowError,onShowInfo两类 void PolkitListener::onShowError(const QString &text) { qDebug() << "[Polkit]:" << "Error:" << text; unacknowledged_messages = true; if (m_managerFullScreen && m_managerFullScreen->getMainWindow()) { QString strText = m_managerFullScreen->getMainWindow()->check_is_pam_message(text); m_managerFullScreen->getMainWindow()->setMessage(strText); } } void PolkitListener::onShowInfo(const QString &text) { qDebug() << "[Polkit]:" << "Info:" << text; unacknowledged_messages = true; if (m_managerFullScreen && m_managerFullScreen->getMainWindow()) { QString strText = m_managerFullScreen->getMainWindow()->check_is_pam_message(text); m_managerFullScreen->getMainWindow()->setMessage(strText); } } void PolkitListener::onResponse(const QString &text) { unacknowledged_messages = false; session.data()->setResponse(text); } void PolkitListener::onAuthCompleted(bool gainedAuthorization) { qDebug() << "completed: " << gainedAuthorization; if (m_managerFullScreen) m_managerFullScreen->getMainWindow()->resetSendPassword(); this->gainedAuthorization = gainedAuthorization; finishObtainPrivilege(); } bool PolkitListener::initiateAuthenticationFinish() { qDebug() << "initiateAuthenticationFinish."; return true; } void PolkitListener::cancelAuthentication() { wasCancelled = true; qDebug() << "cancelAuthentication."; finishObtainPrivilege(); } ukui-biometric-auth/polkit-agent/CMakeLists.txt0000664000175000017500000001153315167732644020547 0ustar fengfengcmake_minimum_required(VERSION 3.16) project(ukui-polkit-agent) pkg_check_modules(KDKINFO REQUIRED kysdk-sysinfo) pkg_check_modules(KDKWIDGETS REQUIRED kysdk-qtwidgets) pkg_check_modules(KYSDKWAYLANDHELPER REQUIRED kysdk-waylandhelper) pkg_check_modules(KYSDKWINDOWHELPER REQUIRED kysdk-ukuiwindowhelper) # æ ¹æ�®Qt版本查找相应的PolkitQt包 if(QT_VERSION_MAJOR EQUAL 6) pkg_check_modules(QGS REQUIRED gsettings-qt6) find_package(PolkitQt6-1 REQUIRED 0.103.0) find_package(Qt6 COMPONENTS Core Widgets DBus Xml Network Svg) set(POLKITQT_PREFIX PolkitQt6-1) else() pkg_check_modules(QGS REQUIRED gsettings-qt) find_package(PolkitQt5-1 REQUIRED 0.103.0) find_package(Qt5 COMPONENTS Core Widgets DBus X11Extras Xml Network Svg) set(POLKITQT_PREFIX PolkitQt5-1) endif() # æ ¹æ�®Qt版本查找相应的KF包 if(QT_VERSION_MAJOR EQUAL 6) # å°�试查找KF6,如果失败则回退到KF5 find_package(KF6WindowSystem QUIET) if(KF6WindowSystem_FOUND) message(STATUS "Using KF6") set(KF_PREFIX KF6) set(KF_WINDOW_SYSTEM KF6::WindowSystem) else() message(STATUS "KF6 not found, using KF5") find_package(KF5WindowSystem REQUIRED) set(KF_PREFIX KF5) set(KF_WINDOW_SYSTEM KF5::WindowSystem) endif() else() find_package(KF5WindowSystem REQUIRED) set(KF_PREFIX KF5) set(KF_WINDOW_SYSTEM KF5::WindowSystem) endif() find_package(X11 REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(LIB_ARCH_PATH /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}) configure_file( ${PROJECT_SOURCE_DIR}/data/polkit-ukui-authentication-agent-1.desktop.in ${PROJECT_BINARY_DIR}/data/polkit-ukui-authentication-agent-1.desktop ) include_directories( ${QGS_INCLUDE_DIRS} ${KDKINFO_INCLUDE_DIRS} ${KDKWIDGETS_INCLUDE_DIRS} ${KYSDKWAYLANDHELPER_INCLUDE_DIRS} ${KYSDKWINDOWHELPER_INCLUDE_DIRS} ) link_directories( ${KDKINFO_LIBRARY_DIRS} ${KDKWIDGETS_LIBRARY_DIRS} ${KYSDKWAYLANDHELPER_LIBRARY_DIRS} ${KYSDKWINDOWHELPER_LIBRARY_DIRS} ) set(EXTRA_LIBS ${EXTRA_LIBS} ${QGS_LIBRARIES} ${KDKINFO_LIBRARIES} ${KDKWIDGETS_LIBRARIES} ${KYSDKWAYLANDHELPER_LIBRARIES} ${KYSDKWINDOWHELPER_LIBRARIES} ) # æ ¹æ�®Qt版本设置包å�«ç›®å½•和资æº�处ç�† if(QT_VERSION_MAJOR EQUAL 6) include_directories( ${POLKITQT-1_INCLUDE_DIR} ../common ../bioauth/include ) qt6_add_resources(polkit_SRCS assets.qrc) qt6_wrap_ui(polkit_SRCS src/mainwindow.ui ) else() include_directories( ${POLKITQT-1_INCLUDE_DIR} ../common ../bioauth/include ) qt5_add_resources(polkit_SRCS assets.qrc) qt5_wrap_ui(polkit_SRCS src/mainwindow.ui ) endif() set(polkit_SRCS ${polkit_SRCS} src/PolkitAgent.cpp src/mainwindow.cpp src/PolkitListener.cpp src/sessionmanager.cpp src/users.cpp src/pam-tally.c src/modeButton.cpp src/kalabel.cpp ../common/generic.cpp src/fullscreenbackground.h src/fullscreenbackground.cpp src/usdblockshortcut.h src/usdblockshortcut.cpp ) add_executable(polkit-ukui-authentication-agent-1 ${polkit_SRCS}) target_include_directories(polkit-ukui-authentication-agent-1 PRIVATE ${KYSDKQTWIDGETS_PKG_INCLUDE_DIRS}) target_link_directories(polkit-ukui-authentication-agent-1 PRIVATE ${KYSDKQTWIDGETS_PKG_LIBRARY_DIRS}) # æ ¹æ�®Qt版本设置链接库 if(QT_VERSION_MAJOR EQUAL 6) target_link_libraries(polkit-ukui-authentication-agent-1 Qt6::Core Qt6::Widgets Qt6::DBus ${EXTRA_LIBS} ${KF_WINDOW_SYSTEM} ${POLKITQT-1_LIBRARIES} ${KYSDKQTWIDGETS_PKG_LIBRARIES} BioAuthWidgets -lrt -lukui-log4qt ) else() target_link_libraries(polkit-ukui-authentication-agent-1 Qt5::Core Qt5::Widgets Qt5::DBus ${EXTRA_LIBS} ${KF_WINDOW_SYSTEM} ${POLKITQT-1_LIBRARIES} ${KYSDKQTWIDGETS_PKG_LIBRARIES} BioAuthWidgets -lrt -lukui-log4qt ) endif() install(TARGETS polkit-ukui-authentication-agent-1 DESTINATION lib/${CMAKE_LIBRARY_ARCHITECTURE}/ukui-polkit) # 翻译文件 file(GLOB ts_files i18n_ts/*.ts) # æ ¹æ�®Qt版本使用相应的翻译函数 if(QT_VERSION_MAJOR EQUAL 6) qt6_add_translation(qm_files ${ts_files}) else() qt5_add_translation(qm_files ${ts_files}) endif() add_custom_target(polkit_i18n DEPENDS ${qm_files} SOURCES ${ts_files}) add_dependencies(polkit-ukui-authentication-agent-1 polkit_i18n) install(FILES ${qm_files} DESTINATION ${UKUI_BIOMETRIC_DIR}/i18n_qm/polkit) install(FILES ${PROJECT_BINARY_DIR}/data/polkit-ukui-authentication-agent-1.desktop DESTINATION /etc/xdg/autostart) install(FILES ${PROJECT_BINARY_DIR}/data/polkit-ukui-authentication-agent-1.desktop DESTINATION /usr/share/applications) ukui-biometric-auth/polkit-agent/assets/0000775000175000017500000000000015167732644017306 5ustar fengfengukui-biometric-auth/polkit-agent/assets/hide-password.png0000664000175000017500000000051715167732630022563 0ustar fengfeng‰PNG  IHDRÄ´l;IDAT8�íÒ±JœQÅñß·X¬|@|-„T¬Lµ›él%é’4V2[¦Û[ÁJ´ÈHa'hHk%ò¥ð#ˆ¸Rí.—;÷ÌáÀ cÆŒMDœDÄ\Û¶^{"b>"¡‡ 3óÃkfæ ؃¦m[™9‹|ÇFUݼÀpŸñKUõ£iš{ãN°†m¼éîAUÝ=cØÃ{|ÂUÕð¯qf.ãVñ 1ÝÕŽqQU¿3s 3XÀ:.±[U§=úýþ°×XÀjU «ê‹¸êR|ÅyfÞâ'¾`×x×éUÕk�—QÓÝŒˆ­GµöÑ{+"6Ÿêç~+žbûÏ�Í>æGþ¾`GÛÕŽù?üùåýð“(ö-IEND®B`‚ukui-biometric-auth/polkit-agent/assets/show-password.png0000664000175000017500000000110615167732630022625 0ustar fengfeng‰PNG  IHDRÄ´l; IDAT8�íÔË‹ŽqÀñÏ#a( Q.)Œ?@ä–Ô°Uˆ•�Æ{\"—eã²p�ÅÔye1ì&e!. ·P”�rËå�…�×âý fŒ=§NÏÓ¹|Ïy~çüþK]Z­ÖˆÚh4Z×jµÀ¨¡ EÄõˆ˜ð§f"bBD\Î?zû]l�ˆ~lÆÚûŒ×¸Všº;xTIhFÄúšýºñ“°­<§•÷ìÅäˆWûŠõÑ„ �Æ\ÄF<¼ÅÎÌü8TG1½˜�ÕX4Èh6›íáEĬÁbœËÌ“0'ÐU˜·°?3_ÿnìÁC\ÎÌ�ªª~Þ£Rõx Ú‰û¸ƒYEïà~ñÉÌ38„…x<]ãq§3³¯VìŽefoÍÖÅ·¶Àû#b"®FÄ|ì¸O2óì/GÙ…K¥ø½ˆ¸Wì籪XŠ?-¬ŸŽâ«‘¥Áß*ú¼ "bû/�·´7Ef.ËÌ¥ÅÞ�õÀˆØ‡ùØò½ƒ²Óñ‡3³¿ÏÓÖQåHJ¡ƒXž™/JÜ.íÍXœ™ªªú.sqg3óT±ujjeßDOf¾Œˆ °+2ó ü. þþ‚ôa&VgæûAß�à’4=Ø�~ àÆbÖaš8’™_êùÂk¦ ¡}#çó+íŸPf满òªj¤åù§äýÇü‰/ ÛgIEND®B`‚ukui-biometric-auth/polkit-agent/assets/arrow_down.svg0000664000175000017500000000146415167732630022210 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/0000775000175000017500000000000015167732644021442 5ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris7.svg0000664000175000017500000000266715167732644023233 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/0000775000175000017500000000000015167732644022363 5ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris7.svg0000664000175000017500000000532115167732644024142 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint3.svg0000664000175000017500000004457415167732644025534 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint6.svg0000664000175000017500000001321115167732644025352 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris9.svg0000664000175000017500000000532215167732644024145 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris3.svg0000664000175000017500000000532015167732644024135 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein0.svg0000664000175000017500000002114715167732644025325 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint4.svg0000664000175000017500000001321115167732644025350 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint7.svg0000664000175000017500000001321115167732644025353 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint4.svg0000664000175000017500000005053215167732644025524 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris10.svg0000664000175000017500000000532315167732644024216 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint0.svg0000664000175000017500000003325215167732644025520 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein3.svg0000664000175000017500000002213015167732644025321 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint8.svg0000664000175000017500000007343715167732644025541 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint6.svg0000664000175000017500000005621215167732644025527 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris6.svg0000664000175000017500000000532015167732644024140 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint2.svg0000664000175000017500000004203015167732644025514 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint2.svg0000664000175000017500000001321115167732644025346 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint7.svg0000664000175000017500000006616715167732644025542 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris5.svg0000664000175000017500000000532115167732644024140 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein11.svg0000664000175000017500000002213515167732644025405 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein2.svg0000664000175000017500000002213015167732644025320 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint0.svg0000664000175000017500000001321115167732644025344 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint5.svg0000664000175000017500000005234115167732644025525 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein6.svg0000664000175000017500000002213015167732644025324 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint11.svg0000664000175000017500000010372015167732644025600 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris2.svg0000664000175000017500000000532015167732644024134 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein4.svg0000664000175000017500000002213115167732644025323 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint14.svg0000664000175000017500000003626215167732644025611 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint10.svg0000664000175000017500000010117215167732644025576 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris0.svg0000664000175000017500000000433515167732644024137 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein5.svg0000664000175000017500000002213115167732644025324 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint9.svg0000664000175000017500000007651315167732644025540 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint12.svg0000664000175000017500000010551515167732644025605 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint5.svg0000664000175000017500000001321115167732644025351 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris8.svg0000664000175000017500000000532215167732644024144 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris4.svg0000664000175000017500000000532115167732644024137 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein9.svg0000664000175000017500000002213215167732644025331 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint1.svg0000664000175000017500000001321115167732644025345 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint13.svg0000664000175000017500000011013715167732644025602 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein8.svg0000664000175000017500000002213215167732644025330 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/voiceprint3.svg0000664000175000017500000001321115167732644025347 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingerprint1.svg0000664000175000017500000004101715167732644025517 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein1.svg0000664000175000017500000002210415167732644025320 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein7.svg0000664000175000017500000002213115167732644025326 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris11.svg0000664000175000017500000000532315167732644024217 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/iris1.svg0000664000175000017500000000527415167732644024143 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/dark/fingervein10.svg0000664000175000017500000002213315167732644025402 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint3.svg0000664000175000017500000002214415167732644024600 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint6.svg0000664000175000017500000001321115167732644024431 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris9.svg0000664000175000017500000000267215167732644023231 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris3.svg0000664000175000017500000000266715167732644023227 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein0.svg0000664000175000017500000000527615167732644024411 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint4.svg0000664000175000017500000001321115167732644024427 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint7.svg0000664000175000017500000001321115167732644024432 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint4.svg0000664000175000017500000002347015167732644024604 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris10.svg0000664000175000017500000000267215167732644023301 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint0.svg0000664000175000017500000001763415167732644024605 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein3.svg0000664000175000017500000000613715167732644024411 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint8.svg0000664000175000017500000003274315167732644024613 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint6.svg0000664000175000017500000002556115167732644024611 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris6.svg0000664000175000017500000000266715167732644023232 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint2.svg0000664000175000017500000002115315167732644024576 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint2.svg0000664000175000017500000001321115167732644024425 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint7.svg0000664000175000017500000003057115167732644024607 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris5.svg0000664000175000017500000000266715167732644023231 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein11.svg0000664000175000017500000000614215167732644024464 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein2.svg0000664000175000017500000000613715167732644024410 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint0.svg0000664000175000017500000001321115167732644024423 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint5.svg0000664000175000017500000002420715167732644024604 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein6.svg0000664000175000017500000000613715167732644024414 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint11.svg0000664000175000017500000003574115167732644024666 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris2.svg0000664000175000017500000000266715167732644023226 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein4.svg0000664000175000017500000000613715167732644024412 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint14.svg0000664000175000017500000001762615167732644024673 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint10.svg0000664000175000017500000003471015167732644024660 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris0.svg0000664000175000017500000000202615167732644023211 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein5.svg0000664000175000017500000000613715167732644024413 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint9.svg0000664000175000017500000003374615167732644024620 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint12.svg0000664000175000017500000003647015167732644024667 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint5.svg0000664000175000017500000001321115167732644024430 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris8.svg0000664000175000017500000000267115167732644023227 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris4.svg0000664000175000017500000000266715167732644023230 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein9.svg0000664000175000017500000000614215167732644024413 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint1.svg0000664000175000017500000001321115167732644024424 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint13.svg0000664000175000017500000003754415167732644024673 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein8.svg0000664000175000017500000000614115167732644024411 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/voiceprint3.svg0000664000175000017500000001321115167732644024426 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingerprint1.svg0000664000175000017500000002071315167732644024576 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein1.svg0000664000175000017500000000613715167732644024407 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein7.svg0000664000175000017500000000613715167732644024415 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris11.svg0000664000175000017500000000267215167732644023302 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/iris1.svg0000664000175000017500000000266715167732644023225 0ustar fengfengukui-biometric-auth/polkit-agent/assets/biowaiting/fingervein10.svg0000664000175000017500000000614215167732644024463 0ustar fengfengukui-biometric-auth/polkit-agent/assets/arrow_right.svg0000664000175000017500000000124615167732630022354 0ustar fengfengukui-biometric-auth/polkit-agent/assets.qrc0000664000175000017500000001277715167732644020033 0ustar fengfeng assets/arrow_down.svg assets/arrow_right.svg assets/hide-password.png assets/show-password.png assets/biowaiting/fingerprint0.svg assets/biowaiting/fingerprint1.svg assets/biowaiting/fingerprint2.svg assets/biowaiting/fingerprint3.svg assets/biowaiting/fingerprint4.svg assets/biowaiting/fingerprint5.svg assets/biowaiting/fingerprint6.svg assets/biowaiting/fingerprint7.svg assets/biowaiting/fingerprint8.svg assets/biowaiting/fingerprint9.svg assets/biowaiting/fingerprint10.svg assets/biowaiting/fingerprint11.svg assets/biowaiting/fingerprint12.svg assets/biowaiting/fingerprint13.svg assets/biowaiting/fingerprint14.svg assets/biowaiting/fingervein0.svg assets/biowaiting/fingervein1.svg assets/biowaiting/fingervein2.svg assets/biowaiting/fingervein3.svg assets/biowaiting/fingervein4.svg assets/biowaiting/fingervein5.svg assets/biowaiting/fingervein6.svg assets/biowaiting/fingervein7.svg assets/biowaiting/fingervein8.svg assets/biowaiting/fingervein9.svg assets/biowaiting/fingervein10.svg assets/biowaiting/fingervein11.svg assets/biowaiting/iris0.svg assets/biowaiting/iris1.svg assets/biowaiting/iris2.svg assets/biowaiting/iris3.svg assets/biowaiting/iris4.svg assets/biowaiting/iris5.svg assets/biowaiting/iris6.svg assets/biowaiting/iris7.svg assets/biowaiting/iris8.svg assets/biowaiting/iris9.svg assets/biowaiting/iris10.svg assets/biowaiting/iris11.svg assets/biowaiting/voiceprint0.svg assets/biowaiting/voiceprint1.svg assets/biowaiting/voiceprint2.svg assets/biowaiting/voiceprint3.svg assets/biowaiting/voiceprint4.svg assets/biowaiting/voiceprint5.svg assets/biowaiting/voiceprint6.svg assets/biowaiting/voiceprint7.svg assets/biowaiting/dark/fingerprint0.svg assets/biowaiting/dark/fingerprint1.svg assets/biowaiting/dark/fingerprint2.svg assets/biowaiting/dark/fingerprint3.svg assets/biowaiting/dark/fingerprint4.svg assets/biowaiting/dark/fingerprint5.svg assets/biowaiting/dark/fingerprint6.svg assets/biowaiting/dark/fingerprint7.svg assets/biowaiting/dark/fingerprint8.svg assets/biowaiting/dark/fingerprint9.svg assets/biowaiting/dark/fingerprint10.svg assets/biowaiting/dark/fingerprint11.svg assets/biowaiting/dark/fingerprint12.svg assets/biowaiting/dark/fingerprint13.svg assets/biowaiting/dark/fingerprint14.svg assets/biowaiting/dark/fingervein0.svg assets/biowaiting/dark/fingervein1.svg assets/biowaiting/dark/fingervein2.svg assets/biowaiting/dark/fingervein3.svg assets/biowaiting/dark/fingervein4.svg assets/biowaiting/dark/fingervein5.svg assets/biowaiting/dark/fingervein6.svg assets/biowaiting/dark/fingervein7.svg assets/biowaiting/dark/fingervein8.svg assets/biowaiting/dark/fingervein9.svg assets/biowaiting/dark/fingervein10.svg assets/biowaiting/dark/fingervein11.svg assets/biowaiting/dark/iris0.svg assets/biowaiting/dark/iris1.svg assets/biowaiting/dark/iris2.svg assets/biowaiting/dark/iris3.svg assets/biowaiting/dark/iris4.svg assets/biowaiting/dark/iris5.svg assets/biowaiting/dark/iris6.svg assets/biowaiting/dark/iris7.svg assets/biowaiting/dark/iris8.svg assets/biowaiting/dark/iris9.svg assets/biowaiting/dark/iris10.svg assets/biowaiting/dark/iris11.svg assets/biowaiting/dark/voiceprint0.svg assets/biowaiting/dark/voiceprint1.svg assets/biowaiting/dark/voiceprint2.svg assets/biowaiting/dark/voiceprint3.svg assets/biowaiting/dark/voiceprint4.svg assets/biowaiting/dark/voiceprint5.svg assets/biowaiting/dark/voiceprint6.svg assets/biowaiting/dark/voiceprint7.svg src/main.qss ukui-biometric-auth/polkit-agent/i18n_ts/0000775000175000017500000000000015167732644017271 5ustar fengfengukui-biometric-auth/polkit-agent/i18n_ts/ru.ts0000664000175000017500000002362415167732644020276 0ustar fengfeng BioAuthWidget Form форма BioDevicesWidget Form форма FullScreenBackground Authentication Ð�утентификациÑ� MainWindow Form форма Biometric БиометричеÑ�кие Details Детали Polkit.subject-pid: Polkit.subject-PID: Vendor: Производитель: Description: ОпиÑ�ание: Polkit.caller-pid: Polkit.caller-PID: Action: ДейÑ�твие: Cancel Отмена Authenticate проверÑ�ть подлинноÑ�ть Authentication Ð�утентификациÑ� in authentication, please wait... в аутентификации, пожалуйÑ�та, подождите ... An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. Приложение пытаетÑ�Ñ� выполнить дейÑ�твие, требующее привилегий. ДлÑ� выполнениÑ� Ñ�того дейÑ�твиÑ� требуетÑ�Ñ� аутентификациÑ�. Password: Пароль: Authentication failed, please try again. Ошибка аутентификации. ПожалуйÑ�та, попробуйте еще раз. Please enter your password or enroll your fingerprint use password Account locked, days left hours left minutes left seconds left Password cannot be empty Use password Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Failed to verify %1, you still have %2 verification opportunities Input Password Failed to verify %1, please enter password to unlock Unable to verify %1, please enter password to unlock A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. _Password: _Password: Abnormal network This operation requires the administrator's authorization. Please enter your password to allow this operation. Insert the ukey into the USB port Enter the ukey password Input your password to authentication Close Acquisition failure Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" wechat Use the bound %1 scanning code to authorization PolkitListener Another client is already authenticating, please try again later. Другой клиент уже аутентифицируетÑ�Ñ�, повторите попытку позже. Authentication failure, please try again. Ошибка аутентификации, повторите попытку. Password input error! QObject Cancel Отмена ukui-biometric-auth/polkit-agent/i18n_ts/de.ts0000664000175000017500000005355115167732644020242 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication Authentifizierung LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication Authentifizierung Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form More 更多 Restart é‡�新开始 Password 密ç � Biometric Biometrisch use password Passwort verwenden DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel Abbrechen Authenticate Beglaubigen Use password Passwort verwenden Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Versuchen Sie es in %1 Minuten erneut. Please try again in %1 seconds. Bitte versuchen Sie es in %1 Sekunden erneut. Account locked permanently. Das Konto wurde dauerhaft gesperrt. Password cannot be empty Das Kennwort darf nicht leer sein. Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities %1 konnte nicht verifiziert werden, Sie haben immer noch %2 Überprüfungsmöglichkeiten An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: Passwort: Please enter your password or enroll your fingerprint Bitte geben Sie Ihr Passwort ein oder registrieren Sie Ihren Fingerabdruck wechat Use the bound %1 scanning code to authorization Abnormal network Ungewöhnliches Netzwerk This operation requires the administrator's authorization. Please enter your password to allow this operation. Für diesen Vorgang ist die Autorisierung des Administrators erforderlich. Bitte geben Sie Ihr Passwort ein, um diesen Vorgang zuzulassen. _Password: _Passwort: _Password: _Passwort: Authentication failed, please try again. Authentifizierung fehlgeschlagen, bitte versuchen Sie es erneut. days left Verbleibende Tage Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock %1 konnte nicht verifiziert werden, bitte geben Sie das Kennwort zum Entsperren ein Unable to verify %1, please enter password to unlock %1 kann nicht verifiziert werden, bitte geben Sie das Kennwort zum Entsperren ein NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. Ein Programm versucht, eine Aktion auszuführen, für die Berechtigungen erforderlich sind. Zum Ausführen der Aktion ist eine Autorisierung erforderlich. Input Password Passwort eingeben Insert the ukey into the USB port Enter the ukey password Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure hours left Verbleibende Stunden minutes left Noch Minuten seconds left Verbleibende Sekunden Input your password to authentication Verify face recognition or enter password to unlock Überprüfen Sie die Gesichtserkennung oder geben Sie das Passwort ein, um zu entsperren Press fingerprint or enter password to unlock Drücken Sie den Fingerabdruck oder geben Sie das Passwort ein, um zu entsperren Verify voiceprint or enter password to unlock Überprüfen Sie den Stimmabdruck oder geben Sie das Passwort ein, um zu entsperren Verify finger vein or enter password to unlock Überprüfen Sie die Fingervene oder geben Sie das Passwort ein, um zu entsperren Verify iris or enter password to unlock Überprüfen Sie die Iris oder geben Sie das Passwort ein, um zu entsperren Use the bound wechat scanning code or enter the password to unlock Verwenden Sie den gebundenen Wechat-Scan-Code oder geben Sie das Passwort zum Entsperren ein Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, Konto gesperrt, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. Ein anderer Client authentifiziert sich bereits, bitte versuchen Sie es später noch einmal. Authentication failure, please try again. Authentifizierungsfehler, bitte versuchen Sie es erneut. Password input error! Fehler bei der Passworteingabe! Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/ky.ts0000664000175000017500000005646315167732644020302 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication راستىنى دالىلدۅ LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication راستىنى دالىلدۅ Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form جادىبال More 更多 Restart é‡�新开始 Password 密ç � Biometric بىئولەگىيەلىك ۅزگۅچۅلۉگۉ ىشتەتىش use password جاشىرۇۇن نومۇر ىشتەتىش DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel ارعادان قالتىرىش Authenticate Û‡Ù‚Û‡Ù‚ بەرۉۉ Use password جاشىرۇۇن نومۇر ىشتەتىش ارقىلۇۇ دالىلدۅ Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Ùª1 مىنۇت ىچىندە قايرا سىناپ باعىڭ. Please try again in %1 seconds. Ùª1 سىكونت ىچىندە قايرا سىناپ باعىڭ. Account locked permanently. ەسابات تۉبۅلۉك قۇلۇپلىنىدۇ. Password cannot be empty جاشىرۇۇن نومۇردۇ بوش ،بەكەر قويۇشقا بولبويت Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities Ùª1 نى دالىلدۅ جەڭىلۉۉ بولدۇ ØŒ سىزدە داعى Û•Ù„Û• Ùª2 دالىلدۅ مۅۅرتۉ بار An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: جاشىرۇۇن نومۇر Please enter your password or enroll your fingerprint جاشىرۇۇن نومۇرۇڭۇزدۇ كىرگىزىڭ كۅرۉنۉشتۅرۉ بارماق ئىزىڭىزنى تونۇتۇڭ wechat Use the bound %1 scanning code to authorization Abnormal network بۅتۅنچۅ تور This operation requires the administrator's authorization. Please enter your password to allow this operation. بۇل ماشقۇلدانۇۇ باشقارۇۇچۇنۇن Û‡Ù‚Û‡Ù‚ بەرۉۉنۉ تالاپ جاسايت .جاشىرۇۇن نومۇردۇ كىيىرىپ بي قاتىمقى ماشقۇلدانۇۇ نىڭ الىپ بÛ�رىلىشىغا جول قويۇڭ. _Password: جاشىرۇۇن نومۇر _Password: جاشىرۇۇن نومۇر Authentication failed, please try again. دالىلدۅ جەڭىلۉۉ بولدۇ ØŒ قايرا سىناڭ days left 1 كۉندۅن كىيىن سىناپ باعىڭ Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock Ùª1 نى دالىلدۅ جەڭىلۉۉ بولدۇ ØŒ سىرلۇۇ نومۇر كىرگىزىڭ Unable to verify %1, please enter password to unlock Ùª1 نى دالىلدۅۅگۅ ايلاسىز، جاشىرۇۇن نومۇردۇ كىيىرىپ قۇلۇپنى اچىڭ NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. بىر پراگرامما Û‡Ù‚Û‡Ù‚ تالاپ جاسايتۇرعان قىيمىلدى جاسووعو ئۇرۇنماقتا. بۇل قىيمىلدى اتقارماق جاسوو ،اتقارۇۇ Û‰Ú†Û‰Ù† Û‡Ù‚Û‡Ù‚ تالاپ جاسايت . Input Password جاشىرۇۇن نومۇر كىرگىزۉۉ Insert the ukey into the USB port ukey نى USB ووزۇنا Ú†Û�تىپ قويۇڭ Enter the ukey password ukey جاشىرۇۇن نومۇرۇن كىرگىزىڭ Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure hours left بىر سائەتتىن كىيىن اچىلات minutes left بىر مىنۇتتان كىيىن اچىلات seconds left بىر سەكۇنتتان كىيىن اچىلات Input your password to authentication جاشىرۇۇن نومۇردۇ كىيىرىپ كۉبۅلۉك دالىلدۅ. Verify face recognition or enter password to unlock چىراي تاانىشتى دالىلدۅ كۅرۉنۉشتۅرۉ جاشىرۇۇن نومۇر كىرگىزۉۉ ارقىلۇۇ قۇلپ اچۇۇ Press fingerprint or enter password to unlock بارماق ىزىن باسۇۇدا كۅرۉنۉشتۅرۉ جاشىرۇۇن نومۇر كىرگىزۉۉ ارقىلۇۇ قۇلپ اچۇۇ Verify voiceprint or enter password to unlock دووش ىزىن دالىلدۅ كۅرۉنۉشتۅرۉ جاشىرۇۇن نومۇر كىرگىزۉۉ ارقىلۇۇ قۇلپ اچۇۇ Verify finger vein or enter password to unlock بارماق ئزى ارقىلۇۇ انىقتاش كۅرۉنۉشتۅرۉ جاشىرۇۇن نومۇر كىرگىزۉۉ ارقىلۇۇ قۇلپ اچۇۇ Verify iris or enter password to unlock Iris نى انىقتاش كۅرۉنۉشتۅرۉ جاشىرۇۇن نومۇر كىرگىزۉۉ ارقىلۇۇ قۇلپ اچۇۇ Use the bound wechat scanning code or enter the password to unlock بايلانعان ئۈندىدارنى ىسكاننىردوو قۇپۇيا نومۇرۇ كۅرۉنۉشتۅرۉ جاشىرۇۇن نومۇرۇن كىيىرىپ قۇلپ اچۇۇ Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, ىشتەتىش نومۇرۇڭۇز قۇلۇپتالىپ قالدى Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. داعى بىر سووداگەر ØŒ جولووچۇ دالىلدەپ جاتات، سەل تۇرۇپ قايرا سىناڭ. Authentication failure, please try again. دالىلدۅ جەڭىلۉۉ بولدۇ ØŒ قايرا سىناڭ. Password input error! كىيىرگەن جاشىرۇۇن نومۇر قاتاا بولدۇ Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/zh_CN.ts0000664000175000017500000005263315167732644020653 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication 授æ�ƒ LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication 授æ�ƒ Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form More 更多 Restart é‡�新开始 Password 密ç � Biometric 使用生物识别 use password 使用密ç �验è¯� DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel å�–消 Authenticate 授æ�ƒ Use password 使用密ç �验è¯� Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. 请%1分钟å�Žå†�试 Please try again in %1 seconds. 请%1ç§’å�Žå†�试 Account locked permanently. è´¦å�·å·²è¢«æ°¸ä¹…é”�定 Password cannot be empty 密ç �ä¸�能为空 Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities 验è¯�%1失败,您还有%2次å°�试机会 An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: 密ç �: Please enter your password or enroll your fingerprint 请输入密ç �或者录入指纹 wechat 微信 Use the bound %1 scanning code to authorization %1扫ç �以授æ�ƒ Abnormal network 网络异常 This operation requires the administrator's authorization. Please enter your password to allow this operation. 本次æ“�作需è¦�通过管ç�†å‘˜çš„æŽˆæ�ƒæ‰�能继续执行,请输入密ç �以å…�许本次æ“�作。 _Password: 密ç �: _Password: 密ç �: Authentication failed, please try again. 认è¯�失败,请é‡�试。 days left 天å�Žè§£é”� Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock 验è¯�%1失败,请输入密ç �è§£é”� Unable to verify %1, please enter password to unlock 无法验è¯�%1,请输入密ç �è§£é”� NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作,è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Input Password 输入密ç � Insert the ukey into the USB port 请将安全密钥æ�’å…¥USB端å�£ Enter the ukey password 输入安全密钥密ç � Close 关闭 Enter the two-factor authentication (2FA) OTP token for the administrator "%1" 输入管ç�†å‘˜"%1"å�Œå› å­�认è¯�OTP动æ€�å�£ä»¤ Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" 输入管ç�†å‘˜"%1"å�Œå› å­�认è¯�OTP动æ€�å�£ä»¤ Enter the two-factor authentication (2FA) security key for the administrator "%1" 输入管ç�†å‘˜"%1"å�Œå› å­�认è¯�安全密钥 Enter the two-factor authentication (2FA) security key for the user "%1" 输入用户"%1"å�Œå› å­�认è¯�安全密钥 Facial recognition to authorization 识别人脸以授æ�ƒ Fingerprint recognition to authorization 识别指纹以授æ�ƒ Voiceprint recognition to authorization 识别声纹以授æ�ƒ Finger veins recognition to authorization 识别指é�™è„‰ä»¥æŽˆæ�ƒ Iris recognition to authorization 识别虹膜以授æ�ƒ Use the bound wechat scanning code to authorization 微信扫ç �以授æ�ƒ Acquisition failure 获å�–失败 hours left å°�æ—¶å�Žè§£é”� minutes left 分钟å�Žè§£é”� seconds left ç§’å�Žè§£é”� Input your password to authentication 输入密ç �以授æ�ƒ Verify face recognition or enter password to unlock 验è¯�人脸识别或输入密ç �è§£é”� Press fingerprint or enter password to unlock 按压指纹或输入密ç �è§£é”� Verify voiceprint or enter password to unlock 验è¯�声纹或输入密ç �è§£é”� Verify finger vein or enter password to unlock 验è¯�指é�™è„‰æˆ–输入密ç �è§£é”� Verify iris or enter password to unlock 验è¯�虹膜或输入密ç �è§£é”� Use the bound wechat scanning code or enter the password to unlock 使用绑定的微信扫ç �或输入密ç �è§£é”� Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, 账户已é”�定, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. 有å�¦å¤–一个客户端正在认è¯�,请ç¨�å�Žé‡�试。 Authentication failure, please try again. 认è¯�失败,请é‡�试。 Password input error! 密ç �输入错误ï¼� Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/kk.ts0000664000175000017500000005573615167732644020266 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication شىندىقتى دالەلدەۋ LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication شىندىقتى دالەلدەۋ Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form كەستە More 更多 Restart é‡�新开始 Password 密ç � Biometric بىئولەگىيەلىك ەرەكشەلىكتى ٸستەتۋ use password قۇپيا نومەر ٸستەتۋ DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel كۇشىنەن قالدىرۋ Authenticate ۇقىق بەرۋ Use password قۇپيا نومەر ٸستەتۋ ارقىلى دالەلدەۋ Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Ùª1 مينۋت ٸشٸندە قاتە سىناپ كور. Please try again in %1 seconds. Ùª1 سەكونت ٸشٸندە قاتە سىناپ كور. Account locked permanently. ەسەپات ماڭگىلىك قۇلىپتالادى. Password cannot be empty قۇپيا نۇمىردى بوس قويۋعا بولمايدى Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities Ùª1 نى دالەلدەۋ جەڭىلىپ قالدى، سىزدە جانەدە Ùª2 دالەلدەۋ ورايى بار An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: قۇپيا نومەر Please enter your password or enroll your fingerprint قۇپيا نۇمىرىڭىزدى كىرگىزىڭىز ياكي بارماقشى ئىزىڭىزنى تونۇتۇڭ wechat Use the bound %1 scanning code to authorization Abnormal network بينورمال تور This operation requires the administrator's authorization. Please enter your password to allow this operation. Ù†Û‡ جوبالاۋ باسقارعٸشتٸڭ ۇقىق بىرىستى تالاپ ىستەيدى.قۇپيا نۇمىردى كىرەۈزۈپ بي رەتكى جوبالاۋنىڭ الىپ بÛ�رىلىشىغا جول قويىڭىز. _Password: قۇپيا نومەر _Password: قۇپيا نومەر Authentication failed, please try again. دالەلدەۋ جەڭىلىپ قالدى، قاتە سىناڭ days left 1 كۇننەن كەيىن سناپ كور Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock Ùª1 نى دالەلدەۋ جەڭىلىپ قالدى، قۇپيا نومەر كىرگىزىڭىز Unable to verify %1, please enter password to unlock Ùª1 نى دالەلدەۋگە امالسٸز، قۇپيا نۇمىردى كىرەۈزۈپ قۇلىبىن ٴٸشڭٸز NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. بٸر پٸروگٸرامما ۇقىق تالاپ ىستەيتىن ارەكەتتى ىستەۋگە ئۇرۇنماقتا. Ù†Û‡ ارەكەتتى اتقار ەتۋ ٷشٸن ۇقىق تالاپ ىستەيدى. Input Password قۇپيا نومەر كىرگىزۋ Insert the ukey into the USB port ukey نى USB اۋزىنا Ú†Û�تىپ قويىڭىز Enter the ukey password ukey قۇپيا نۇمىردى كىرگىزىڭىز Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure hours left بٸر ساعاتتان كەيىن اشٸلدٸ minutes left بٸر مينوتتىن كەيىن اشٸلدٸ seconds left بٸر سەكونتىن كەيىن اشٸلدٸ Input your password to authentication قۇپيا نۇمىردى كىرەۈزۈپ ازاماتتىق كۋالىك دالەلدەۋ. Verify face recognition or enter password to unlock چىراي تانىسن دالەلدەۋ ياكي قۇپيا نومەر كىرگىزۋ ارقىلى قۇلىپ ٸشٸۋ Press fingerprint or enter password to unlock بارماقشى ٴٸزدٸ باسٸۋ ياكي قۇپيا نومەر كىرگىزۋ ارقىلى قۇلىپ ٸشٸۋ Verify voiceprint or enter password to unlock اۋا ٴٸزدٸ دالەلدەۋ ياكي قۇپيا نومەر كىرگىزۋ ارقىلى قۇلىپ ٸشٸۋ Verify finger vein or enter password to unlock بارماقشى ٴٸزٸ ارقىلى انىقتاۋ ياكي قۇپيا نومەر كىرگىزۋ ارقىلى قۇلىپ ٸشٸۋ Verify iris or enter password to unlock Iris نى انىقتاۋ ياكي قۇپيا نومەر كىرگىزۋ ارقىلى قۇلىپ ٸشٸۋ Use the bound wechat scanning code or enter the password to unlock بايلانعان ئۈندىدارنى كەسكىندەۋ بەلگىسى ياكي قۇپيا نۇمىردى كىرەۈزۈپ قۇلىپ ٸشٸۋ Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, ٸستەتۋ نومەرىڭىز قۇلىپتانىپ قالدى Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. جانە بٸر قاريدار دالەلدەپ جاتىر، سەل تۇرٸپ قاتە سىناڭ. Authentication failure, please try again. دالەلدەۋ جەڭىلىپ قالدى، قاتە سىناڭ. Password input error! كىرگىزگەن قۇپيا نومەر قاتە قالدى Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/tr.ts0000664000175000017500000004167615167732644020304 0ustar fengfeng BioAuthWidget Retry Yeniden Dene BioDevices FingerPrint Parmak İzi FingerVein Damar İzi Iris Göz Face Yüz Tanıma VoicePrint Ses İzi FullScreenBackground Authentication Kimlik DoÄŸrulama MainWindow Authentication Kimlik DoÄŸrulama Failed to verify %1, please enter password to unlock Unable to verify %1, please enter password to unlock wechat Use the bound %1 scanning code to authorization Failed to verify %1, you still have %2 verification opportunities Abnormal network This operation requires the administrator's authorization. Please enter your password to allow this operation. A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. Input Password Insert the ukey into the USB port Enter the ukey password Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure Account locked, days left hours left minutes left seconds left Password cannot be empty Input your password to authentication Use password Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Form More Daha Fazla Restart Yeniden BaÅŸlat Password Parola Biometric Biyometrik DeviceType: Aygıt Türü: Back Geri Details Ayrıntılar Action Id: İşlem KimliÄŸi: Description: Açıklama: Polkit.subject-pid: Polkit.subject-pid: Retry Yeniden Dene Device types: Aygıt türü: Vendor: Vendor: Action: Eylem: Polkit.caller-pid: Polkit.caller-pid: Cancel İptal Authenticate Kimlik DoÄŸrulaması use password Auth Kimlik DoÄŸrulaması Please enter your password or enroll your fingerprint in authentication, please wait... kimlik doÄŸrulanırken lütfen bekleyin ... An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. Bir uygulama, ayrıcalıklar gerektiren bir eylem gerçekleÅŸtirmeye çalışıyor. Bu iÅŸlemi gerçekleÅŸtirmek için kimlik doÄŸrulaması gerekiyor. Password: Parola: _Password: _Parola: _Password: _Parola: Authentication failed, please try again. Kimlik doÄŸrulama baÅŸarısız, lütfen tekrar deneyin. Authentication failed, please try again Kimlik doÄŸrulama baÅŸarısız, lütfen tekrar deneyin PolkitListener Another client is already authenticating, please try again later. BaÅŸka bir hesap zaten kimlik doÄŸrulaması yapıyor, lütfen daha sonra tekrar deneyin. Authentication failure, please try again. Kimlik doÄŸrulama hatalı, lütfen tekrar deneyin. Password input error! Account locked %1 minutes due to %2 fail attempts %2 baÅŸarısız denemeden dolayı hesap %1 dakika kilitlendi Authentication failure,there are still %1 remaining opportunities Kimlik doÄŸrulama hatası, %1 hakkınız kaldı QObject FingerPrint Parmak İzi FingerVein Damar İzi Iris Göz Face Yüz Tanıma VoicePrint Ses İzi Cancel İptal ukui-biometric-auth/polkit-agent/i18n_ts/bo.ts0000664000175000017500000002775515167732644020261 0ustar fengfeng FullScreenBackground Authentication MainWindow Form Biometric use password Cancel Authenticate Insert the ukey into the USB port Enter the ukey password Close Failed to verify %1, please enter password to unlock Unable to verify %1, please enter password to unlock Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Failed to verify %1, you still have %2 verification opportunities Acquisition failure Please enter your password or enroll your fingerprint This operation requires the administrator's authorization. Please enter your password to allow this operation. A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. Password: _Password: _Password: Account locked, days left hours left minutes left seconds left Password cannot be empty Input your password to authentication Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Use password Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Input Password wechat Use the bound %1 scanning code to authorization Abnormal network Authentication failed, please try again. PolkitListener Another client is already authenticating, please try again later. Authentication failure, please try again. Password input error! ukui-biometric-auth/polkit-agent/i18n_ts/ug.ts0000664000175000017500000005614515167732644020267 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication راستىنى دەلىللەش LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication راستىنى دەلىللەش Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form جەدۋەل More 更多 Restart é‡�新开始 Password 密ç � Biometric بىئولەگىيەلىك ئالاھىدىلىكنى ئىشلىتىش use password مەخپىي نومۇر ئىشلىتىش DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel ئەمەلدىن قالدۇرۇش Authenticate ھوقۇق بÛ�رىش Use password مەخپىي نومۇر ئىشلىتىش ئارقىلىق دەلىللەش Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Ùª1 مىنۇت ئىچىدە قايتا سىناپ بÛ�قىڭ. Please try again in %1 seconds. Ùª1 سÛ�كۇنت ئىچىدە قايتا سىناپ بÛ�قىڭ. Account locked permanently. Ú¾Û�سابات Ù…Û•Ú­Ú¯ÛˆÙ„ÛˆÙƒ قۇلۇپلىنىدۇ. Password cannot be empty مەخپىي نومۇرنى بوش قويۇشقا بولمايدۇ Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities Ùª1 نى دەلىللەش مەغلۇپ بولدى، سىزدە يەنىلا Ùª2 دەلىللەش پۇرسىتى بار An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: مەخپىي نومۇر Please enter your password or enroll your fingerprint مەخپىي نومۇرىڭىزنى كىرگۈزۈڭ ياكى بارماق ئىزىڭىزنى تونۇتۇڭ wechat Use the bound %1 scanning code to authorization Abnormal network بىنورمال تور This operation requires the administrator's authorization. Please enter your password to allow this operation. بۇ مەشغۇلات باشقۇرغۇچىنىڭ ھوقۇق بÛ�رىشىنى تەلەپ قىلىدۇ.مەخپىي نومۇرنى كىرگۈزۈپ بي Ù‚Û�تىمقى مەشغۇلاتنىڭ ئÛ�لىپ بÛ�رىلىشىغا يول قويۇڭ. _Password: مەخپىي نومۇر _Password: مەخپىي نومۇر Authentication failed, please try again. دەلىللەش مەغلۇپ بولدى، قايتا سىناڭ days left 1 كۈندىن ÙƒÛ�يىن سىناب بÛ�قىڭ Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock Ùª1 نى دەلىللەش مەغلۇپ بولدى، مەخپى نۇمۇر كىرگۈزۈڭ Unable to verify %1, please enter password to unlock Ùª1 نى دەلىللەشكە ئامالسىز، مەخپىي نومۇرنى كىرگۈزۈپ قۇلۇپنى ئÛ�Ú†Ù‰Ú­ NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. بىر پروگرامما ئىمتىياز تەلەپ قىلىدىغان ھەرىكەتنى قىلىشقا ئۇرۇنماقتا. بۇ ھەرىكەتنى ئىجرا قىلىش ئۈچۈن ھوقۇق تەلەپ قىلىدۇ. Input Password ئىم كىرگۈزۈش Insert the ukey into the USB port ukey نى USB ئÛ�غىزىغا Ú†Û�تىپ قويۇڭ Enter the ukey password ukey مەخپىي نومۇرىنى كىرگۈزۈڭ Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure hours left بىر سائەتتىن ÙƒÛ�يىن ئÛ�چىلىدۇ minutes left بىر مىنۇتتىن ÙƒÛ�يىن ئÛ�چىلىدۇ seconds left بىر سÛ�كۇنتتىن ÙƒÛ�يىن ئÛ�چىلىدۇ Input your password to authentication مەخپىي نومۇرنى كىرگۈزۈپ كىملىك دەلىللەش. Verify face recognition or enter password to unlock چىراي تونۇشنى دەلىللەش ياكى مەخپىي نومۇر كىرگۈزۈش ئارقىلىق Ù‚Û‡Ù„Û‡Ù¾ ئÛ�چىش Press fingerprint or enter password to unlock بارماق ئىزىنى بÛ�سىش ياكى مەخپىي نومۇر كىرگۈزۈش ئارقىلىق Ù‚Û‡Ù„Û‡Ù¾ ئÛ�چىش Verify voiceprint or enter password to unlock ئاۋاز ئىزىنى دەلىللەش ياكى مەخپىي نومۇر كىرگۈزۈش ئارقىلىق Ù‚Û‡Ù„Û‡Ù¾ ئÛ�چىش Verify finger vein or enter password to unlock بارماق ئىزى ئارقىلىق ئÛ�نىقلاش ياكى مەخپىي نومۇر كىرگۈزۈش ئارقىلىق Ù‚Û‡Ù„Û‡Ù¾ ئÛ�چىش Verify iris or enter password to unlock Iris نى ئÛ�نىقلاش ياكى مەخپىي نومۇر كىرگۈزۈش ئارقىلىق Ù‚Û‡Ù„Û‡Ù¾ ئÛ�چىش Use the bound wechat scanning code or enter the password to unlock باغلانغان ئۈندىدارنى سىكاننÛ�رلاش كودى ياكى مەخپىي نومۇرىنى كىرگۈزۈپ Ù‚Û‡Ù„Û‡Ù¾ ئÛ�چىش Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, ئىشلىتىش نومۇرىڭىز قۇلۇپلىنىپ قالدى Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. ÙŠÛ•Ù†Û• بىر Ø®Û�رىدار دەلىللەۋاتىدۇ، سەل تۇرۇپ قايتا سىناڭ. Authentication failure, please try again. دەلىللەش مەغلۇپ بولدى، قايتا سىناڭ. Password input error! كىرگۈزگەن مەخپىي نومۇر خاتا بولدى Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/pt.ts0000664000175000017500000002303615167732644020270 0ustar fengfeng BioAuthWidget Form Formato BioDevicesWidget Form Formato FullScreenBackground Authentication Autenticação MainWindow Form Formato Biometric Biométrico Details Detalhes Polkit.subject-pid: Polkit.subject-pid: Vendor: Fornecedor: Description: Descrição: Polkit.caller-pid: Polkit.caller-pid: Action: Açao: Cancel Cancelar Authenticate Autenticar Authentication Autenticação in authentication, please wait... na autenticação, por favor aguarde ... An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. Um aplicativo está tentando executar uma ação que requer privilégios. A autenticação é necessária para executar esta ação. Password: Senha: Authentication failed, please try again. Autenticação falhou. Por favor, tente novamente. Please enter your password or enroll your fingerprint use password Account locked, days left hours left minutes left seconds left Password cannot be empty Use password Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Failed to verify %1, you still have %2 verification opportunities Input Password Failed to verify %1, please enter password to unlock Unable to verify %1, please enter password to unlock A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. _Password: _Password: Abnormal network This operation requires the administrator's authorization. Please enter your password to allow this operation. Insert the ukey into the USB port Enter the ukey password Input your password to authentication Close Acquisition failure Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" wechat Use the bound %1 scanning code to authorization PolkitListener Another client is already authenticating, please try again later. Outro cliente já está autenticando, por favor, tente novamente mais tarde. Authentication failure, please try again. Falha de autenticação, por favor, tente novamente. Password input error! QObject Cancel Cancelar ukui-biometric-auth/polkit-agent/i18n_ts/bo_CN.ts0000664000175000017500000006446715167732644020642 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication བདེན་དཔང་ར་སྤྲོདà¼� LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication དབང་བསà¾�ུརà¼� Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form རེའུ་མིག More 更多 Restart é‡�新开始 Password 密ç � Biometric སà¾�ྱེ་དངོས་སྒྲིག་ཆསà¼� use password གསང་གྲངས་སྤྱད་དེ་བཤེར་དགོསà¼� DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel ཕྱིར་འà½�ེནà¼� Authenticate བདེན་དཔང་ར་སྤྲོད་བྱ་དགོས Use password གསང་གྲངས་སྤྱད་དེ་བཤེར་དགོསà¼� Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. སà¾�ར་མ་%1འགོར་རྗེས་ཡང་བསà¾�ྱར་ཚོད་ལྟ་བྱསà¼� Please try again in %1 seconds. དུས་ཚོད་སà¾�ར་ཆ་%1འགོར་རྗེས་ཡང་བསà¾�ྱར་ཚོད་ལྟ་བྱེད་རོགསà¼� Account locked permanently. དུས་གà½�ན་དུ་ཟྭ་བརྒྱབ་པའི་རྩིས་à½�ོà¼� Password cannot be empty གསང་གྲངས་སྟོང་པ་ཡིན་མི་སྲིདà¼� Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities %1ལ་ཞིབ་བཤེར་བྱེད་མ་à½�ུབ་ནà¼� à½�ྱེད་ཚོར་ད་དུང་%2ལ་ཞིབ་བཤེར་བྱེད་པའི་གོ་སà¾�བས་ཡོདà¼� An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: གསང་གྲངས་ནིà¼� Please enter your password or enroll your fingerprint གསང་གྲངས་ནང་འཇུག་གམ་ཡང་ནà¼�འཛུབ་རིས་ཕབ་འཇུག་གནང་རོགསà¼� wechat འཕྲིན་ཕྲནà¼� Use the bound %1 scanning code to authorization བཀྱིགས་བཀོད་བྱས་པའི་བརྒྱ་ཆ་1བཀོལ་ནས་དབང་ཆ་བསà¾�ུར་བà¼� Abnormal network རྒྱུན་ལྡན་མིན་པའི་དྲ་ This operation requires the administrator's authorization. Please enter your password to allow this operation. à½�ེངས་འདིའི་བཀོལ་སྤྱོད་ལ་དོ་དམ་པས་དབང་སà¾�ུར་ན་གཞི་ནས་མུ་མà½�ུད་ལག་སྟར་བྱེད་à½�ུབà¼� གསང་གྲངས་ནང་འཇུག་བྱས་ན་à½�ེངས་འདིའི་བཀོལ་སྤྱོད་བྱས་ཆོག _Password: གསང་གྲངསà¼�: _Password: གསང་གྲངསà¼�: Authentication failed, please try again. ར་སྤྲོད་མ་à½�ུབà¼� ཡང་བསà¾�ྱར་ཚོད་ལེན་བྱེད་རོགསà¼�。 days left ཉིན་དུ་མའི་རྗེས་སུ་à½�་ཕྱེà¼� Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock %1ལ་ཞིབ་བཤེར་བྱེད་མ་à½�ུབ་ནà¼� གསང་གྲངས་ནང་འཇུག་བྱས་ནས་ཟྭ་རྒྱག་རོགསà¼� Unable to verify %1, please enter password to unlock %1ལ་ཞིབ་བཤེར་བྱེད་à½�བས་བྲལ་བ་དང་à¼� གསང་གྲངས་ནང་འཇུག་བྱས་ནས་ཟྭ་རྒྱག་རོགསà¼� NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. བ་རིམ་གཅིག་གིས་à½�ྱད་དབང་དགོས་པའི་འགུལ་སྟངས་ཚོད་ལེན་བྱེད་སà¾�བསà¼� དབང་སà¾�ུར་རྗེས་འགུལ་སྟངས་དེ་ལག་སྟར་བྱེད་དགོས་ Input Password གསང་གྲངས་ནང་འཇུག Insert the ukey into the USB port བདེ་འཇགས་ཀྱི་གསང་བའི་ལྡེ་མིག་དེ་USBཡི་སྣེ་འདྲེན་དུ་འཇུག་རོགསà¼� Enter the ukey password གསང་བའི་ཨང་གྲངས་ནང་འཇུག་བྱེད་པà¼� Close རྒྱག་པà¼� Enter the two-factor authentication (2FA) OTP token for the administrator "%1" དོ་དམ་པའི"བརྒྱ་ཆ་1"ཡི་རྒྱུ་རà¾�ྱེན་གཉིས་ཀྱི་à½�ོབ་à½�ང་ཚོད་ལྟས་ར་སྤྲོདà¼� (2FAA)བཀའ་རྒྱ་བྱང་བུà¼� Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" སྤྱོད་མà½�ན་གྱི་"བརྒྱ་ཆ་1"ཡི་རྒྱུ་རà¾�ྱེན་གཉིས་ཀྱི་à½�ོབ་à½�ང་ཚོད་ལྟས་ར་སྤྲོདà¼�(2FAA)འགུལ་རྣམ་བཀའ་རྒྱ་བྱང་བུà¼� Enter the two-factor authentication (2FA) security key for the administrator "%1" དོ་དམ་པ་"1"ཡི་རྒྱུ་རà¾�ྱེན་གཉིས་ཀྱི་à½�ོབ་à½�ང་ཚོད་ལྟས་ར་སྤྲོདà¼�(2FA)བདེ་འཇགས་ཀྱི་ལྡེ་མིག Enter the two-factor authentication (2FA) security key for the user "%1" སྤྱོད་མà½�ན་གྱི་"བརྒྱ་ཆ་1"ཡི་རྒྱུ་རà¾�ྱེན་གཉིས་ཀྱི་à½�ོབ་à½�ང་ཚོད་ལྟས་ར་སྤྲོདà¼�(2FA) Facial recognition to authorization གདོང་རིས་ངོས་བཟུང་ནས་དབང་སà¾�ུརà¼� Fingerprint recognition to authorization འཛུབ་རིས་ངོས་བཟུང་ནས་དབང་སà¾�ུརà¼� Voiceprint recognition to authorization སྒྲ་རིས་ངོས་བཟུང་ནས་དབང་སà¾�ུརà¼� Finger veins recognition to authorization འཛུབ་མོའི་སྡོད་རྩ་ངོས་བཟུང་ནས་དབང་སà¾�ུརà¼� Iris recognition to authorization འཇའ་སà¾�ྱི་ངོས་བཟུང་ནས་དབང་སà¾�ུརà¼� Acquisition failure ཕམ་ཉེས་བྱུང་བ་རེདà¼� hours left ཆུ་ཚོད་གཅིག་གི་རྗེས་ནས་à½�་ཕྱེà¼� minutes left སà¾�ར་མ་à½�་ཤས་རྗེས་à½�་ཕྱེà¼� seconds left སà¾�ར་ཆ་à½�་ཤས་རྗེས་à½�་ཕྱེà¼� Input your password to authentication གསང་གྲངས་ནང་འཇུག་བྱས་ནས་དབང་སà¾�ུརà¼� Verify face recognition or enter password to unlock དཔང་མིའི་གདོང་ལ་ཞིབ་བཤེར་བྱེད་པའམ་ཡང་ན་གསང་གྲངས་བསྣན་ནས་ཟྭ་འབྱེད་པà¼� Press fingerprint or enter password to unlock མཛུབ་རིས་མནན་པའམ་ཡང་ན་གསང་གྲངས་བསྣན་ནས་ཟྭ་འབྱེད་པà¼� Verify voiceprint or enter password to unlock སྒྲ་རིས་ར་སྤྲོད་བྱེད་པའམ་ཡང་ན་གསང་གྲངས་བསྣན་ནས་ཟྭ་འབྱེད་པà¼� Verify finger vein or enter password to unlock ཚོད་ལྟས་ར་སྤྲོད་བྱེད་པ་ནི་སྡོད་རྩ་དང་གསང་གྲངས་བསྣན་ནས་ཟྭ་འབྱེད་པ་དེ་ཡིནà¼� Verify iris or enter password to unlock འཇའ་སà¾�ྱི་ར་སྤྲོད་བྱེད་པའམ་ཡང་ན་གསང་གྲངས་བསྣན་ནས་ཟྭ་འབྱེད་པà¼� Use the bound wechat scanning code or enter the password to unlock སྦྲེལ་ཡོད་པའི་སà¾�ད་འཕྲིན་གྱི་ཨང་གྲངས་སམ་གསང་གྲངས་བསྣན་ནས་ཟྭ་འབྱེད་དགོསà¼� Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, རྩིས་à½�ོ་à½�་རྒྱབ་ཟིནà¼� Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. མà½�ོ་མà½�ན་སྣེ་གཞན་ཞིག་ར་སྤྲོད་བཞིན་པའི་སྒང་རེདà¼� ཡད་ཙམ་ནས་ཚོད་ལེན་བྱེད་རོགསà¼� Authentication failure, please try again. ར་སྤྲོད་མ་à½�ུབà¼� ཡང་བསà¾�ྱར་ཚོད་ལེན་བྱེད་རོགསà¼�。 Password input error! གསང་གྲངས་ནོར་འདུག Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/vi.ts0000664000175000017500000005437115167732644020271 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication Ủy quyá»�n LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication 授æ�ƒ Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form More 更多 Restart é‡�新开始 Password 密ç � Biometric Sinh trắc há»�c use password Sá»­ dụng mật khẩu để xác thá»±c DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel Há»§y Authenticate Ủy quyá»�n Use password Sá»­ dụng mật khẩu Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Vui lòng thá»­ lại sau %1 phút. Please try again in %1 seconds. Vui lòng thá»­ lại sau%1 giây. Account locked permanently. Tài khoản bị khóa vÄ©nh viá»…n. Password cannot be empty Mật khẩu không được trống Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities Không xác minh được %1, bạn vẫn có %2 cÆ¡ há»™i xác minh An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: Mật khẩu: Please enter your password or enroll your fingerprint Vui lòng nhập mật khẩu hoặc dấu vân tay cá»§a bạn wechat Trò chuyện Use the bound %1 scanning code to authorization Sá»­ dụng mã quét %1 ràng buá»™c để á»§y quyá»�n Abnormal network Lá»—i mạng This operation requires the administrator's authorization. Please enter your password to allow this operation. Thao tác này cần có sá»± á»§y quyá»�n từ cá»§a quản trị viên má»›i có thể được thá»±c hiện tiếp tục. Vui lòng nhập mật khẩu để cho phép thao tác lần này. _Password: Mật khẩu: _Password: _Mật khẩu: Authentication failed, please try again. Xác thá»±c không thành công, vui lòng thá»­ lại. days left Số ngày còn lại Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock Không xác minh được %1, vui lòng nhập mật khẩu để mở khóa Unable to verify %1, please enter password to unlock Không thể xác thá»±c %1,vui lòng nhập mật khẩu để mở khóa NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. Má»™t chương trình Ä‘ang cố gắng thá»±c hiện má»™t thao tác đòi há»�i đặc quyá»�n, yêu cầu á»§y quyá»�n để thá»±c hiện hành động này. Input Password Nhập mật khẩu Insert the ukey into the USB port Cắm ukey vào cổng USB Enter the ukey password Nhập mật khẩu UKey Close Thoát Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Nhập mã thông báo OTP xác thá»±c hai yếu tố (2FA) cho quản trị viên "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Nhập mã thông báo động OTP xác thá»±c hai yếu tố (2FA) cho ngưá»�i dùng "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Nhập khóa bảo mật xác thá»±c hai yếu tố (2FA) cho quản trị viên "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Nhập khóa bảo mật xác thá»±c hai yếu tố (2FA) cho ngưá»�i dùng "%1" Facial recognition to authorization Nhận dạng khuôn mặt để á»§y quyá»�n Fingerprint recognition to authorization Nhận dạng vân tay để á»§y quyá»�n Voiceprint recognition to authorization Nhận dạng dấu vân giá»�ng để á»§y quyá»�n Finger veins recognition to authorization Nhận dạng tÄ©nh mạch ngón tay để á»§y quyá»�n Iris recognition to authorization Nhận dạng mống mắt để á»§y quyá»�n Use the bound wechat scanning code to authorization 微信扫ç �以授æ�ƒ Acquisition failure Lá»—i khi tải hours left Số giá»� còn lại minutes left Mở khóa sau phút seconds left Mở khóa sau giây Input your password to authentication Nhập mật khẩu để á»§y quyá»�n Verify face recognition or enter password to unlock 验è¯�人脸识别或输入密ç �è§£é”� Press fingerprint or enter password to unlock 按压指纹或输入密ç �è§£é”� Verify voiceprint or enter password to unlock 验è¯�声纹或输入密ç �è§£é”� Verify finger vein or enter password to unlock 验è¯�指é�™è„‰æˆ–输入密ç �è§£é”� Verify iris or enter password to unlock 验è¯�虹膜或输入密ç �è§£é”� Use the bound wechat scanning code or enter the password to unlock 使用绑定的微信扫ç �或输入密ç �è§£é”� Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, Tài khoản đã bị khóa, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. Má»™t máy khách khác Ä‘ang xác thá»±c, vui lòng thá»­ lại sau. Authentication failure, please try again. Xác thá»±c thất bại, vui lòng thá»­ lại. Password input error! Lá»—i nhập mật khẩu! Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/mn.ts0000664000175000017500000006532015167732644020261 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication ᠡᠷᠬᠡ ᠤᠯᠭᠤᠬᠤ Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form ᠬᠡᠯᠪᠡᠷᠢ More 更多 Restart é‡�新开始 Password 密ç � Biometric ᠪᠢᠤᠯᠤᠬᠢ ᠵᠢᠨ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ use password ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠬᠡᠷᠡᠭᠯᠡᠵᠤ ᠪᠠᠳᠤᠯᠠᠭᠠᠵᠢᠭᠤᠯᠬᠤ DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel ᠦᠬᠡᠢᠰᠬᠡᠬᠦ Authenticate ᠡᠷᠬᠡ ᠤᠯᠭᠤᠬᠤ Use password ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠬᠡᠷᠡᠭᠯᠡᠵᠤ ᠪᠠᠳᠤᠯᠠᠭᠠᠵᠢᠭᠤᠯᠬᠤ Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. %1 ᠮᠢᠨᠦ᠋ᠲ᠎ᠦᠨ ᠳᠠᠷᠠᠭ᠎ᠠ ᠳᠠᠬᠢᠵᠤ ᠳᠤᠷᠱᠢᠭᠠᠷᠠᠢ᠃ Please try again in %1 seconds. %1 ᠮᠢᠨᠦ᠋ᠲ᠎ᠦᠨ ᠳᠠᠷᠠᠭ᠎ᠠ ᠳᠠᠬᠢᠵᠤ ᠳᠤᠷᠱᠢᠭᠠᠷᠠᠢ᠃ Account locked permanently. ᠳᠠᠩᠰᠠ ᠨᠢᠭᠡᠨᠳᠡ ᠦᠨᠢᠳᠡ ᠤᠨᠢᠰᠤᠯᠠᠭᠳᠠᠪᠠ᠃ Password cannot be empty ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠬᠤᠭᠤᠰᠤᠨ ᠪᠠᠢᠵᠤ ᠪᠤᠯᠬᠤ ᠦᠬᠡᠢ Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities %1᠎ᠶᠢᠨ/᠎ᠦᠨ ᠰᠢᠯᠭᠠᠨ ᠪᠠᠢᠴᠠᠭᠠᠯᠳᠠ ᠢᠯᠠᠭᠳᠠᠪᠠ á ‚ ᠲᠠ ᠪᠠᠰᠠ%2 ᠤᠳᠠᠭᠠᠨ᠎ᠤ ᠳᠤᠷᠱᠢᠬᠤ ᠵᠠᠪᠱᠢᠶᠠᠨ ᠲᠠᠢ An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋᠄ Please enter your password or enroll your fingerprint ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠪᠤᠶᠤ ᠬᠤᠷᠤᠭᠤᠨ ᠤ᠋ ᠤᠷᠤᠮ ᠵᠢᠨᠨ ᠤᠷᠤᠭᠤᠯᠤᠭᠠᠷᠠᠢ wechat ᠸᠢᠴᠠᠲ Use the bound %1 scanning code to authorization %1 ᠺᠣᠳ᠋ ᠰᠢᠷᠪᠢᠵᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ Abnormal network ᠲᠤᠷ ᠰᠦᠯᠵᠢᠶ᠎ᠡ ᠬᠡᠪ ᠤ᠋ᠨ ᠪᠤᠰᠤ This operation requires the administrator's authorization. Please enter your password to allow this operation. ᠳᠤᠰ ᠤᠳᠠᠭᠠᠨ ᠤ᠋ ᠠᠵᠢᠯᠯᠠᠬᠤᠢ ᠵᠢᠨ ᠬᠠᠮᠢᠶᠠᠷᠤᠭᠴᠢ ᠵᠢᠨ ᠡᠷᠬᠡ ᠤᠯᠭᠤᠯᠳᠠ ᠪᠡᠷ á °á  á ¶á ¢ ᠦᠷᠬᠦᠯᠵᠢᠯᠡᠨ ᠬᠡᠷᠡᠭᠵᠢᠬᠦᠯᠦᠨ᠎ᠡ᠂ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠵᠢᠨᠨ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠳᠤᠰ ᠠᠵᠢᠯᠯᠠᠬᠤᠢ ᠵᠢ ᠵᠦᠪᠰᠢᠶᠡᠷᠡᠭᠡᠷᠡᠢ᠃ _Password: ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋: _Password: ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋(_P): Authentication failed, please try again. ᠬᠡᠷᠡᠴᠢᠯᠡᠵᠤ ᠴᠢᠳᠠᠭᠰᠠᠨ ᠦᠬᠡᠢ᠂ ᠳᠠᠬᠢᠵᠤ ᠳᠤᠷᠰᠢᠭᠠᠷᠠᠢ᠃ days left ᠡᠳᠦᠷ ᠤ᠋ᠨ ᠳᠠᠷᠠᠭ᠎ᠠ ᠤᠨᠢᠰᠤ ᠳᠠᠢᠯᠤᠨ᠎ᠠ Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock %1á Žá ¶á ¢/á Žá ¢ ᠪᠠᠳᠤᠯᠭᠠᠵᠢᠭᠤᠯᠬᠤ á  á ·á ­á Žá   ᠦᠬᠡᠢ á ‚ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Unable to verify %1, please enter password to unlock %1á Žá ¶á ¢/á Žá ¢ ᠪᠠᠳᠤᠯᠭᠠᠵᠢᠭᠤᠯᠬᠤ á  á ·á ­á Žá   ᠦᠬᠡᠢ á ‚ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. ᠨᠢᠭᠡ ᠫᠡᠷᠦᠭᠷᠡᠮ á ¶á  á ­ ᠨᠢᠭᠡ ᠤᠨᠠᠴᠠ ᠡᠷᠬᠡ ᠬᠡᠷᠡᠭᠰᠡᠬᠦ ᠬᠦᠳᠡᠯᠬᠡᠬᠡᠨ ᠢ᠋ ᠬᠡᠷᠡᠭᠵᠢᠬᠦᠯᠬᠦ ᠪᠡᠷ ᠳᠤᠷᠰᠢᠵᠤ ᠪᠠᠢᠨ᠎ᠠ᠂ ᠳᠤᠰ ᠬᠦᠳᠡᠯᠬᠡᠬᠡᠨ ᠢ᠋ ᠬᠦᠢᠴᠡᠳᠬᠡᠬᠦ ᠡᠷᠬᠡ ᠤᠯᠭᠤᠬᠤ ᠵᠢ ᠱᠠᠭᠠᠷᠳᠠᠵᠤ ᠪᠠᠢᠨ᠎ᠠ᠃ Input Password ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠣᠷᠣᠭᠤᠯᠬᠤ Insert the ukey into the USB port ᠠᠮᠤᠷ ᠳᠦᠪᠰᠢᠨ ᠤ᠋ ᠨᠢᠭᠤᠴᠠ ᠳᠦᠯᠬᠢᠬᠦᠷ ᠢ᠋ USB ᠦᠵᠦᠭᠦᠷ ᠲᠤ᠌ ᠬᠠᠪᠴᠢᠭᠤᠯᠤᠭᠠᠷᠠᠢ Enter the ukey password ᠠᠮᠤᠷ ᠳᠦᠪᠰᠢᠨ ᠤ᠋ ᠨᠢᠭᠤᠴᠠ ᠳᠦᠯᠬᠢᠬᠦᠷ ᠤ᠋ᠨ ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠢ᠋ ᠣᠷᠣᠭᠤᠯᠬᠤ Close ᠬᠠᠭᠠᠬᠤ Enter the two-factor authentication (2FA) OTP token for the administrator "%1" "%1" ᠬᠠᠮᠢᠶᠠᠷᠤᠭᠴᠢ ᠵᠢᠨ ᠬᠣᠣᠰ ᠹᠠᠺᠲ᠋ᠣᠷ᠎ᠤ᠋ᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠯ OTP ᠬᠥᠳᠡᠯᠦᠩᠭᠦᠢ ᠠᠮᠠᠨ ᠳᠣᠬᠢᠶ᠎ᠠ ᠵᠢ ᠣᠷᠣᠭᠤᠯᠬᠤ Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" "%1" ᠬᠠᠮᠢᠶᠠᠷᠤᠭᠴᠢ ᠵᠢᠨ ᠬᠣᠣᠰ ᠹᠠᠺᠲ᠋ᠣᠷ᠎ᠤ᠋ᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠯ OTP ᠬᠥᠳᠡᠯᠦᠩᠭᠦᠢ ᠠᠮᠠᠨ ᠳᠣᠬᠢᠶ᠎ᠠ ᠵᠢ ᠣᠷᠣᠭᠤᠯᠬᠤ Enter the two-factor authentication (2FA) security key for the administrator "%1" "%1" ᠬᠠᠮᠢᠶᠠᠷᠤᠭᠴᠢ ᠵᠢᠨ ᠬᠣᠣᠰ ᠹᠠᠺᠲ᠋ᠣᠷ᠎ᠤ᠋ᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠯ ᠤ᠋ᠨ ᠠᠮᠤᠷ ᠳᠦᠪᠰᠢᠨ ᠤ᠋ ᠨᠢᠭᠤᠴᠠ ᠳᠦᠯᠬᠢᠬᠦᠷ ᠢ᠋ ᠣᠷᠣᠭᠤᠯᠬᠤ Enter the two-factor authentication (2FA) security key for the user "%1" "%1" ᠬᠠᠮᠢᠶᠠᠷᠤᠭᠴᠢ ᠵᠢᠨ ᠬᠣᠣᠰ ᠹᠠᠺᠲ᠋ᠣᠷ᠎ᠤ᠋ᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠯ ᠤ᠋ᠨ ᠠᠮᠤᠷ ᠳᠦᠪᠰᠢᠨ ᠤ᠋ ᠨᠢᠭᠤᠴᠠ ᠳᠦᠯᠬᠢᠬᠦᠷ ᠢ᠋ ᠣᠷᠣᠭᠤᠯᠬᠤ Facial recognition to authorization ᠴᠢᠷᠠᠢ ᠪᠡᠷ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ Fingerprint recognition to authorization ᠬᠤᠷᠤᠭᠤᠨ ᠣᠷᠣᠮ ᠵᠢᠡᠷ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ Voiceprint recognition to authorization ᠳᠠᠭᠤᠨ ᠣᠷᠣᠮ ᠵᠢᠡᠷ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ Finger veins recognition to authorization ᠨᠠᠮᠵᠢᠭᠤᠨ ᠰᠤᠳᠠᠰᠤ ᠪᠡᠷ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ Iris recognition to authorization ᠴᠡᠴᠡᠬᠡᠢ ᠪᠡᠷ ᠢᠯᠭᠠᠨ ᠳᠠᠨᠢᠬᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠬᠤ Acquisition failure ᠣᠯᠵᠤ ᠴᠢᠳᠠᠭᠰᠠᠨ ᠥᠬᠡᠢ hours left ᠨᠢᠭᠡ á ´á  á ­ ᠤ᠋ᠨ ᠳᠠᠷᠠᠭ᠎ᠠ ᠤᠨᠢᠰᠤ ᠳᠠᠢᠯᠤᠨ᠎ᠠ minutes left ᠮᠢᠨᠦ᠋ᠲ ᠤ᠋ᠨ ᠳᠠᠷᠠᠭ᠎ᠠ ᠤᠨᠢᠰᠤ ᠳᠠᠢᠯᠤᠨ᠎ᠠ seconds left ᠰᠸᠺᠦᠨ᠋ᠲ ᠤ᠋ᠨ ᠳᠠᠷᠠᠭ᠎ᠠ ᠤᠨᠢᠰᠤ ᠳᠠᠢᠯᠤᠨ᠎ᠠ Input your password to authentication ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠣᠷᠣᠭᠤᠯᠵᠤ ᠡᠷᠬᠡ ᠣᠯᠭᠣᠨ᠎ᠠ Verify face recognition or enter password to unlock ᠨᠢᠭᠤᠷ ᠱᠢᠷᠪᠢᠵᠤ ᠪᠠᠳᠤᠯᠭᠠᠵᠢᠭᠤᠯᠬᠤ ᠪᠤᠶᠤ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Press fingerprint or enter password to unlock ᠬᠤᠷᠤᠭᠤᠨ᠎ᠤ ᠤᠷᠤᠮ ᠳᠠᠷᠤᠬᠤ ᠪᠤᠶᠤ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Verify voiceprint or enter password to unlock ᠳᠠᠭᠤ᠎ᠪᠠᠷ ᠰᠢᠯᠭᠠᠨ ᠪᠠᠳᠤᠯᠠᠬᠤ ᠪᠤᠶᠤ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Verify finger vein or enter password to unlock ᠬᠤᠷᠤᠭᠤᠨ᠎ᠤ ᠨᠠᠮᠵᠢᠭᠤᠨ ᠰᠤᠳᠠᠯ᠎ᠢᠶᠠᠷ ᠰᠢᠯᠭᠠᠨ ᠪᠠᠳᠤᠯᠠᠬᠤ ᠪᠤᠶᠤ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Verify iris or enter password to unlock ᠰᠤᠯᠤᠩᠭ᠎ᠠ ᠪᠦᠷᠬᠦᠪᠴᠢ᠎ᠶᠢ ᠰᠢᠯᠭᠠᠨ ᠪᠠᠳᠤᠯᠠᠬᠤ ᠪᠤᠶᠤ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Use the bound wechat scanning code or enter the password to unlock ᠤᠶᠠᠭᠰᠠᠨ ᠸᠢᠴᠠᠲ᠎ᠢᠶᠠᠷ ᠺᠤᠳ᠋ ᠱᠢᠷᠪᠢᠬᠦ᠌ ᠪᠤᠶᠤ ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠤᠷᠤᠭᠤᠯᠵᠤ ᠤᠨᠢᠰᠤ᠎ᠶᠢ ᠳᠠᠢᠯᠤᠭᠠᠷᠠᠢ Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, ᠳᠠᠨᠭᠰᠠ ᠵᠢ ᠨᠢᠬᠡᠨᠳᠡ ᠤᠨᠢᠰᠤᠯᠠᠪᠠ Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. ᠦᠬᠡᠷ᠎ᠡ ᠨᠢᠭᠡ ᠬᠡᠷᠡᠭᠯᠡᠭᠴᠢ ᠵᠢᠨ ᠦᠵᠦᠬᠦᠷᠯᠢᠭ ᠢ᠋ á ¶á  á ­ ᠨᠤᠳᠠᠯᠠᠵᠤ ᠪᠠᠢᠨ᠎ᠠ᠂ ᠤᠳᠠᠰᠬᠢᠭᠠᠳ ᠳᠠᠬᠢᠨ ᠳᠤᠷᠰᠢᠭᠠᠷᠠᠢ᠃ Authentication failure, please try again. ᠬᠡᠷᠡᠴᠢᠯᠡᠵᠤ ᠴᠢᠳᠠᠭᠰᠠᠨ ᠦᠬᠡᠢ᠂ ᠳᠠᠬᠢᠵᠤ ᠳᠤᠷᠰᠢᠭᠠᠷᠠᠢ᠃ Password input error! ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ ᠢ᠋ ᠪᠤᠷᠤᠭᠤ ᠤᠷᠤᠭᠤᠯᠪᠠ! Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/fr.ts0000664000175000017500000005343115167732644020256 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication Authentification LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication Authentification Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form More 更多 Restart é‡�新开始 Password 密ç � Biometric Biométrique use password Utiliser le mot de passe DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel Annuler Authenticate Authentifier Use password Utiliser le mot de passe Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Veuillez réessayer dans %1 minutes. Please try again in %1 seconds. Veuillez réessayer dans %1 secondes. Account locked permanently. Compte verrouillé définitivement. Password cannot be empty Le mot de passe ne peut pas être vide Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities Échec de la vérification %1, vous avez encore %2 possibilités de vérification An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: Mot de passe: Please enter your password or enroll your fingerprint Veuillez saisir votre mot de passe ou enregistrer votre empreinte digitale wechat Use the bound %1 scanning code to authorization Abnormal network Réseau anormal This operation requires the administrator's authorization. Please enter your password to allow this operation. Cette opération nécessite l’autorisation de l’administrateur. Veuillez saisir votre mot de passe pour autoriser cette opération. _Password: _Mot de passe: _Password: _Mot de passe: Authentication failed, please try again. L’authentification a échoué, veuillez réessayer. days left jours restants Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock Impossible de vérifier %1, veuillez entrer le mot de passe pour déverrouiller Unable to verify %1, please enter password to unlock Impossible de vérifier %1, veuillez entrer le mot de passe pour déverrouiller NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. Un programme tente d’effectuer une action qui nécessite des privilèges. Il nécessite une autorisation pour effectuer l’action. Input Password Mot de passe d’entrée Insert the ukey into the USB port Enter the ukey password Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure hours left Heures restantes minutes left minutes restantes seconds left secondes restantes Input your password to authentication Verify face recognition or enter password to unlock Vérifier la reconnaissance faciale ou saisir le mot de passe pour déverrouiller Press fingerprint or enter password to unlock Appuyez sur l’empreinte digitale ou entrez le mot de passe pour déverrouiller Verify voiceprint or enter password to unlock Vérifier l’empreinte vocale ou saisir le mot de passe pour déverrouiller Verify finger vein or enter password to unlock Vérifiez la veine du doigt ou entrez le mot de passe pour déverrouiller Verify iris or enter password to unlock Vérifiez l’iris ou entrez le mot de passe pour déverrouiller Use the bound wechat scanning code or enter the password to unlock Utilisez le code d’analyse wechat lié ou entrez le mot de passe pour déverrouiller Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, Compte verrouillé, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. Un autre client est déjà en train de s’authentifier, veuillez réessayer plus tard. Authentication failure, please try again. Échec de l’authentification, veuillez réessayer. Password input error! Erreur de saisie du mot de passe ! Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/es.ts0000664000175000017500000005313415167732644020256 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication Autenticación LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication Autenticación Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form Forma More 更多 Restart é‡�新开始 Password 密ç � Biometric Biométrico use password Usar contraseña DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel Cancelar Authenticate Autentificar Use password Usar contraseña Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. Inténtelo de nuevo en %1 minutos. Please try again in %1 seconds. Inténtelo de nuevo en %1 segundos. Account locked permanently. Cuenta bloqueada permanentemente. Password cannot be empty La contraseña no puede estar vacía Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities No se pudo verificar %1, todavía tiene %2 oportunidades de verificación An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: Contraseña: Please enter your password or enroll your fingerprint Ingrese su contraseña o registre su huella dactilar wechat Use the bound %1 scanning code to authorization Abnormal network Red anormal This operation requires the administrator's authorization. Please enter your password to allow this operation. Esta operación requiere la autorización del administrador. Introduzca su contraseña para permitir esta operación. _Password: _Contraseña: _Password: _Contraseña: Authentication failed, please try again. Error de autenticación, inténtelo de nuevo. days left Días restantes Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock No se pudo verificar %1, ingrese la contraseña para desbloquear Unable to verify %1, please enter password to unlock No se puede verificar %1, ingrese la contraseña para desbloquear NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. Un programa está intentando realizar una acción que requiere privilegios. Requiere autorización para realizar la acción. Input Password Contraseña de entrada Insert the ukey into the USB port Enter the ukey password Close Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization Fingerprint recognition to authorization Voiceprint recognition to authorization Finger veins recognition to authorization Iris recognition to authorization Acquisition failure hours left horas restantes minutes left Quedan minutos seconds left segundos restantes Input your password to authentication Verify face recognition or enter password to unlock Verifique el reconocimiento facial o ingrese la contraseña para desbloquear Press fingerprint or enter password to unlock Presione la huella dactilar o ingrese la contraseña para desbloquear Verify voiceprint or enter password to unlock Verifica la huella de voz o ingresa la contraseña para desbloquear Verify finger vein or enter password to unlock Verifique la vena del dedo o ingrese la contraseña para desbloquear Verify iris or enter password to unlock Verifique el iris o ingrese la contraseña para desbloquear Use the bound wechat scanning code or enter the password to unlock Use el código de escaneo de wechat vinculado o ingrese la contraseña para desbloquear Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, Cuenta bloqueada, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. Otro cliente ya se está autenticando, inténtelo de nuevo más tarde. Authentication failure, please try again. Error de autenticación, inténtelo de nuevo. Password input error! ¡Error de entrada de contraseña! Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/i18n_ts/zh_HK.ts0000664000175000017500000005241615167732644020654 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication 授權 LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication 授權 Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form More 更多 Restart é‡�新开始 Password 密ç � Biometric 使用生物識別 use password 使用密碼驗證 DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel å�–消 Authenticate 授權 Use password 使用密碼驗證 Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. è«‹%1分é�˜å�Žå†�試 Please try again in %1 seconds. è«‹%1秒後å†�試 Account locked permanently. 帳號已被永久鎖定 Password cannot be empty 密碼ä¸�能為空 Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities é©—è­‰%1失敗,您還有%2次嘗試機會 An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: 密碼: Please enter your password or enroll your fingerprint 請輸入密碼或者錄入指紋 wechat 微信 Use the bound %1 scanning code to authorization %1掃碼以授權 Abnormal network 網路異常 This operation requires the administrator's authorization. Please enter your password to allow this operation. 本次æ“�作需è¦�通é�Žç®¡ç�†å“¡çš„æŽˆæ¬Šæ‰�能繼續執行,請輸入密碼以å…�許本次æ“�作。 _Password: 密碼: _Password: 密碼: Authentication failed, please try again. èª�證失敗,請é‡�試。 days left 天å�Žè§£éŽ– Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock é©—è­‰%1失敗,請輸入密碼解鎖 Unable to verify %1, please enter password to unlock 無法驗證%1,請輸入密碼解鎖 NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. 一個程å¼�正試圖執行一個需è¦�特權的動作,è¦�求授權以執行該動作。 Input Password 輸入密碼 Insert the ukey into the USB port 請將安全金鑰æ�’å…¥USB埠 Enter the ukey password 輸入安全金鑰密碼 Close 關閉 Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization 識別人臉以授權 Fingerprint recognition to authorization 識別指紋以授權 Voiceprint recognition to authorization 識別è�²ç´‹ä»¥æŽˆæ¬Š Finger veins recognition to authorization 識別指é�œè„ˆä»¥æŽˆæ¬Š Iris recognition to authorization 識別虹膜以授權 Use the bound wechat scanning code to authorization 微信掃碼以授權 Acquisition failure ç�²å�–失敗 hours left å°�時後解鎖 minutes left 分é�˜å¾Œè§£éŽ– seconds left 秒後解鎖 Input your password to authentication 輸入密碼以èª�è­‰ Verify face recognition or enter password to unlock 驗證人臉識別或輸入密碼解鎖 Press fingerprint or enter password to unlock 按壓指紋或輸入密碼解鎖 Verify voiceprint or enter password to unlock é©—è­‰è�²ç´‹æˆ–輸入密碼解鎖 Verify finger vein or enter password to unlock 驗證指é�œè„ˆæˆ–輸入密碼解鎖 Verify iris or enter password to unlock 驗證虹膜或輸入密碼解鎖 Use the bound wechat scanning code or enter the password to unlock 使用ç¶�定的微信掃碼或輸入密碼解鎖 Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, 帳戶已鎖定, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. 有å�¦å¤–一個用戶端正在èª�證,請ç¨�後é‡�試。 Authentication failure, please try again. èª�證失敗,請é‡�試。 Password input error! 密碼輸入錯誤ï¼� Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/polkit-agent/data/0000775000175000017500000000000015167732644016715 5ustar fengfengukui-biometric-auth/polkit-agent/data/polkit-ukui-authentication-agent-1.desktop.in0000664000175000017500000001033315167732644027441 0ustar fengfeng[Desktop Entry] Name=PolicyKit Authentication Agent Name[ca]=Agent d'autenticació del PolicyKit Name[ca@valencia]=Agent d'autenticació del PolicyKit Name[cs]=Ověřovací agent PolicyKitu Name[da]=PolicyKit autentificeringsagent Name[de]=PolicyKit-Authentifizierungs-Agent Name[el]=ΠÏ�άκτοÏ�ας ταυτοποίησης PolicyKit Name[en_GB]=PolicyKit Authentication Agent Name[es]=Agente de autenticación de PolicyKit Name[et]=PolicyKiti autentimisagent Name[eu]=PolicyKit autentifikazio agentea Name[fi]=PolicyKit-tunnistautumisagentti Name[fr]=Agent d'authentification de « PolicyKit » Name[gl]=Axente de autenticación de PolicyKit Name[hu]=PolicyKit hitelesítési ügynök Name[id]=PolicyKit Authentication Agent Name[it]=Agente di autenticazione di PolicyKit Name[ko]=PolicyKit ì�¸ì¦� ì—�ì�´ì „트 Name[nl]=Authenticatieagent van PolicyKit Name[nn]=PolicyKit-autentiseringsagent Name[pa]=ਪਾਲਸੀਕਿਟ ਪਰਮਾਣਕਿਤਾ à¨�ਜੰਟ Name[pl]=UsÅ‚uga uwierzytelnienia PolicyKit Name[pt]=Agente de Autenticação do PolicyKit Name[pt_BR]=Agente de Autenticação do PolicyKit Name[ru]=Ð�гент аутентификации PolicyKit Name[sk]=Overovací dialóg PolicyKit Name[sl]=Overitveni posrednik PolicyKit Name[sr]=ПолиÑ�икитов агент за аутентификовање Name[sr@ijekavian]=ПолиÑ�икитов агент за аутентификовање Name[sr@ijekavianlatin]=PolicyKitov agent za autentifikovanje Name[sr@latin]=PolicyKitov agent za autentifikovanje Name[sv]=Policykit behörighetsmodul Name[tr]=PolicyKit Kimlik DoÄŸrulama Aracı Name[uk]=Ð�гент розпізнаваннÑ� PolicyKit Name[x-test]=xxPolicyKit Authentication Agentxx Name[zh_CN]=PolicyKit 认è¯�代ç�† Name[zh_TW]=PolicyKit èª�證代ç�†ç¨‹å¼� Name[ug_CN]=PolicyKit ئىسپات ۋاكالەتچىلىكى Name[kk_KZ]=PolicyKit دالەل ۆاكىلى Name[ky_KG]=PolicyKit ىسپات ۋاكالەتچىلىكى Comment=PolicyKit Authentication Agent Comment[ca]=Agent d'autenticació del PolicyKit Comment[ca@valencia]=Agent d'autenticació del PolicyKit Comment[cs]=Ověřovací agent PolicyKitu Comment[da]=PolicyKit autentificeringsagent Comment[de]=PolicyKit-Authentifizierungs-Agent Comment[el]=ΠÏ�άκτοÏ�ας ταυτοποίησης PolicyKit Comment[en_GB]=PolicyKit Authentication Agent Comment[es]=Agente de autenticación de PolicyKit Comment[et]=PolicyKiti autentimisagent Comment[eu]=PolicyKit autentifikazio agentea Comment[fi]=PolicyKit-tunnistautumisagentti Comment[fr]=Agent d'authentification de « PolicyKit » Comment[gl]=Axente de autenticación de PolicyKit Comment[hu]=PolicyKit hitelesítési ügynök Comment[id]=Agen Kewenangan PolicyKit Comment[it]=Agente di autenticazione di PolicyKit Comment[ko]=PolicyKit ì�¸ì¦� ì—�ì�´ì „트 Comment[nl]=Authenticatieagent van PolicyKit Comment[nn]=PolicyKit-autentiseringsagent Comment[pa]=ਪਾਲਸੀਕਿਟ ਪਰਮਾਣਕਿਤਾ à¨�ਜੰਟ Comment[pl]=UsÅ‚uga uwierzytelnienia PolicyKit Comment[pt]=Agente de Autenticação do PolicyKit Comment[pt_BR]=Agente de Autenticação do PolicyKit Comment[ru]=Ð�гент аутентификации PolicyKit Comment[sk]=Overovací dialóg PolicyKit Comment[sl]=Overitveni posrednik PolicyKit Comment[sr]=ПолиÑ�икитов агент за аутентификовање Comment[sr@ijekavian]=ПолиÑ�икитов агент за аутентификовање Comment[sr@ijekavianlatin]=PolicyKitov agent za autentifikovanje Comment[sr@latin]=PolicyKitov agent za autentifikovanje Comment[sv]=Policykit behörighetsmodul Comment[tr]=PolicyKit Kimlik DoÄŸrulama Aracı Comment[uk]=Ð�гент розпізнаваннÑ� PolicyKit Comment[x-test]=xxPolicyKit Authentication Agentxx Comment[zh_CN]=PolicyKit 认è¯�代ç�† Comment[zh_TW]=PolicyKit èª�證代ç�†ç¨‹å¼� Exec=${LIB_ARCH_PATH}/ukui-polkit/polkit-ukui-authentication-agent-1 Icon=ukui-polkit Terminal=false Type=Application Categories=System;Security; OnlyShowIn=UKUI;MATE X-UKUI-StartupNotify=false X-UKUI-AutoRestart=true X-UKUI-Autostart-Phase=Application NoDisplay=true X-DBUS-StartupType=Unique X-MATE-Autostart-Phase=Initialization X-MATE-StartupNotify=false X-MATE-AutoRestart=true X-KDE-Wayland-Interfaces=org_kde_plasma_window_management,org_kde_kwin_keystate ukui-biometric-auth/images/0000775000175000017500000000000015167732630014646 5ustar fengfengukui-biometric-auth/images/FingerPrint.png0000664000175000017500000004472515167732630017617 0ustar fengfeng‰PNG  IHDR  ‹Ïg- pHYs.#.#x¥?v9ðiTXtXML:com.adobe.xmp Adobe Photoshop CC 2017 (Windows) 2018-06-22T10:02:14+08:00 2018-07-02T11:05:22+08:00 2018-07-02T11:05:22+08:00 image/png 3 xmp.iid:d25dd608-d1a1-4345-8aed-f31ffb97fc5f adobe:docid:photoshop:bf20e7c4-7da4-11e8-92f2-d9e6550a8a6d xmp.did:3a170e97-9755-d640-8f8f-3f9b31c0e3ae created xmp.iid:3a170e97-9755-d640-8f8f-3f9b31c0e3ae 2018-06-22T10:02:14+08:00 Adobe Photoshop CC 2017 (Windows) saved xmp.iid:d25dd608-d1a1-4345-8aed-f31ffb97fc5f 2018-07-02T11:05:22+08:00 Adobe Photoshop CC 2017 (Windows) / 1 3000000/10000 3000000/10000 2 65535 160 160 4F 5 cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF_IDATxÚì�MvÛ6†ßädnm@Çê ÌÎ:iÅ 4®º‚È+¨²‚Â+(³‚Ð+(=Ö T:hg¥VPéhŸ´‚|^V4�HJußst;– ‰ï.€7ë¯}CÇúéÇÞ€å�¾þùwçl¼å�™uM1€,�u»zÇñë’±»W²d± f1€,ÈbY,�ŲX ‹d±:Õ;þNÏDHÿ,¾Fôï€ÍSw¶¥ïSúš8ìW"åO—TÁd€û/w/=*ý­2¤)�™îWâÀÞps‚îá C( �–Æ´! Ó[òÝ€�•€›¸ëá0èñ+�ù@ ¹ß ¼9׺Â]n5±�¬r¬8¡ÇÈÁÒþL�ÏŒû•ˆ‡ à¹%ßÇv,²vK ËXîXÄcôu»_‰¬å±@ºÆ›G1€h¿[ß�“Û±¼�.®ðÁâb&¥˜k{Åq‡¥‡)�/bÊ^ßâE†àíº¸mëÖâû Jaƒ‰Û^Xøhe½Œ÷+q(Õìª,]ÔWè¤÷“Q È:. ÆûŠ˜““�+Kø,ýlCÐy¸“U[XRBµ„TWJ<x<G�íJ±ÑûýJCÊ÷+‘ìW"ð€ç’u�“ûöÍÛÁ“ÞÅ&/Á~%�źeÌbY,�å·¸Ð>A]‡Ë¸½Š“�V³ÍÒc„óZ\•6ȧü¶gÆŸ,XeÕæ°Ÿ›µÕš LH°€/†y3C›*¦ “!Õõ8´×µâ¶;ÿÃx&ÕrÅðdÝBËýJÌ+~'ð�æ¿wÈ›2¼nN=K8JÍE’2¡ÇÔrØÞ·\Ý<€”DÄ¥‹ÿX5G<ž‰-Å}�¬Ñ ÈÃÒäS{ @ ÄÁ8ž �¼ƒ¤|‘wû•˜ÔXÊ‹Í)[.ð¶÷ï¦$«—@ßÐùq¿QÇ=‡ºåJÖ'²ˆ‡!øv ð-(N{¨¸xqÇ®i¹RéWYM#.[À ƒ7Bukþš’�Ì3K.P]Œ5ô@‚/ÕX½#] Èã›KN¤dm(6ÌÀË_œ€à»Ó\˜ùP‚vŠ#¨ggŽdác°ð}گIJKàT×N›•u 8hyS"ƒ 8P¥§ýJð2ÉF¤€¯5KàX³«Ò§Åï�Ö"“5Œ5czޯĂì¾Ï76‰…º%ºmD(#ŸÞ:Œu}¹É;½°Âí:Ç{äÖÞý•ÞÚù‚ùØaìºìß+{` |¡m)¢Tæ˜;¸×5}Ýâõ¦EÀ©opûM‰v”µÛ‚ûa¯$X²6à+m`ô›l)=2GÐËñäC Žgb àw_!ì;€™â¹À§K^äX2AGýy¥ ‰æÈ·`«‹�k|ññcßK4}P¾»�&¦ðs‹‹á‚›BÒ¸Šø³ê¦0.+Q†Êºßçbµ1`H– 6ÙnMÉ¢p±Wow"ë%*!ck¨ˆ [¯‹ÞjÕYDã:çx&RŠ=½˜!jCêêyâ^ÏÐ�ibD£ðƒÞûÈ—©ÈÁ¶äK´W÷šðá—!.^º…5!s´ÐºTÚëYV' Ò¥��>wöÜ,€ ¬O@%“Ì‹Êņç[œ¢ÉŽe„|¦'êçÍž_ô ídÃk‡ YˆI›±Ýx&"èÛžšÂ!_ry`ôr½õ¾@Jµ´¶”v4ä;ä…âíx&�¿ÉûÆ3‘Qš-àŒñºèúØR?`v9ž; o0Í¿з%)Ì£)¾K]àÃë o3d_[ò—8Ÿ€·š¦»P2"ŸrÓÍÆ¼·PÓ qD¾wô–ìþÂÊw?ún(DXH–ÑyšLÓ†µÙ¯DÀ1`÷Šð=™ÀGqÓâÒÞ¯DLkß#Ÿ Ü!ŸÿuÕyq½¬ãAßÖ„¨\ïš.®�å¼jaw<“¦î²Â|ç“+~ë|#…Õ8’k3ynÙrþNnì*jJˆ„ÆC° î@‘ân†3Âyq9hZ ¹ÐMWa„Ó2�BSŸ¶ïð@ÊüTAwdðܹâ¹GäÍ ‡¿çòša]b¡Jd¼‰}Ù!U~ð* ¢‚Ô©3†`p:€ºÐ–­ìý,µØGP/„ÿÏ�gâ^ÏÞLÇ3ú°· Ñ#ÿsL<ÎÛÔ­ÊÝÕǧ–µÃi»ÝƒÃû�ã¼™¶²^HŸÑV QŒ>#vÁf%kSê2–ᆠ„Ô]üYÓµÃ÷}F0Ù*£Áøýè±" ÀæZ(b¿Ô\UÒr¨‹7 ¼/°ßßYñÛÚ%U‘¦‰A¢e¦0€õîïÞàƒ6wW7WL±×¿à­‘o&ù„|¯¾µÂjúÍ¡ä£úý¹¸Ï6Ïá$Ä¢¢¿Î$ŽºwÈ «ˆäÛh$5 Åßþ0ž‰Ô´Yb¿ÛñLlðºt47¸ù)ã¿ÏļÏ� }wÁòlºvW~ÞÑäâSûQúñ3òÙ…Ú I#€z«ÝÏ–1ÙYLg0þ§Sä½°‚½Pã~Wp-b°ˆ¬ÝšÀ³Ú¡~¿ÚãÙ0N3¶Æ†ËñqȺ)4øpuàÞ¹HÍ÷+6™2#7Šdbaø|Õ{�vÁˆ'=^Z*t-vÁÐDa ÒžÀš&[mɺ†Èê?,S,öÇ6`½pU'fÏ=ø`1zîWN�œ*S�o¡ºILs¬6Í ¡k¢£™[Ý‚u›V¬®pja-kú¡˺)RX?í¢ ÍZ�”q`]¬_ õºßÈ&Y±L@|Œ9 i¼ ô§ -*¬ß V5.xk0Þ�ãÆhp¨KÝNY ÅóbËa M8nôÀÒñôÝ'ÏÑ,e÷éPÿ“Ìž³aÜsK;¨?Û÷Ñ`Ù¥€Ûj9ùF¸s0txNjnNB ÝÖ´¾ ò!ëà›h¬Ÿ­û ®45øÛκ³š¸•-`CÙî+@w!}oÒò?Wü,ËKkˆ+,�*[ÞØZ?�%K Ýpâ€e+‘:i°€f@‡ñ¨,fb3>4̺Àkˆ€svU§-m÷ñÓl’ùb`É–¶Ð2€ž«´'´êÜÝgÇmTω }f÷ëOìßyaXßÂá5…"†\„Âd¶€oýDWø–8ßeu1$Å~ e=‚.¤ÇÕk,¬Ï©qã ÜhdhÀ6Áiu„×Ûa˜,¶Þ!?0³ø›óÔwKZû-]¶¬ƒôý„¼¬÷W§#ò~@‹# ?°ÚÔ�g4†;S—]ñ:?»Hï½÷whIÈù¶¹Gø}ÙçÉ4†$K7Ái–ä‰3ßá&!Eë}ÒÒ6l²»^#Ÿò³rŸÔ�ŽgbyÍséÀvµ¡¸(C^jIÛ8Fa ¨ã¦YkCød«9€Þž˜~ ¢RÎ?Ò�¿ïà¦ãÐsPÂ.v9Ѐé³c›Ã7"wýe<i[~¬•�õŸNå–)€�èÒIN¬|:Ž•”¬U›pÐkÉÝ6»–7EW½VÄz§QVùGÇ”¦êÐ¥‹ÔÁõpÍß@{«!ßT¼p•mÄj)Χê>uÔl p¾ÓׇŽb΋jÐe˜Š³Û€¼->p|Ýç�.;AW§°K‡XËz¦"õmÆe�Ö€WÀ2w<5]@=?ý½ãëML¡©èðV½¿Äæ`n°9tœ®Wµf½ bëG+ôè°À©¸I`c9k,aY^œ˜îûÞ0òÂl}KÙ*,]3Ô Ë÷É>w*Ý$1 �mدD<ž‰Œ2aï§æzm)s-îâ NíH6|±SVäŸib>À¡Ëš²ç­"�y¦ä`ñZY|Õ è…ì;€:«s)ðFÈëpÓ6à“n¬/ªÄ@èŒpÚ~#°u\|Å–>Ôê–xÔÄxIÓŸ ‰5ñ¤3|±Ü‘bÔ7 ¾˜¸Û]Q‚€ù‰êu–DTd›�á3L(^È%oÀëºà"Ž9àÔ,º¥GÖfÝ�¦Ö¢Š,ú±m·Vaã0‚ô#£ÉêM+¬ì¼«>½Æ¤”yßU¼Æ|H ÍëôõÏ¿¿1€úäB º\$,ÆI½naMï†VFaÛ�/@õTØŽJ¶vUÞZ“è|K¿WX¼¨ÁVo:Ÿh¬áš\òáV¼Ù�h¹fRß ší3¨”bïÀ²¦²6Ö-sÒÿx/Õ$›®hõz0È.¸»x/í‹ 4茋l{0² ÖÇ_Oû•/}‘)û}�ó�@ãüy±}�nùœKûà—¶c½ãÂAëæ¤ú]Hà‘¯BKz0®-£|D^öao°o³û•ˆ©»å‘2ñAÃÈ…h'!¬ÛÈbY ‹Å²@‹d1€,ȾÎVÅÉ•ê6ij+~ª زسX «úÿ-Füã‹ p IEND®B`‚ukui-biometric-auth/images/ukui-loginopt-finger.svg0000664000175000017500000000457215167732630021455 0ustar fengfengukui-biometric-auth/images/Iris.png0000664000175000017500000005014315167732630016265 0ustar fengfeng‰PNG  IHDR  ‹Ïg- pHYs.#.#x¥?v9ðiTXtXML:com.adobe.xmp Adobe Photoshop CC 2017 (Windows) 2018-06-22T10:02:14+08:00 2018-07-02T11:06:22+08:00 2018-07-02T11:06:22+08:00 image/png 3 xmp.iid:b78bea26-9a1f-5a40-aa24-3f1baf8c43a2 adobe:docid:photoshop:e1fcfd40-7da4-11e8-92f2-d9e6550a8a6d xmp.did:26e0b17b-aa01-6343-8adb-ad9cb203136d created xmp.iid:26e0b17b-aa01-6343-8adb-ad9cb203136d 2018-06-22T10:02:14+08:00 Adobe Photoshop CC 2017 (Windows) saved xmp.iid:b78bea26-9a1f-5a40-aa24-3f1baf8c43a2 2018-07-02T11:06:22+08:00 Adobe Photoshop CC 2017 (Windows) / 1 3000000/10000 3000000/10000 2 65535 160 160 µe»N cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFíIDATxÚì�]¨#çyÇÿB³ëºíö¢k»Êj_l–µWë&E`¤£¥ ýZ-uÀ�¤gމi© ž…@n’î,õE¡†�ÓÒH`ç\å&`šB‚™#‘Tx±=‡“ Û+!bû¢�¥+/¾ðöBÏØsFï;Ÿï;_šöJGs4ïüÞçù?ÏûõÀýû÷QYeY™R5Ae€•UVVY`e€•åÏFãI·¬÷ö@™²àÑxR Ò�Ñi·ÌÜSÀ–t_vYžÙgJä!T;®—ûÌÜžJÿÝ¢ûÛ�'G ƒN»µ¨<`và©tg9¿rªèh4žL}îoI�Ìè´[Ó Àô¬FžálÀ¯_ï´[F�ák°ÉûÙ>½h  ÀÑx¢|Aäˆ<ƒYtH÷Ý'I±S6 `ˆP‹²ŠtN’¥…ðþ{â¢0Yr¡Øöùµ™K-°!F^Q h›%AhTFïéF@È™QãšØ` ÙI�¨yŒ ¹�z¶é£ó*ð⃘»°œÉë™®ú„cÓBmLM�8ÐÏ‹7Ì€Ôh¯·@«À‹Ô¦yD^›Þì´[úÆH¥•>½Uí´[V…T¬¶mPÔàE•Cò†‹��BîÀG³¢ŒP Œ™§«—ºY…äL¤öG§T^/�½›Eb—:€TT68½ñ€à«¼ž\mx‹§µ;í–ZZ ¾Ûœ· =n[0ý"PªN 5G㉠va9S ²á!™§Á�è™,J |©Ýheù|6J†7xPÁ—½‘æÛe¼u €Ež²˜Ð¾ÔÅne±õ¹TO¨TðUFžÐp�4yjžPŠ�'€+ø ›![X/“Iñ„Š„P+ø í m]Ž'4s‚iÈçv_) d=¯«$­ò ¹n³‚¯48ÙñE¹üh@¨¹i·vÚ­nõ8K™_1x Êš øŽ°ZÉUYñ³ã}Æ[B2cE@Ѱ>Ãb‰Œç™U&B«¹ƒnÛÂj(/;I÷±fVô‹ºR¿2®õ±š*ç¶mšPœ¾$÷kc}FE.¦zGµzOohP ®ÿÖò‚e3N§³,œÿ·ºU=ØÄj£$az0 €Öë}…H:¶&AÖ„ÿJ2Q6# mJØìùP_B�õfšq$W,iÑϺ¯‘GÝWïé5‚­K¡älN¾ÚÁh͇ú @º¯ÓniÒô ½×¨v”'èúôsµ Ïö€„½5êÓX#¹±•4ÇPÇú*¶ƒN»ÕÏ x}¬ªøq¡s´ÜÔ¥éÂh8·flFÐŽ~ÞÑ0Èc¨¦Q¯W¼ß¹Ón5¥HËüîæ-ô’¦Ó¼­ˆÙÑe¶ŒdÁ¥7›.ݹñ2̼…iN(Ž´´"*€C°gzë=½Kà…õv3òfN˜[dØaÜšt+Â÷7 Æil`}ÿÂH)*€¶'¬d’õR˜ÕBf¯ÎĊº�Z½§7]z5lØÞ`d}OŒ¬Ø„°„HPŧË*Ï¥Yp&ðŒYìÒå)r ]€wttlèYÖ]ÛßDĽ{â–ajXMN¤ôPºÞùÉyæ|¨›(�‘gTCjÛÌ@¤õ"Ž3Êõ•ä ÌàíSãOQR«÷tÄí¼‚Çr Õðt°gV»Ã¬A:h� 1òŠ‚÷‹> å]‚ä@êé†OÈÙHðÔé¤A l+%G�Ú¨÷t «É�~û6æC]Ш÷t‹<Â&Á§bU ¯Í‡º à‰ží˜Ö{º^y@~£jðßLñ€êh<òe‰KÝ¢e» Úé–+4]mÒá�ÈZ€á’Œ5ØÀó9Ëó™ÒCè�ï æÃã€ÚÔ€q>7aYɰAU¬ªè<ønR÷Âg �éSy3ëB/yCë|¨OçC½à y<¿°Üß8HáÓð GnmÆgûX€+e™ô"¶R…{ÿ!ä͵÷¢ôRšàWøoR‚ÁwÊhÈݲž#Dï*µÙ|¨7tú%A8(-€å®×s}~ÀÐ5û” nZ†ÕÜÎëú\þG8ìaUÄNÍ*)5˜éS^Ù›õf|}FƒÏ°*Èn¢©Xß:C£„k¦›Ë^�jiKªô”Kb¹}º†Í赡û"†âÐ!À.)K–.m‰ Ô$p.qBn3¤æÐ�´·Éð‘73±¾Vw'¬÷ryCÖ¢ó-·ë=Ý$P,)dZœÞµO!wÒƒjŒÐ«£2pÚA�ñ‚<&k_@§\c…ö\H¡áŽÞÛ�˜4hŒëè›:Ìñb^v5*0‰š`× /°)dç[RQôGSD©à”]Ö*ÿ’uVŸ®v~Xë«…èVSý픿ã]QÕ*ôóf! /y �2]Þnëý¨sõ80KO<\Ë95Ä_Õ6�ÞžÆENÛŸŠ)HB™œÎ&´ô%@ø ¾EŒk.Òô~ VÖ™ôɲ½\Ÿu#air:¡°ÑE"|ûó¡Þ�  C²#©I€ÏòweN‡¢¨àÕojÂkÚ$?o_¥ä$q†œÈÀ§&¸îÇ ÏËùPn9ÀÕëÇr¿þàï>ˆæ=‰S§kxø‘3Ç>óÞ»ïãÞ‡÷ðÎ[SÜ};ÐÉŽø$øîÖgËœáy}žóŒ"œ�:€>_*pH(„ûÀóòÞ|¨k)‰úoøþ±0¡(xéå õù×ïØxíUÛF)㮜vK†Q鶈3qö�o7 |d}ÆkR²ùPÿ�7ì|üñÇøÅá‡úüS_jâùT|ãTœû<³²àz "¿÷‚´™°0ì¹¾ v½p †ïÁð‰Hѽe°Ú­àþqÏvé�=ÞÀó/¨øÚî³8qâëWnK˜�çõª—DŽd�×PÉ|Àú¤ƒAÊð9ÞäXmíÿþ÷·±®uá‰óøæ·þ~M;’™‚þY%ª®à¶±EB¨D€Ï� §Úž:€dwÜÿøè£�b_èÔéžAeA¸EÖÁ1Åú¬é®„jƒ=rB%$*ØÕqÑ•qoc-3\ç1y±'Oð ¼±cÛ^/Ø”Ñ8{7)„Jøúœìg_Ât�nˆ�’–=.ú‚'NžÀמcjÂø{ÛLÚú’*‰ Tàk‚sú‘¤™ÈÞ/lgà2.zêt Ï|•™{ˆêÌSÎsÌ%„Š|5°ÀÈ€�þÞVŽ<àÝÿxè÷vá OœÇ…‹ç½/o‹ð‚œ±òšÌ† a-ŽdÁw�µ¥Zešyõžþ-º_ûÜÙ?ú7þ¢ÿeÖË¢´ ôDÄÂeŸr‹wÚ©x/$ÝC�#tÓ†¯àŸ¼¯ÿé—¯ÅO}i­Ïõe…á4ÌBîQ¯ 'ãÝI>–<S”°Fð½ à„–3�ü�ðf„á-AÅéE™°O‰†áUÖ„ …!V Æu³Øæk!ê»´¶¡ß_’ç8í}ïëÏ}UÊ ^xâ<+#‹�¦ä@¨1Þºáí` #óê¾½”~7$è\Ó™õf½§Ç�±ÞÓ›õžþÏõžþ6€ÿdÜ;ZOÿ±ïç†0m½–„&€ë¬lßí —Ðºï(­Y( m ×üé»»õž~«sϾ à1ևϞûþúoþ\êM?üè0/X_³²åÖƒ Á×Àúô÷%ŠÞoì‡ùdó"þî›ÏIÿ‚œá¹2™ÆÐóÛÎl Å'ý/ÞˑµÏÉOâÙ¯?ƒgÿö™Ì¾´ìµ¸dÆ*ã-£ÞÓk Ýì#ôØ{@y§ÿú_ù+|÷¥oãÉËSûÛ�=Þê¹s ¡�õ]\·¨Ÿáx‰F½ç¿_K½W�ýÉŸuqáây¼óÖʱö³¿ƒGë�°tXjöÞoÞß”~Îzž …Â,‹N3åP`§á~ô žÞnáéí¾Øz*SøàÃï…i‹BM³óΦšÍ‡º©�‹Ô±¾ú‰[½–d ×<¦aÏWݔĺyšœØ€ñÖ±$”ñ²ª×ZFß½!À{lo“©1/Í Ò¹ÃšÅÈì÷�IЧ×õ¸•Ò^–çß"N5?Öó�%”y2†ᦷ%\3Ž÷3±^[>¶¯£âqýøÕëf7Ð ¼ù«_ç @†,°„ †“ Ø‘„LØòzÀ~»È€¯½ºÆÅL@éË›€,ÓÜÎŽ2ÞÐK8Ÿ,¬ ö¼®�Äïo4f3¼/üì§Væðq¶òѶM‘!=†dbÝw½P `A¸Mâ2 /¨¡0|è }Y€9�ÀpéLJ0>g˜øÎ¢WžÍùðŽ$-Æ�‰ÈÀuï ?úá 3ø~1š°¼ß~Ò±w‚ õu5ðùNdVBx�€Ý4 $à—¢Ã0%8Þ’Ì�?ɤìò_ëw 1ëAT†þ³2‚/Ô,z%ä49å™ ûÞy]S_Ðu5/Ü¿Mðú;Uø¾ÿïÌ>+jæQ?Mï—¾Ðú”g€Õ4kU"€gEl�MXc…â4 tàc”]EÌ<"ÎJHjâªQ•ˆQå@x[„ò—¡%îµMÖ÷ÿÑRÃñ;oMyð‰œô«…èÌ¢àë‹€/2€! Ž×°À |T¬ï£‡_Ž&ø·—¿'´FxïÃ{øÙO-üà?¸ð YièÚXÝ›Ô,$À§‚} G¬�*•‘ŽE$&ÞklAì‚xŒ½�ß{÷}üËK~<øIb_¿cã__þ¯Ü"ú€í>ˆ�ø4°‹ÌÎÉW‘ï'—{DÓµ§Mã{$©àï`µÛé…‹çY+׸:ïÍ_ý¯½jcñàÄû*笭K-Ò” !gOb᥄8Ðpîó <üèœ# x7 YšÌ[z1Áçdº,øöDí�&ú¬8ì�Tc‰nÎyqÂzx@Ï×°…‰31öÀ@æŽ2ÛÆçÌ?á2Hø�ÕçIDCœë̇©ÌÒv`ìb57±I/×èßN‡ZÐÿ[ì4¦?qdOÒã¹üôžèÌ]€1²©÷t› ®ÉkE0ÎÙp‰ô1]sÀIÆb8™šdh*Àe°A¾Qï郈ºPc¼f–i�ˆ^Š“Ttšy:&y¾©ŒûQd5”kŸ8Ö>ÎawÍ�ײìy^ÞBvG8di&C—îÅ™õRïé Š.<½w}>ÔU™’B‘ÙR.|2ä°=WÇú’Åm™§PæÐûiX?Èg†S¹èZ6'Ë�¸œÆö,R4`Ä ÙqóZPO#�ù†ìÌ,§ðõ±ƒõZ¤C¼CÔ<…Ë3ó€o¨�}Ø(›³ƒ¦]‘G½.Rÿ¾G÷ÝŒŸãõxYîõùPï§¹ˆII³!]‡Ý±táY? ©Œy‰û(þ>†A¶ÀúÚÞƒ°ÕÚ ÖÆj©$/Ëmf±#Zj!˜‘Éé>!Ù÷`g×&¶¤sòê MŠ¡†8C´³ãE3ÓÑ™èÑ5&øö°š®¾@en-m•EBL²8D6›Ïç@W/øˆâ5Ô Â/t§6ÀB\R§6òð}3°h=6Çàu©ýüfôPNóò½c8OºÔN»¥ nÄõÞ«>¿¶�rì_�&x3ÒÔ–Œï0O4µN»¥Kp4ž8åçfw;í–™Qq´Ð¢�kÒÃ-1aSäšÐ:íÖ@€ 0¦ÿtÚ­…„®a5|# �7 D9Òá?M,µv�'Fĺ¨ê ö:í–&±ÁÄå%%2¥ ÍÔV÷ sDR“($ż³rŽ:íVSš�'SFï»Òi·,É!LÈq„¶Yô¬ÙµÔRE¸¥©jãÑxR£Ð›ˆ…8²¨ŸhÊÅ @œ‘W4ŠäIÿ:?AÞnIš<õ{�'Ö Ü‘£aÜ,˜÷¥†â «‘«iòÓœWs×E¸£ºf.ðR×¾'+ˆ ` ëëR ÅUø¬ïåxF €•ö$ຮŸK>~HÐe&/|Bïµ(Ùo"é‹ô±>=HZVR¨«ôe!Ñ5è'?¢ ¤écpMú‰ºÈÉñvf¼7'útÚ­~œë% �'&ÃóvÚ­nNtÔNÌK,ñé‚£(ݹï’3áxi3O#?Tp¾%Òé$�çŽSÕƒ‚õUVvD°›yn�'M°''’]‰Ç‚}¾˜”Qž1Žö’a3G‡’Ím¦îípÛÍ8ÃoB¤/¨‚½ ór§Ý²óبä› õYئ›�Eò“0ÊYŒ+Dj › ÃуKݼBè“U;p‚þ[ ùñ)>�¹lX}öÎh<±°^êV÷:k4žØ`Ÿ ÖÌ"3®,ÿNEôš�.Ö—Nž`‘+¯¬Øð«ix¼ºPÉËõÁ>a©‚°øðíÆ)6§éA½£[AX:øödT5¤MÉ猴¢«Ò„…‚o_ôìwiÐå -°OXºÀ¦úae ŸTèº1üý U¢))x5ðwB• ŸTèò„&V[ßz5á€7Ðʲ�¯™%|©è ǬÄnÓäÆÊÒ…¯ïßõ4àK%3zÜì!¯Cý*9Iå9èðÙ:Í1üÔ¦hŽ%AhU˜Hiûø[³eÒö™íŒà“u´'Lå …‡\üݱÔ,ÂL·æðÉ�ZÍ_yC!ÇYëµs&�=ó½ataå “wpü‰¸×;íV¦ `.6'¢^jø„ä%V[>˜V¡;µþŠÁÌBn. ©Sœ†Óª°ì›dèð_ “«ˆ’+Cj`U²Ñ+�µ™ÿ}trÙys «Q»`Ÿ‰Q�xÜãiðß3f ÀHºvcãt5²N�¼¢¹)‘4ž†àe§äõ¦y½—Ü2Iqì“EÜynômÐG¸ÍŠ  `D‘]*¯èòv}¯k.œ$)€1@Œ´W]NïUÃún¥ÑÂJJ§ÝšÒl�sX�H¾äüj4áÀç½}¬v&è5+¤äx •¡�ΕA z–»–Jç–@OxV±Ú0G-É=õIše+9•ÀÊ* XYe€•UVVY ýÿv¾Æ%�~âIEND®B`‚ukui-biometric-auth/images/ukui-loginopt-smile.svg0000664000175000017500000000232415167732630021305 0ustar fengfengukui-biometric-auth/images/ukui-qrcode-null.svg0000664000175000017500000000344315167732630020573 0ustar fengfengukui-biometric-auth/images/VoicePrint.gif0000664000175000017500000003056415167732630017427 0ustar fengfengGIF89a  Ä¢ÒÿÇÑßUsŸÐÑÕððñ§ÔÿÜîÿúýÿ¹ÝÿÑéÿôúÿâñÿ­×ÿÖëÿèôÿÅãÿî÷ÿ³Úÿ¿àÿËæÿÄÅÊÜÝßÌÍÑôôõÁÂÇDÿÿÿÿÿÿ!ÿ NETSCAPE2.0!ÿ XMP DataXMP ÿþýüûúùø÷öõôóòñðïîíìëêéèçæåäãâáàßÞÝÜÛÚÙØ×ÖÕÔÓÒÑÐÏÎÍÌËÊÉÈÇÆÅÄÃÂÁÀ¿¾½¼»º¹¸·¶µ´³²±°¯®­¬«ª©¨§¦¥¤£¢¡ Ÿž�œ›š™˜—–•”“’‘��Ž�Œ‹Š‰ˆ‡†…„ƒ‚�€~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!  !ù ,  ÿ &Ždišƒ¦®lë¾p,Ït]Ÿx®ïzjÿÀ pÈâ�HŒ�Èl:�ɨ”´|Z¯×�vËízµ–…„-›Ïha4 §ßð8p-j�äø¼^CWº÷€�W}v"‚‡ˆC„‰�Ž/‹w�“”‘†5 ”šo–5›¤X�5ª ¥¯D§3ªµ®°»5²2 ¶« ¼Æ1¾4à ÇÑ+É5ͺҼÔ6̶™Û»Ý? ¶Ð䝿?ãí¤ï@ óõ›÷@µèí{ÔÏ@U&*hÐVB…‚âS7bD6Œ¬È«…Àâ!‰AÀ©*æÐ…-àÿ8X@[É—*@ÕJ³¦ ‘lÖ¤U‹�Î’éTMøùrG¢%yªBêñ€-¦ŸB…(uêÀªVëaͺÍé*®õ”vKN,Yr2H8»-ÁL¶Ò6 טHu�Ùª˜ÖÖ¾¥þÞ$x0¥Â†!NÜh1cDŽ Š,åÊz.cÆcËåfD~tm•çÑ€ØZ‹‘H¢[ç�0̧ì=io�¾-Çm-Ö-d.@Îðáq„—æ[ÞàÇ‹Ç9ž!yôm¥C¹PžA:êÖ—K[Yëù îÞ߀‡ƒžœQU ‹ÿ~<|wr´U1�z}öב³U{þ!à|Ò  ÿ}¾Aà6 "¨ÁƒN¬wÞ‚MP8!†ŽÐÀ�u¡„2a¡ %¡aЇäVËP,¬È¡‰ÿ�ØŸ2Jˆˆ‹«ðµ!‰3ÆPâ‰?ÞHCŽF™^"ÍÜbвøÂ�5B©£�Qfy¥ ©¨AÀ€ä’2PÙ •I–©e’R’�iX¹å”3Ù&KŽ9 yÎÅÉf�bÖY¥’?è# €Ì[�Ê™¦ŸdÚ‰èvkæ9©r�)ž… z&¡6j#™“Q´é¡sRª£¤©rŠêŸ­æ¡Î“®ŽZ+š‘jfu¯Zê(©�84ƒ¨¸Þª«i"ë+¬�&4©ù«±»«�ÿ²Ô^*‡ÏB;l¥Ù®ª«§¼ÚÚ«µ€d Û·Óžë. ض¯¹ô2L»½[¬¾ Â;®¸ŸÛ¯½µøØ(³Ë&ì¼+0<ðÃÁÖ*¸üVËïµÿ"Œî— ,0Æ“®ÆLJ\ƒÇû2Àåî[/Ä–™|dÊ.×|lƹ®LòË/u2Í[̳ÃÇìóÌí¾,´Í ·4Ðnv ôÇ7=²ÂO4×äÖÍì÷sÒ6/ 1ÑP ñ×h«-Ò;‡-òÅdƒ=„ji×­ÝÄrS�óÂ{W¬í êÚ= t}ÝöÓ,[÷áB<Û(Ëm5Ü}+ýw ù©b0‘3^õâXñÿäÑyè WžºÎ¨Ãüó…x¸Þ¬ó]»ß±b¾—éSCý¹êˆ7[Cs¥óž·ïÀOn¹ä?té­ñ³#»ÊNŸN„¶„ }ë´WÿöòŒÛð¦3{}pÎÞçî6ó¨¼X~ÙçÛž¾ðªF¯~ Ø×¢ýöÓ™øÅ§°f�¯éÁ|þKVò¸>úÅ ;ñyûˆ¾þÕ�{—c�WTA+û´NZ œÛ0x¿¤%'€@àågÁ«µð „ ·ÀøáÎ�/°E=øBTMEð‹ÝŽ&Áð á‡B˜¡ äœ"~�H ‚[AL±QÂU�9䋇\–Ž—ž›’�¡Ÿš-¤¡‚¬§�$¯'”©¦˜­7œ²‹¹ªÀ¸•»6½3³«µ ¼£Î°À¨ÍÊTÄÏ¥ÑžÓÆÌɹſ×à±Èâ©�ãê®ØìäÒ¾™ðæòïë‘öî÷^ñºå?ßòáÛwn >týŽG°ÞAƒ"¤çoÞÂz +f ç�LÂ7¶‹XP¢GŠ Cÿ>4ɲ¤ËŽüP‚ (R`K˜/É´¨’$ΟWæÔÀ­ÇÇ‘7ƒúTš”èÑmOkJ ÔéN¨W§.åÈÔèÕ‰5jMÊ5eÓtT»-;s(Ú­HsrµÖ,ôlmº} ¶'Ù¸kë¬Û#^Áy±æIó°ÞÀ�/¥ëW.âËŒ÷fu<ÖræªoÿFNÜ÷lTΨá~V+¹±êÎ�Oí6k» OS³¬ôÐaÙ–�®6›ïîàÖRw[MËò×i{Ÿ\üÜõrÞÃ|W~K›ò%…Y«^;zö铹ïþÞˆ9që€ï1î§;�¹ƒè²¿�¢Gð·^zÿé òå÷U'àA“Å ö÷ýD(¡ƒV@haƒäÉQᆠ(…† J!‰B„!ù ,2Ae@ÿ &Ždižg�­ê¾îºÂtm›*{樂ñÀ (—i o¾£²F4.aɧ'sNOÑ뵩Ee»O.¸'KÅfÑW‰fWKmå:£ãöàü}Ëóð|O{:}�4€„#~T‰#ƒE;‹p†ˆ�6t�V‡”/–›’$™e¢�ž¦(Ÿ“�u�š‘¨)”ª˜®¤Š±²¬§¬´L¶3¥»¼—¿½³¹«ÅŽ·CÉʛĠÈéÀ?ÂËœÇÜÚ¾ÎÝѯdÁÙÓáÐéæê$ãíÍàÞÔòèëöïåñâð•óçôÿ 4áŽY>}ìÞSˆ«>l µiXÓÏ!Ë&ToÔÁŒ‚Üø�ãA�#ÿ†TIÒ߯‰¯1Ò(²dI˜'e¶´8²¦Kr){>œ¹£ÍŸCEâ *Ô(R§<—¾¤x”gU‰M2½Z´©W”SùqÝI“%аÇú´ªÓlÒµe¡Æõ*U)Õ§_ñÞÌZnWµn Kö¯^¼}1&–k˜mT¾wÏ,íÖÃ’c�¹+òdÌŸ;sÞœ´æÓGï+�¹°ë³vÅ> œ·š.ÒƒgÓ–öÚî—¼kµþ[ipߨ‰¯Îmûv4”[‰ÎÙœh¡áÈSS—x|[hîÖ¦3ž¼u¿×‹ïî~䦾셸ףVuåÀéo]·ô¹GÀ×ß}Ù§ßxü¥‘Ÿ")hŸyS4è ~J8¡w ^aá…ñ�±!‡åe!?7„!ù ,6A`@ÿ`&fZižhªªÁ(¬p �¤LË8ÞŠoî¯7ÛèG<í2½b1c*}ÇäÓç§PöWUu·,-÷E•Ǧ(Z("_×a|ö¦·�b°/GW÷y[{i‚[�}ˆHh„%�‡u€‘�1�—†–™Š=œ?˜}…¡:›”bžY£’†•0•¨¨9 ‹|´²¥w¢´±¤ª³R2¯¦‰Ã¶½Æ«¾™®¸5º�ÅÀšÊÔÈÓÖ°ÑŸ¬Üª×ÒÙ¹ŽÝÈ¿(æµàÚ¼ÉåäÀèÏ)áÎãÕñðçúéôëíòî½Ã·Ï[½‚æ#دቃ.Tˆp¢EâÜAËPcÅ�=šù·n^ÈŽÙÿ‘äÈϤK‰ _–€(eK˜!U²$¶“âÉ›"eê´' P› ®$ŠÔgM CAMŠó)Õ™KcVÝ”kJš^�нµáT§a¯ 빑éX´]ã®uË“.ܦs‚•û6¯UlYªí«+[Ãvý¦½ u/ÞÂ�G.ûW1ßÁW†LX¯æÅ–# u¼l…ècê&·ûÆÙ³ÌªK¢nmí5àØ“oa®mº™TÙÁ:ë¾�qaÖ‚yÇ!þ;÷ìäÒl§.N™+òÍ©˜›>%åÒ®•x^9‘ñJÊGõûç¸ÝÛ“?ÇzýêV2ÞoUÿŒ ÿŒ”6€øí' ¨Ç �k$‰�á ø` !!ù ,4A`@ÿ &Ždffdª®lœB+Ïê‰Î6­Ë¯ïÀÚ‰– 5½Ìï,ÊœL]rÕAY×jkªÝe…¦.�+Æ Íáò¦~žÝé¶Š,ßàw]»G²Ë_)W}Q}„Q�%oz]†�]EYƒ�3�>.•<š’‹"”˜;—J™¡Rœg“ž‡,£T~¦c¨iªqŒ±–•®@„�¶Ÿ«šk¸»¢³7µy°¤ÆÄºÂ­ÇÀ¿ Ì§ÎÙײ¸Õ©žÞ¿¬+Å#ãsÒáÊê¥Û˯å·îñÓÈàÖðÏÚùûí¯ì‰Ó7� ¿‚ý}£†ÏŸCôèLöМÁŠòj´S�#Ä‹Z™Ñ#Å�SÿnD¹r¤»‰÷‚‘|‡‘&Ëš0ÊTY3"H�ötœé“hº“.[–¼É4)N_ë6]êtªÍª@;*ÊÓjÑ®YŽ�Š•ªÙ«g{-ŒºS)Ú·_ÿAõXîÏ´wµ"Åk´/رkéòýkׯÜÀ[•Åí™W-­˜\Ý.öz²âƘ ›´ÌX3å™9ÙFîLxrؽ…Kg&ZpjɫݶNL¶çº³Ã⦺ïÃ�…^öí6·—si[Ýdòþö|á»÷Ž£€óä÷�„�Ÿô+‡p!=†ù2ƒ§�"Æ�CŽ#¨�£ÅŽAÿ¢ü‘YIƒ,WNL)òä3�#e6¤©³¢C—0öTiÓcM£#[Ýw”gQ§HŸ¶#¹ÔdÔ«P³Æ”:PéF˜3·b«uЯw’]Ö,Λi}–U¶kN¸C›²¥{ÖëݱmùÊ�ê¯ÔÀƒë>ükÃêÜÄ‚©Jf¼²e¢?ßfŽ‹ùqçÊ’ oÎKú°Z»†G›¾¬WñYʈ?Çö*º1ØÈ­q'¥,tµlÝ\§¶Í97ëÒÅ _k ¸4wÊU�m~<ÁèÄWRÿ½ Ùul/‹/«þü;‹ˆÚ¹q¿§"ö©é½g/?ÇûÞÓÛ#|ÕÛÝ�Cæá˜u%‚BSc$¸ "Ò—Äi Á !>¸à�M8h!„�4hÎ!úW¢##šqâ­Ì¡Î+òæbŠ0‚hG|nĸœ/z‘A!ù ,2Ae@ÿ &ŽdižYš�lëj�*¼tm£ê­“q:ïÀ HµÚz™ŸqI#2iHåsZrRYÑ«v˜Û–²^ª5,“™c²Y\|¦a²éî ¦Øw^ü9ŸÛòn]#~A}{;€5oo„X‡e�tI7H‰M‚#�’.†uzŸ5–mŠ™\—Ž'ž” ¬¢D¤˜—Œ¦©&«R“¹�°:‹›¡P’¸•½7¿µœ-Ä­»ËƦ´¨Ê�Áº_ժХ³À®Â×̯߻ÈÔâÃêéìà“èîÓ±òÙí¹ã‘öõÉ×ôUüîðak¶ï·�$ÎÅÈp]Àƒ~œH°â ‡Ë™�h1ßC}z„gNšÆ� Aÿ^<™Ð$ÀŒcœ¹�äF—6Qb¤¸2fΖÞ^òôHSg»Ÿšp.ÜiTæÐwKûqìY”êÓ”BÿE*²+V˜\ý�ê´iU¢5ɖܪö*S«MÃNEkÖ­Ê‘mµÎcI®ß¾€¡>›”ëW»>ó޽iøm`¬r•">ëÕ±à�„O)~lòfÍŒ?®Û*2ÛɨI÷4½7ëßÊwa».ܺqìÑ«?gÎŒ›óíƒ/ævåõ»ß³E.„ÛJýš¸´ä’1/Û|ú,è§¥[£ØùõʵÝê,>­¯èÕ·S^^zöÚº§¯/ßþ|öôۊdzîÞÎl#EƒG|@XÊ€ƒb™2€Sðà‚6øŸž�ÃwW°gapÏi¡á†àu˜!} †ˆ!–Ú†)ª¸˜…-Ö!ù ,2Ae@ÿ &Ždižh¦fhë¢Á*¼tmŸ+{ïc¬Î¼ P”Þ| qI+2_HåsZrROÑ«–¸Úš²^ª5¬“™ã°ù™6¦×F8¼Ù�¾eS9~×Þy{=‚6}-mIG„eŒs/†)u$‰RPŽ˜€|“5ˆœ�š5z¡"�.‘8Ÿ•‹¤ Š$¦‡ª§ª¬6£°ƒ®t*›¾UŸ²_™º¥Œ½:…¶ÂÈ-¹–éÀËÔ#·¢ÅÑε֯–«ÌÞÐ%ä±ÚÓÊǼžãèç®æ»Æ×ÍìâêßåïóÛñÎØêy çîŸAzòÖÑãRpa»| õÁCÈ�’=‡øöôGq£Æ…!"{ø‘£É’('ÿ‚ ™ÒâÀ€ûµTxÒL–ÁÖ”©rfL—"ï½¼¸“¦Ïˆ ƒbªóhÅŸP“úÄ Ô©ÇžXyæT ŽdV£_¡"¥ ¶êV«Ó�J6ªW­eãŠ}*5lÛ¶óÒÅ;2cX½Wá äjÓ¯`Àj§òšoqâ¿OÝ|+ñZÉD 3% 9pe€™ÏŠ>¹4/Ç] ö<—u]ÁwaZF»r²êÖ�I»F­¹±lÓ¹å¾ît[ZçàÄvó:k㣓3oŠ øÊ忦svŽºÙjÚðÎUïóvŸ‘ÏÎ>:ÛñϹÍR>?|zøÝåK¢ä¦�±ØÙÑÜÖ'Æ€qì -Qà~�ùÑà ž�ÞÞYh …j˜Ž†zèž!Š8ˆú™¸!†)º!ù ,5Aa@ÿ`��‚fžhª®ì8²pÌŠ¤¬ÑYiï±›ñ@N�'òh”5—@%”÷„U§2)Öé"Z»Û�6<skäž+ýEÍìÕ8~º®ìóéܾ¼6ñkd{pX~f€/‚�u„S†hˆ?Q‹I”7�on&�9›˜yj‰(ƒšg�(œ:‘Ay¤§;©)Ÿ–Yµ®^¦¹±—¥ 0­–|e¥¼«“¢•ʽ¯6¼Œ�´Ì¶Ô¸@ОҾÀ-·Ã˜mÎÍ»‡Ó’Ñã¿ßÌÙä²�³ÜàóÖôãîÇçðõèËþïPÅhÌ\?~ꄵ#ˆ�a¹m ïåZgoaÁ‹ 1ªÚ'ð`Šk3Š|x Yº‰ ÿæsˆp£Ç“*R¶œ’¤Mm-æHQ%Ëš4a%1&;Ÿƒâ¼9ôŸR2�JJu©Õ�E±VD:ò©¾—W‰nõú³j@“a�jåÊÔì×�O{ÕÙ6mÓ³ÍÊ]K6éÔ«hïî˶oW©�¶»Òoâ¼jÝ–elî_¨G ×½+ϲި’ý†. Y0hÊ¢Q“k:ó寇³^Ìyrmˆ(³ž[øµíιéòî;õí՞ŸÖ+n3pâȱ‰ª¾žœ @¢Ù¤ÛÁ¾¨Õ·­¹Ï.¼Òš`×âë䥬îÝÅïÍ%ãÂ÷ßÉkÑôùÔáÃ�›3íþ.^ÁAï4ìS´�bœzí9ä‡Pa†ø>”G�#ÉŠÞÿb„xrcF‹c‚d†r^KbûÝœù�aJ�8'²Ùs¥Ï£0õ¡s9(O§*kæì¨4¢P¤?“fÝj³çTy_‹Ö´&“(T“fµžU«ÖhصM_r5Jö©\¬]ÑÂÅ[ÏíÕ·wé.ô»4¨N±"Ϧš6îܱìÊêeë8/e¾ƒ¥þ=Çxo_Í…«‚½*ø"èÎw?NÜöôÎÆ–WKnͺrÉÀ�/~=ÙvnÉ»½ræ}ùsíØ4†{Uܵå{ÁE=®:ùáèÌŸ×{šçÈv+³ZYfêº`W÷^¼ðr°È£Æq~¶xhò‰Ó§>Ä|$1áÝm\˜Ä€þEÄG6yb ÈTþqJR¡âTGuføÍ†é5˜Îru„È…‡ªWŠ)¦¶âˆØ•ø_N„!ù ,2Ae@ÿ &ŽdIY*˜lëšiúδˆÖ&ªâ<g½  (ÔeVÂà/Ù»cH&n)­9ƒÆhuFݾ®M¨—Ö³À¼¬ùU^ŸˆX±Û›çàá]©-m«½h8$|L~r[�Vˆ#…I‡z‰x%ƒC‘�u<|�GiŒŠ–�o—"Ž-›™#•3¬¡ Ÿ¬§t2{ª¢Z­±“¤£«Ÿ³¸döÀ¥_¼.®Á´0ÅœºÊ¥¯ÍÉϷǘ۰ÉÌË-׿ܽlÑòàÕæ¹”ÎÅçÝÆ“êâ¼ÒïØéðóù¾ºÆu7í!tñ‘ó¶ÐHBvû.¤Mb@… ºÓV¯_/� 36üÑâD�9ÿêiR¤Å•ùEü(“¥M—%oVÌÓ_M‘@W¾¸fQ•D“"³9tiOžG6ÝèT(T¥åŒ"•zµ*V†SCF¥šu+Y±_v=›Ò+×±hÝžU«U®©ŸpÛÎÅhµ.[”©Âì›Ö£ß»>óõ¥xæa½ˆ×ÆÝ R`„’3Îlø+dÈšíÒ-ìØs`Î- ‹îl÷såÅKŸÄk6òáТd?}|ú6ìܨg‡uM{µIÝp-cö�z3sá’‰#']üouÛµqO†µNgm.Ë=w¿8žw<½ÅßcWÞôyTá[·6ßú‰“’†—‚4�…Œ.L›/‹‡y£�ž�ž -¢•4¥™«¨Wª‘M7¯º¦Ÿ½´°œ·¬¿¡”¼™ŒŽ¶£¸\0»Š½Êª©ÍijÆË'²¹^ÕÌÁÀ%­ÜÇß›ÝÏã$Ô×éÓñ�ðÉ¿ÎpïÁêäç=ØÞ#Üé³7Œ@L}ÍXoÖ=tâ”W�aB�üVÌx‘b>ŽÏ0¶#øqdÃŽ Aÿª„¸Ò_ɉ'Cö;eQ¦FƒëRšDÉó%B› ÙÁ ªs(P >òÌù�iÒ};ŸRtZ_Ħ-J�i5«¦«8½FsYu'U¯BiŠõ¶¬Ñ®fá’]{rëR¹?ñ~¥Û³-ß³qY ~x¨Ý£zEÎ-œ7ª_ÆJ^L¹ñd­�/GNL2³åÏJ£•¨v0èn¢!§Ýlz/dÔžYk^­¸´fØœ¹¶®íú6ÛÜwwwŽØ1ñÑX[ÓžÊ1õlÒ½mŸþ-MweaÎcÍ„Æ\¹µØå¨€3g]:vðÅ\m'Õý:”�ªµ�_Üý÷ãÕçÿÕû>;÷mô!WK E�Æ€ûyK~–è—ŸdJ@gÀ;ðf„„5Pˆ QN˜"RX(†Â„8ܦq`P` ¨â,váâ‹ò­Ób‡4’c3æà‹=úŸŒ8Þ!ù ,2Ae@ÿ &Ždižg�­ê¾îºÂtm›*{樂ñÀ (—i o¾£²F4.aɧ'sNOÑ뵩Ee»O.¸'KÅfÑw¹¢Gmáú]‹é;p^åéwx;|:ƒe6t�‡6m„E~‹4‰}d3H‘j˜xP˜/“…$‚•?£%›/¢#Ÿ�¥—–¡š”®¤L²C¶™¯u�ŽV»º0«¾y�¨¼± ŒÅ(Â&©pÇÀ§1Ë)¸ŠÀœÙ½�ÛȬª¸ÄÒâ�ß¾›æäÉØ´·ìãï¹óÍÎÑõ×åç÷ÞëàðBó—��;Sû"4(N^¿‚’�뺆ê ^ŒÇ­UE� Ò{r£ÈŽIÿNÔϡǀ&‡¡8Ïe8†-3–Üù²]š3}æÄÇóæI~=mÂ,š²§½¦Fe]‰S¤Ò‘T#þdŠêҬî^}J“«Ø é¦F5ô,Òµ*½ ÕÊñmY§,­êËÖn×»pË›WªÅ¸€¿ NüwnLÄŽ!®vïbŠŠO¦«WmæÈxë*äK:)Ú­¥5Ÿ:ú2êÅn§Ví3èÁ«;·þlÛöæÇ’siº6FÏ·?ÿnœuMdkê—Æ³äØÅÛ�}ú�èÚ©qŸæ¥Ê’·S—=ë{áôâ×o�è}Rõ�Éc1ÏÕ7þÐVýW z÷Å—_C*á_AmyÆklTçà î!a‚GTØÍ|Êd„††°—†'jqִ݈Ôʼn(š‹-Âö"12Sâ0Ö¨Ÿ9Š!ù ,6A`@ÿ`&fZižhªªÁ(¬p �¤LË8ÞŠoî¯7ÛèG<í2½b1c*}ÇäÓç§PöWUu·,-÷E•Ǧ(Z("_×a|ö¦·Íu¬W÷]gD{'‚Db�yS„&†\y€‹�ib•r|5T“‘‰œ}:–%�%”ŽŸš£ž ¥‹0¤¤¦­¬²�˜Šµ¯¢±³¶µˆ¸¨?°¼À©nÁ·H´ÉÈż¾®vÏÂÍЙј—Ø…ÔVˬ’âϻܪè·ÄF«ÖíÝR½Ç×óÙßãï)¹ÉÆêøÒy;U9xÝ©›¦`?ƒû´I”Ñ!³{b˘ϟ´zùÅ؃#A� Aÿ6¸n"É–E®œÇ%Ë€0_âÜi¯âÍž.sÒ–0¦Fš*mb9t#Sœÿ~† 5¢Ñ«:)­)S©PžSµbmº´¨N“B£–õJ(Úª)-ÎìJ÷èW´jëŠ=©÷ìS {Ó&íKö.Ó¼['&а±O¤rÙŽ…ëÔ¬à¸Rç¶�úpV¾v7kîöóåÌŽC“Ö˜òZ »~ [ñØØ¢%›ž�›6XˈoÛ­uµî‹Q×f,ûK®�€[% óëè©‹?uY9ö啳W>\™xäo¹ûžÜäðô¯êC³¯¾äöÁ©›¯oXþ�‘±#sT=�œÝWÄ=�`¸¥à åaá eŒD8Å„çU ÎÇMîÔܱ„øÈ/c"8ú…X¢‡'²ˆÆ‹sÄè4ÂñH!ù ,3Aa@ÿ &ޤ–�Y©®l B+Ï*šÒ6­ËïïÀJ— 5½Ìï,ΜL]r%q×*mªÝA[ßîŠ+~feá2‰¬f¥…§6‹-/½ígÑ=H×ç«{#a�;}&Q„‡qxŒ]†ŠVŒ�‘H0%”Ž’7$Eš�‚ˆs˜k¥ž£n•W p¡3}­@ƒ¬§¢›~¸<¶—>®M«“¼‹¯Ä@±Ã–Æ�7²¨º.¼Îœ¿½JÕÏÅѾ¦ÜÙÀºŸÉÁÚ¤Þ"ÓXáµç¹Å´¸ÈíË#éËöð¯ò×Ì™ãëÂæåÆNÚ?}«á#ç¯]º…ù}ëG±žA�y 6KXñB‡-b¸qä;†Ý$ÿ4ÙP¥;…!=´F…æL�+]Ò“ÙÑfÊš;}Nœˆ³ç> _Šš³æÃ˜/…òdU¤Ë§,).�Ú´%ÒŒPï…øÓëͱìt’¥zôlV¢hIš-k4nIµ(Ù^ÄÏnמAƒ¶­û–çÖª­~í[8êaÁ{ä{2¢ä™�A6Vê—ðU¨œNÙ-e˜¢×&^�Xjk±©ó²ÆzZkg½šk+Æ,.64sŸE£Aùx[pÝÔlû.7¦4àár]�N¥b0U3Ñ‹wzå»—ŸoŸ{Ý;jä¯�s†øí-ÎË·�Žý{{‰¨sM?EªUáßÊ&`wÿé÷š-2êa–ßoâµaH�­À`ÃPX „jLXdžÌu˜á‡ V(‡‡r€H!y+F!ù ,2Ae@ÿ &ŽdYfhf®l[©àÎô¨Öfzã< £²žP´ê†Â_&ˆä{Ç&NɔҞΔµFÝÖ°¸¨·Õ»À_­™U^¯ÐWµû›¿›b›ÜÚÖ£Ìp3yD{R}„c�g…ƒM‡Ž�xdu'��•@t›—‰a˜šK9˜“l–#‘™-�pª¥Ÿ4‡¯±qµŽ¢UˆX«+³¨~‹ž¼¹¤·½&¿�$ÈÆÄ§ËÁÎ<Ê£ÃP¡ÐÖ̰©À´ÞÒ'Å×ç\àâØÇƒëèäßÑáà’µïÜ…øñüôóûþ¶õ³w¯^«nœÔE0!Ãú "„·Ðá4ÛEœ×�bGy $ød$Ä’ê2ÿ¢äxr¥Â�Ý¥d¹ñeK‹Oâù°fO�i½Èsg?“2…òšX£R£»œ¹ü¹t¨Ó�*¡ÂÜ5•hLŸZ“ÚìÖ5'SÕ¨†%»Öj¾²Mß¶­t¬Û£3íÂý ÖìÝŠWÕöÊu.á­i #í+×ï^À�ãò­+82ÞY;~¼µ³X]"3¿å¬“bbÓ¢ƒ‘>U³äÖ¯=>\úuè§ÃVÿEœ·2ÚÔ…]OVÜ›8îцC½­7‡9˰e÷ÈèØóáS¦C”ÍðÎ×!¬þÌûññÚ@'ï<=mS汞·U>Ù÷fÂÅG§ß>¾ïý.œ¶{帧\v˜ÍÇ�IuHÔÆÇz âÁ$1Î{· 1% N¨a…FH¸Û‡ rh!|fDbÇ…Ô¹¡â,èb=+Šã/ºq#€s䏯ŽàÍÈÑŠ!;ukui-biometric-auth/images/FingerVein.gif0000664000175000017500000003543415167732630017402 0ustar fengfengGIF89a  æ•êÿüüü‡çÿëõÿÙÚÝáâä.SŠ·ÜÿêüÿãúÿÇäÿTÝÿxäÿÜùÿÓêÿHÛÿ¸ÅÖùþÿjáÿ$­ÜÍÿÃôÿ¡íÿ¼òÿ_¦Ê�¢¾Êõÿe×þÒöÿœ­Ç‰ÒÿÕÜçA�¸(Ôÿôþÿðýÿ8×ÿwÑÿ˜ÒÿÑÿÄÅʵñÿªîÿ¢ÒÿÐÑÕª¹Ïˆ¾UÏþCÏÿÇÑßÌÍÑÔøÿt¬Ïÿ©ðÿFg—–·3Îþâñÿ¿àÿÔÕØ5zªW�qН°ïÿfÐÿ×÷ÿ'Íþ­×ÿ§ÔÿªØêºÔáãèïñô÷ìñó’Àسäÿc~§UsŸ-hœ^–»]ßÿØâê“Ûó»êýTªãñô¯Üÿªâÿj½ÞéíóžÛþežÛñõnƒ¤sÈá�ãý±âòœÊáD¹áÙæð‡ÉàyÓê|¶ÒÓðõNuŸŒÎñ Öÿððñ©ËàðúÿèèêøøøÈÉÎôôõÜîÿììîôúÿÏöÿ°ÊÝI„ËîúÀÞë­ßðDÁÂÇÿÿÿÿÿÿ!ÿ NETSCAPE2.0!ÿ XMP DataXMP ÿþýüûúùø÷öõôóòñðïîíìëêéèçæåäãâáàßÞÝÜÛÚÙØ×ÖÕÔÓÒÑÐÏÎÍÌËÊÉÈÇÆÅÄÃÂÁÀ¿¾½¼»º¹¸·¶µ´³²±°¯®­¬«ª©¨§¦¥¤£¢¡ Ÿž�œ›š™˜—–•”“’‘��Ž�Œ‹Š‰ˆ‡†…„ƒ‚�€~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!  !ù ,  ÿ€~‚ƒ„…†‡ˆ‰Š‹ŠH11‘-�Œ–—˜™š›œ�pt^¤¥¦¤?-ql�®¯°±±p<(}¸¹º»¼¸2t²ÂÃÄ®rq½Ê˽–?ƒtïxä�ã\!‘ b{Ø)OSâ@Нn„ÞFl)n$üWÓ–ÁK ;Šðþôg� ¢¯[à"äP öA}¯2¦‹Ü]†ž‚#hh‹v0B/íùžÊ„‡šfNˆ‡˜ lØ ÃÂDï)€Åœ‚ j‰nš ôbÊÕa/…³ýšbEF®Ëjå%9µ.YB{º¨%…&¯\¶ò=_*ÐÔ¡uÙ2Wæ2&&´f‰Ãø‚Z¼Ï3Eõ]ègÊD¸ŽÙ‰m®-GÒìâ+/q%IÅ�rÿÙÌ71ÁKZI„W· ÀÊ2ÏK¼Š‰ƒ§ÿ†™:sÉ�œªÔ"Ôâ4=¥’h# §,‡*elÛ)ã"ê‡ÐSp5D=-çË�†´'X{UG7Ó#�rr|'Á8rD]tÔ¡/Å`NÁÃÏ‘ …fLç6Ôíð‚‹JK :Ôɹ"EA¡é!2rÓsÊPp1ÿ�S’’û¹ôªª¤‘“£²¢;ÅjZ Q� 5o#ÁS ®¯°¯UPG#"�œ»¼½»ž¡¥ BBvvag O\ÏÐÑÒÑ>\®=Pb¤¢¸�¾ßàœŸ¤Ã3Æ)S=4óôõö÷óÓÏ Ky§ ¢r…H�и`ç�­s—ˆ 0Y\ÔsA±¢EÆh3EïEËÆAHƒm#¼\ɉœ©3¶k¨Â‚…)c@ZÜ™qÌ ¢HØT£ 6áøQ$—g4”< P Ë«�‚™Š©Î�C›¦LØi1#ŒÐ>XË6í‚·Qä„e�4ËØ�õžFµc`7¬ˆ"yA”aQ£Ê™;u.&;š`@÷h2kž@¡F�!Nˆí¹´éÓ£O€AbÈæ×6Ð� €@R¤hwa]²cfc\ bP„ v)ù'PˆG-nY׆6lX¨-™2] /`O¨‘# «C“>]ƒ‚û÷ð;×HºÆø×c„ÎPÛæmܺµ³N¿gÒ?Ûpƒœr�¶HMð!¡„x<ÑBòÁ|àá¡„@�መÐÑÄ (¦˜‰†|pbŠ(¶À"!�!ù ,™ÿ€~‚ƒ„…†‡ˆ‰Š‹‡H11‘-�Œ–—˜™š›œ–HN7|¤¥¦¤N?1�®¯°±šHM§¸¹§78²¿ÀÁ—8·ºÇÈ¥M-IÂÎϰIÆÉ©N8’M¢É¥?­Ðàá‰H?É×”ŒŽ¶È-âðáäÇ7ß�H-?Ô§îñÿ¿’àÐå„™0büJ¸°a& ùÈ€D'¹š4sÈQQ’&¸ÜmŒ÷¡\?_Sú�p"¢0aŠ˜I³fÌš>`<…C¥Ê ›(1b‚£ ’&hÀ”©�§PŸ6eª4ÁÑ¢3q‚xÊÉHŸÿZ�ÂCÖ@›¤ žr°cGƒ† pÿá^˜K·îܸÜj°Ãa†ªVŒ¡ÕÏÇ]_Á‚‹Ð‚¬�ÇUò°}[anŠ@€¨Ø¬Â‚çÏ AsÎ äòݼ|ÿ6<'PS7+�è’Ç�¹@‘{Ysg ‚@¼¸ñãÅ…ø¼¹ô]·þ&̶ìÙ¯ˆ"HpÛ—ïg.`þ-Ü8ƒó $¨_Ͼ=úóɃ{nžâ\ ÑW'°rO©Ø>æÇMÊTMEµ]ZvìÑÃ4D˜pà €ÞzQD±À†tØ! †(¢‡n¸@†ë¡GœplfZT<ˆGÕXc‚ ˜U�²�5%hãvh95Ñ“½%¸67Dù‚zrø!ˆ!d \žP×_R æ˜d–9&˜\jb‰'F¡cL€Á ˜a� 6”VŸ}÷i�ÇŸy !(]Ú…ˆ&ªÄ¢Œöáè£(D*餠P)˜BƒQ6VÕ”@ñăOœ—e—aæÛoŸ)ç*rÇ1€œ«¢5çÜ\L<ØÃƒFô%USUe*l¦–N:é£È&«ì²�²pI 7D{ƒØe­´Ô.Âì¶Ë!ù , ™ÿ€‚ƒ„…†‡ˆ‰Š‰~�Ž���‹“”•–—˜™ˆI‘�žŸŸš¢£¤¥‚|¨ ¬­®~¦±²£°¨¶Nœ¯º»‘³¾¿…Ž-¶¨?¼ÇÈ�À˦�ÃÄ-ÉÒ¼I|Ìš°ƒÓ‘ÐÜá®I7ÄÆâŽ‰r‚è¬Iß¶íó�ïÄò­lúûüýþû†úH°à@ºš˜£Ç’7bZœ8›"ÄœhŠÀ‘£ˆ� CvŒð‹Ø ‹( ÙCe Ú!�#F ˜™ f‚8q ÙÉsgNœ6ÌŒù‘$¦ Ä2¤\Šƒ„A0Øl°“ƒ;4Tغõ‚ׯ`½r­�Uƒ3„Š`„£‹ÿʱD²Ô"bM"ˆ�Y“ê «Z+xM‘ˆUXX̸qãĆ�Kö¬ÚlGÀ5ôÁ\]l?Pá1`Eª_¬] Vl€k×bËžM[ökŒK›•ƒÚšmßBj‹îç_wñ(Ï€sêÁ‡¿žÍ : سkß.Á:Û®ëNqa«ߘ… ´’Ï�ã¿~(÷á#`Á…YO`={”ÿ ¸ÀH €ÿE‘�uà‰·[yfý\Ä¡b6#éRL2ÍDS_:Í âUYU(‚�²U‡€HÂŒ!Ô 8žPÃŽ;Ràã�@ù#�8Ú8# .ðŠvÕ ¤˜yå™gZ—¥ÇV[DÕ‘„d¨áGÆä¡TR�â Kôà&ªÙ`cûÅæÝuþ%…€è'’H&`‚ 2èdx‹Ù Y _ô‚£Y]…e–A�Ù¥—ý¦Erñ�Ã,s@Ä ÀÇžS¦š’Áª°1 Äšê °ŠÂ2�!ù ,–ÿ€‚ƒ„…†‡ˆ‰Š†~�Ž���‹“”•–—˜™„‘œ�žŸ~𢣤£ §¨©Ž¥¬­¦ª°±§®´µ…|I²»¼�¶¿£|Â½ÅÆ�ÀÉ•Â|ºÇмʈёIÌ|ÕÛ»IÌ8Ü�lÄâÌÎâê©èâäÓ®ô‚& úûüòþÀ°!¡¤OĈ&X˜ A*"nB±¢Ã‹ $<(B_©Ìšük…ƒÙ D2l@‘ƒ;4T˜YAE‰›.èÜ©“f…˜ìp˜!ÄáÂ�1AÀ–dd©Ì:Š`ÁB–3\ʬ 3E @TˆU ˆÙÒªU;,¯=ÿ -Ú@#‚¤”¾ ƒàt�õª62æÌ ^êH  qc�_H~¹²eÈŽ°Uñ¶gLE�ް—¤°}Eµ0)Øaa™]Ã2~\™�m$ÀØ #·ïß·mWvœVlç™@×Õˆ×ÐRaRk2�'ƒÕ†¯¹~]lÁ1äÛ¾£ˆ_° ‡ùÒ«'O^¼ïÛÃ5[àœÂ³�ÐF4'Ø¿‚"xЀ )t]C B N±ÝlßÙ–Ûx ¨GÂ…!d˜á 5tèᇠvxˆ'hÂ…$¤Ç^¹Á'@cØðV}:aÀ`bE]ËU GvÔ�ÿiÐA*t•mC„ÍP˜T€ %@Ø`Cw´�'�xQ�g!Š&Ž¢‡”i晈8¢†(ª¸€{÷¢|1ÚðÅ”gГŽ<2ô#�B꣄-ÏñqÒ/ ¬ ¨ÒRè¡�RÂB”òõ‹d*E¤‚ÈA)¥¶!ù ,–ÿ€‚ƒ„…†‡ˆ‰Š†~�‚+~“”•‹—˜™š›œ�…•  +¤;¡§¨�ž«¬­ž©°~¤+±· ®º»¬¸±³¤¶¾Ã“¼ÆÇŸÄ°´+ÊÏÈÑ­Ï·ÍÔÔÒÙ˜|Ž×©E´uÞÐÚˆã§|ê1ç§´íãNê|-òÅlø”Hõ|û•Þ‘ŠPY†z?²)ǰ¡C‡Õá0¡b&2*Á±£Å “ø{¸ªI½›*Š1�Ë04˜ÉăM,BræœÉ3f—,9‚Ü•NÝ’�è­S¤²eÌ99ر£AC…«WU”Øêá‚ׯ°V¨ªÁ‡BfÂ*bhÒz1ÿ�rò—ÄP„•`B�!Õj¯)R¢¢° ‚(.a¡±ãƆ ìõjYiüD0Â-&õ2ÈÕ$²¡»N÷R½z!0áÈÈ  6ƒ¸_ÔÞÍ{·lÇ…'W®ŠYóÏm/Eä3q4¦õnÂ+³ÁŒÕ€ 7žÍ›�wÂÃ#¼yór¿Ø AÀlÈ*„[.¾6y"õœhóü±¿ÊŽaÀ€Uäv‚ÁÆ�ß™E DøÀ„ aá$d¨a‘ÇÂð@|WÛ{…Q6}k¹ä’€>PKA(”žÒ€4ºø’^3 1Ã�v‘fC©l»yÞƒN¨aT†p•'Ô %\véå—_j©å•Tj8a„†ç�{8fƒ @Lq$XvZ=µÈY�mYT× 8Ú¸�,ùˆÀO$ E�DRåk­&Øk°96(öBêuê©zŠ…ºA D&\Xv^v–F$ú>ºçJù— äÚ‚6@àë¯ÀBƒüQÇÄì²¾v‚«®Ç!ù ,&–ÿ€‚ƒ„…†‡ˆ‰Š†~�~+‘ޔދ—˜™š›œ�„• ”�‘ ¡¦ ž©ª«ª§®�‘+¯µ”¬¸¹­¶¯±‘´¼Á~ºÄҵ¾+D®ȨÆÒ©Ð¶²+¡s;‘E;ÏÕÃÓ›ã‚Ð1|êNâÖ²”ÚÜ××Þàí éëÕ‰÷øê|ìú�: k@¼yçÕ ×.@�Žä|êç0 DP%ܸqaµŠÉU,¡dÉ&Rª\i‚ˆB ˆp”åmΦ‘äXáÔTRĈ‚&š �ÑL<(]ªt –žwµ­§Âpl¹õ\B!àP(õßMÙå~£á§7^ØOBÌ`¤F€ $| .ÈÝw@(á„v‚†'Ô e téå—`~¹e†Z8a‰Qœ˜žl”Ù`S( œuP=áØÔŽ#UE�>ê·’iŠC]þ¹“�J!E¤QE Æ[¨a)m&ÖZ-zÅÕ‹FBŠ”RyÞH¨¡ý Ê'~ˆ!ù ,9•ÿ€~‚ƒ„…†‡1|ŠN‡�Ž� +’�•––‰‹—›œ—™|Œ�¢’+ ¢¨�Ÿ¡©­›«®—¤’±¶°¶¹ˆŠ ºŽ¥µ¾¨¸Ã¾ÅƃÀ¥É�ÈÍ®ÏÉ¥+Я¼¬×­ÒÉÕuÛ•ÝáØšáE¥äŽãëâÙä¥:î»æõœí©üü""WLTðOD¿îôá3¤Ð�¿#HL@1Aƒ‹…0ñÀ‘‰!/VL â?„º.¤ð!‚Š >r°cGƒ† 8q^Ø ¦„Ï);wæ¬`Sƒ3@6 XÒ 7x+=A-ADDŠ1g̼YagŠ@€¨«Â‚Y ‚¨ ଲaÿ�|Jô¨R’F ,×+*¦©~ª^ÍZSçW±e-X¼X€ãÇ ^H–¼�ÁcŒÛš+W¨M ™Žpúîž_vP­¾¼8£°W±f_f@›�„Û·£ÀØÍƋ۵-;f¼YEgœ@/%Iº‘Ê}„J÷W°àØ«¬âlbÙjãŽe�ùèÑ“ 1¤½{÷$Ò›_@wíá‹ßª˜KTy‚ƒâ/6l î:¸q µFI}Ò�wÜ-ÁU6‘÷ÕXçõœìÑEÀ�Æ’ðÀ‡. â… È÷B{ûñןhPQxMÄÒ.a$Â�/Á“L3vØMFô $Œ=ÆÛ„¾…¸ˆ ’@B!œ å 5Tiå•XVI�•'@Â`Á¡|0,À^p¾Y`Ž©UA�Cr0ÃO©ÕÄ#ŒHáX#>{â˜cLwbu“3j‡ $ŠÁc6Ø !Á%yá’ <गPN)e–VRàé§ nYƒ¦]BÙá \èÞzh°Y£@L‘(€å•isâdç]0é‰1od l �°Q $«ì²ÌB …%R(ËC!�C³ttì°¾!ù ,K•ÿ€‚ƒ„…†‡ˆ‰Š†~~�~:+“D�E‹š›œ�žŸ Œ�£¤£;“+£—¨­£¡²³´²¥·¸~u­u¥u­¨¯¸µÅƶ¹É¥¸Á­ ½¥Çר…ÊÛ¥E¨s¹ÞШÒ�ÕÐÙé³Üì�s¨E¹§“ ÐE:ÀÐDà�ê.jÇ­ÎD¢%{GÉϹqÁü•ˆˆ ²|2:±xk€ƒâ ÁÊ�×£ !Jl‡Q#Gb/sµä³ñ¥G�›)ã—jÔœ”­ˆÈ#8³fLRØŠzòx dNT:41›´Ã�ž“ŠDí¤”¢¬®‹æ`}Z䊉³ED¨]«6‚ÛÿžeE„)ظ›Àzý¤ѽVgŸ]Ä ‡X<(f"¤±c! "GN�@ðœm ý ¦5oFš{Cõ5´C° ÅŠ·`¡¢¡u… JÈ.‘â‚íÛ·_¿Ö°ÅC X 7 ŒæKNWÜ]4:´¦æDŒ`rµÕ)`_H‘*_‚ùóè-€WÌlvÛá <‚f[uNÔܹ"½Ñ�p_bŠýÄvÝ�g 2¸Á 2 À„VHaƒã�§µÅ×}ÃQ*ËÒŸˆt%Ý}‘%6[ ì©° ƒ2À€0äƒ<öèc�6Úø „`xÆW�ÿôq°Åˆ+ìWȉ´¼e%[j� å–ÅuyÄ`BÑÀ ®mç^Œ'a�W ®P ldÉ� !Ò¦É{çØ9øDa"Úpúqpà�*Ÿ8 ²Ièä sš�ª‹ ¢«×¯ÂFø³Ô€yT¥ÊJûÇ*VCaÿEŒ� n‚<òšhÀWˆß¿~ù Æk¢°#ºŽUÆV-'¶~½�K7�å~9ر£a‹‡%ÀT¸@º´iÒF.‘—à !|-×M¼øñB’Žc5ŽlN.‚ËBfhÖ�štŠ*‚(b¡¹óçÐU”º„Ѝ+h°Ãvƒ³k_jœ;Sã:tüÆ<ƒsñã@T¨pÎ È‹ èßÏ¿?ƒÁ€sò�ÝÚiÐÝwàÑf yå�w›‚ø–_íg\|Íàá~¾ƒ$–hâ‰À "€ûy@sb—š‚°É&‚x†@á"6EPÙ…Ž–‡¸¨H¦ÃÐ’Q,àäD)e”NÂ�CLJ€$-¾h� ¢¶]�ˆÝˆˆŽ±ˆ—WsÑU—]—õ5ÜvÂ� iC‘ì—¤Q4 e”$B'$ªh Œ2JÁ£�F*)¤�&zh…’@å�’ˆ¤:gƒ @Lq'̸�kÞ1Þlsy¥æj®ÙU›s½ùÛoq6 ÀžAœ�zîÙá‡üm)Aˆ/p¨ Oú€•Wæ ©¦RFûl‰[r j¨Í‘z\iì�A°¬¶j™loÆ*ë¬�!ù ,^•ÿ€‚ƒ„…†‡ˆ‰Š‰~Ž��‘‹“”•–—˜™ƒ‘�+ŸDœ¢�:ŸŸ’šª«¬š£¢ ¦¨¯‘E¦´Ž­¼½«ºœ¦+À�;Ã�Æ»¾ÍΛÊËŽ¦ ÓsóÓ�ÏުܢD¦Òºu·Ÿ¹áœßí“뜞 ÓÉð¢î‡÷£1|þNûÅ:µ¬š¬€ÆúýCØ�á#…|FÎØt+Ô9|Q"Ãg[üTÄA„“(Sž¼b‚\>A!_jŠi餈#¬1ÁÓƒOy4B´¨&>}2IÀ48EœôES楪‡læl:TŸ%Š-1%Å…³hÏN ë¡B pÿíp˜!D(Ó§#¤ªÂj•ß?n"`:t;Ü^XË6l�Ç�X˜Ly2€ T¨Â9…Ù n5È­ÛÀ)ÔWýEì‹©jà­…+ö D…ÈA�ð¢·ï t  xqÊš�|~«�CÝ»yýªvÂ:õ?A‚�!ûlŠÚ–0ð½��yÞ0Ò«‡E‚û÷Ì›n|rr³¡�—vª7ÑßêˆtÁVÚq—ØßÙf�qºõ–^{QD¸À9Tha$<ðÀFØž{òÑ€}Ê�õ–ÏAÕŸ!ÿ©¢R`"ĈӌO=åWBÑÃŽPT€ x  ›|îI8a…C ABˆL2y 5D)%RVå“O6 \jÈá†(Àq6(÷h:ò8QBíwW�QÅ(UJ€¥$çM8Õh#aB 1ßv |gƒ A )‘xÈ!—9lÉ¥–XB%˜fªé¦WfÉ$—nf˜Á�9âd‡1Å  `šhk¶ÙœqÎyR !ù ,g•ÿ€~‚ƒ„…†‡1|ŠN‡��+‘+EŽƒ’+–œ�ƒ‰‹ž¢£ž |Œ¤†D™‘D›�™•©³~¦¨´¸¢¶¹~¬™;u‡;‘¼¤»ÈËˆŠ§¼ ’;E¬”�:E¯ÌœÊÛÞݳu™Ѭ®Þ¸àéÈë¤�‘;ƒ˜¬ÁìÉηø¼î£«‘tšC-¥ü:ùK˜/-’Š 3—‰ˆ@†�b,¥W±H Ñûu@ØFBOZJéHœ$“Žþr€P%K•ͦ‚·âØ r@EáF�‰£H‰Ì±ÙgÃg¤È]AšA‚« hÕ*¤k×<[<ˆ»EÈUFŒZsÙM§(ÿ›:"'b„Õ«aÅb±£AC…¿/<K‰ÃˆK`Ñ`‡Ã !ZϦÑ6Õ[¸‚üE¨{·��ø‚I ¤´ŠÓ*,¨^ÍZ5ƒ °ƒ”â!E Ás€Ü Ú•ÊÅÌmøf»Y?ó l[ÅlØH  ºõëØlx„»€Õ§�ܾP¡ïîÞ¾×Ï •xq‡œ³6˜±\p ©-(ñ¢ÿ  È€hà�lÃÖM§Zx·åvÞY”­4\:•¥¡†Cux„øP…UžÕw_~ÓU 0´Ã0.ðÀŒ3’`ã�8Òø@ÀE X�ƒ§ÙFžJ†´ú`@j©ÕáPÕȆF¹$ZXmõÙ ô˜Ügƒ~Ô©8 ?ÂH# !Äy !Ì9g xæIÁž|öéçžyÎg7Îè#�«Ù`SŒ ¹éöØVX-%•VþTå”uE©Ö–twÁ˜vðå`öÙv~eÔZªM§kšibà¯×íÊš 6¨PÚx€õÕ*Ž ‘ÇÐ�•o¤J¹[U!ù ,q•ÿ€~‚ƒ„…†‡1|ŠN‡�„+‘Ž„ ‘˜+D:”�ž„‰‹Ÿ£¤Ÿ¡|Œ¥‚˜s¤¬™+uª¶§©¶º¥¸º±+ªsE²À»¦Š¨ÈÌž½¶�‘EÇ¥–œ͎ÏÙܠʹÕÄ‘®¶°™äÝ…ÛéÜ륗‘DÈóì†îöÈø£u™œ»–äó&j`³}£~a3˜ !ÃQ= È$ð!³ˆ)aìD“?B†A²¤I‘Ô,n̈蛪‘#Fä1AÓƒ� ræ³'O�9M€AL’)ºd© #LCð´ã¡DU0²V¸Àµ«W®Z+hk‡Ã !A‰‘”×R¦¤ÿöE1*N!38ØÑ�•+˜%‚”PAØ‚áÈV¤qŠ`Å–EÛ@툶�V´nnÝ»3öö} ¤0€ ¨_0Àºµë×­Èp˜0ÈÄjà€VèZÌ÷Þnv¶”.Ôœ¡ùrMQÚðlÖ^¼€¡Z‚õëØ³3ؾ=¶lö!gÝÝ›([�‡£_á3Îä[™«p.›5w 0òÃx° ÿ‚  DÅuÜyÞm`i`Go¿5¢Ù'(ÍURLuUTT;Íà¡F€ "ÌÙ`A}ö1`��ýH‹!„pÂŒ5ÔpB�8R ãŽ<ö¸#Ž3Æ‹$ Xà�t÷�_a6ØÄ"‚€ÁxšEYe¾…aI(�T¡IƤ!Tvᔓg¤¹_ñ•h"}¼Æ�ŠHg'‹þ'àžEH �H&™ ³æäc]UFšg,aå•C©¥å'u!ù ,z–ÿ€~‚ƒ„…†‡1|ŠN‡�‡D+‘ Ž”•–—‚‰‹˜œ�•š|Œž„s‘‘u£©© ¢ª®—¬¯E¦“¯·”±¸»†º®¦E¼Ä™Š¡Åžªu¦+ɼËѯө ¦DÔ¸ÖۣݞÎsÞ®àå˜ç�¦è«Ç­ïžêœ¥¦ó�õúˆñ¼�"™¡ ÁƒõñëWh!¡‚"FŒ@@11š "¤£ÇŽ B†L@2E‰" JûÇ�S=ˆK6èÈÁŽ JèÜY˜ @ƒ­@´‚†£v8Ì2Ò$‚)U9lé§[„ˆHΜQSQ )R€)„l�³hƒ°À¶­pÿ�È ;ÔhR¦ œŽæ’%UKË®ÆÜzókX pÙØä…ãÇ�_l`  ²e2h7ÅУ˜’|*–ß¿¹XbMrFa°ˆg®Ì2ŒÛ¸sߎ"¡·À)WÖ̶ó¢Bç5ÕÑÔ–¬"ÄdíÚë…±-h¦ üEîàs< ¾¼øQÒûn9sq ž�k°#š4ß^§w!¼*¢¿ÄÿU”•V!ÑÃ�PTp]v³ \oé-°À’0Ä…'„p 5tÈa‡5PСˆ z¸a†!¤HŠJˆ^oìa¶™ ðÅwœ�*RS£ˆR)%äB@F$Q€¸ÕQ ®…�Á“g`gƒ Ú5ø éE!!…ã‘�â—'nX∔iæ™$žøåŠ$´ˆo¿ ç[SÆ“œ�œyô™€¢ÑÅ ]Xaè¡J$ªh !ù ,ƒ–ÿ€‚ƒ„…†‡ˆ‰ŠŠ~�Ž��‹’“”•–—˜…�� +žžDs›£¤Ž™§¨©¨¥›EŸ¯¡¬²£ªµ¶«³�s¯¼+D:¹Á¦·Äń›½½ÈÂÆÑ©Ï�uË×ÍÔÁÒÜ“Ú�� ¯sá¼Ù߲݉è›1|ïNì�®ž:Êž;~uå¯çò¹îàýk$h £€|â±ÛÊ�ŽWuí[æÏà(„ ±Ùȱ£Ç�‹aTuo…AD>) 4‘Ùu#Õ¡ŠyjÀ+7"Ì1Ás…@�ØÑ³ßKi4ebJ:)§ˆ#˜ð4�%A‚B ;ú™cÌ×°{«(M4ÆOäÁ„ ].#'ÓÏÇ�.óé"²ª•Å–5mÂÄérÞÍq’&u`¢iP¡*� �ÐѪ¶®zJ*bÄ`ˆMРlYh=PÂÖlÙ± ÿÀz•ÚL+VPvqý:¶[vìhÐP¡pá À”Xì±cÃk°Ãa†�·qŒAïлµòŠÐ�X¿3®€8E @TÈVa¡¶… ¸ƒ°]{6l ®žÌárƒÌ#:o zùgB¤ù¢|ØulÚh×. »÷ /^l`à½üöݽU>¸øñ¸›51o¾Hki² fPo»ööò ȀŠQ¨ €z·]zë çžXp–È|ô]øY|‘¥a¼†ÝX`(. â´èb‹+.€b�:ˆžz)°gÇeð‰€† LEZT^}VX§•%Ä• LÚaPb"6d@w&J�"‹�à% !„ dÖ`¦™¤©æšlªy&™b†à¥‹*&(Aƒ g� 61” `0q–™5Ö‘EF5ÕB U‘^išiI6 ˜žAkÖñi‰Xfy"ŠQĨâ‹/’Ð%ª+’Jc�Ýig[ŸÁ ·™VÖf"º™¢‹;ukui-biometric-auth/images/Other/0000775000175000017500000000000015167732630015727 5ustar fengfengukui-biometric-auth/images/Other/16.png0000664000175000017500000000121515167732630016662 0ustar fengfeng‰PNG  IHDRbb«¥TIDATxœíÝ1nA…ñoV©éAANÏ Bc®à: uLK“ÜÀ¾�kܤE¢À´i¨m„erƒGáY°A$QíýÉþoÇÀS`<¯kóRÊë"i ¬êâ”m„xx`^¯_tÀI½yK"ìÓxW¯OФ5p¼>·šj žï�M‘¤ºø¤á@Cö  k=El%„‰„0‘&ÂDB˜H a"!L$„‰Ø×�ç² p]ú;I�ÛÍ2\¥”ï�_M6ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H»„¬¿}c<ŒRJ�|"l$„‰„0q°s�ŠÒP>&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜Húõ.ê7M'¨þüóŠÌöòŠL' a"!L$„‰„0‘&ÂDB˜H»!5›b¸~žy¬êõq“Q†­?óU\Ö›W�†²þÌ/‹¤Û—L�e“‘†gÌëõQWJùœ×…90 6‡lϸ�p^lIšéîú‰C iq�s›Ý´éXÒÅ6¼ÚóóÛ�´¾Ãy]HïîóoD+ê9¥õ|IEND®B`‚ukui-biometric-auth/images/Other/03.png0000664000175000017500000000326615167732630016666 0ustar fengfeng‰PNG  IHDRbb«¥}IDATxœí�»r\E†ÿ9{±! œB™’sžÀ$"á;!¶IIì7�Þ@1JœRE€"H�KU&t‚-i/j‚�Þóokæìj¥Õv±ýWMÍå\<§¿¹¬ü�DdOD^ŠÈo9­ªcì¨DäøqÒ¸¾‘½Ú _ßâ…VøûÝHDÎî·×úž”_vàUnûÀ €¿üñà_öÿÖs_8ðmn;J)ý˜DdÀin|…„Ðæuà(—¿k¼È•ŸR'~ÉåIDÎ<ð=€?·Õ«Õ7~pžDDrãW[ìÐ.ë=4ÛîEh¦áD‰„' NÔßv–¨ÁìÏ0š´Êkʯs.Tw¥m€hôrJ¹ Ú k{crN ÜÎj 2ƒ°4¿6õ Õ't}ãÚ$ˆ€f�ê£ ~/×Õ—RÕf†˜¦è15å)µq}ŒØô–ñèÔ}�hÐ}�ß«ÁçÜa:3J³„�4ôoÖ–§Òrdƒ¯A¶£B×&T×òÔäcºÆðo¥>€sOÖx¶`ˆ6Àœhg·ÛYÂ`x–0ˆÒì°Ë”Õ*Ë‘ùÓfƒ>ÆbðµmbÒ˜®¯¢sOæ""_®ð�øA¡l¯mŠ�= ƒ!tá½A¿ƒGd)øvÔÛàëÒÃ�Öà�p3øôgȈګ3%¥ô°úҔЎ~›pÄ‹3ƶ[(¶�ÁðS›¬Ò,àQÏìS 4œË¶>̹äz�î­é€ˆØÑ§£ã1€Gùå�r.I Gë}*÷Ì= ZP¼·Ø¥J�”~Î&,nÖµ¥ˆg€]~ìèç‘>Ê©T¾*äœ.é™ùÌ‘>€©Î §GAÿœ`|–ËCj{œŸÑ:éç6†À3Áî!¥�œFiŸ°¿ x©ªmÔŽ]ë9øÓLú˜‚~I�¾Èå+ŸrýÀÇ|ý_´³è*÷µ‚˜äÆ”_RûX›ì/˜Û>s—g—Ý[±¬¼ê}wyƶ�RJ3)%wÿÛÜ¥”®�ø[“' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„'R—Ëš÷&<ýÒpSþ|ëxÿ•<ýDDš¹§Z'Jëv©®•êrÉIÝ-‡…œ-GÙíÒº\Z‡Ë’Óe—oÍ\µŠ%uÉ v\ȯÐZ‘²�¨–/)×ô)çTÿˆÖ%s `("#a=Põƒ/sð.( jAʰj1Ê�çà—Ì{­ ¯5àe—d Èú¿2tk9ÍyÍNZë#,Ÿ}`¯¨�“¤é­)ÀOˆº\^‹Èe©£±5е&»ÚÖ3÷t¹&ÛÙa�°7,ñZ5{Ñ’á®ZN×F>—G¦}T¸Î¦½ü̈ž³Æ¾s¥”&Àj–Ôj>+hÝåÙc›ýµ'9xü±ýœ—LÝÙ¢Ú:êk[—G¸îÖÜö³d¶[šÖt�‘K°,¨Ò5λ-©WÐ5fËTƒÅut`Ê:НLÞå¨_:Þ€ƒ_ò/-I¬e.ùö˜‚.güš~ic³v†´ÔS·/íYÔ?-»-�Kt/%C܇m] ¸óùEd`¦¼[ó­Õeà&–n7pÑ}`Dõ¡©Ù‚�ìƒñËyÀÊs/³½÷9Òp­6üàº>È~†¥ÛÀ{j¿ÅE‚·þÅE‰€s ˆiýãRÿ Ï‡ÃK²çÇáÙ>xþ-#{ax.Ö}Àz3©Šuð P&¦Xß ë¯Ñòâ`?ޱÓ÷gäøÜ‹£”""Ò2|÷$“m“é½Ö³‹°qË2b ¢e ÔgýãYüØeÅÚ?xf)-ˆcc­RÊXÏ&hŽM»¶zVlC´MF w�G‘"á|Àbÿðt·œßÍîQÅwIDŽD么üšËP�aO%"g+ÄIãú\DŽj'|¹Â ­Þoùû»‘ˆ\¬·—zž”OvàEû Àkø}ëßìÿ­'¾ðÀ7yì4¥ôC‘cçyðZ¡»×S§¹ýíÀ³Üù a›z àçÜ~–DäÀcßøcW³ÚS} àï’ˆHür‡Úgý £]Ï"Ô*@8Q€p¢áD‰„' N œ¨Ùõ*¡ýÏðˆÚ‰>·}+1µ¶ÀŒÚó Íwm5Þx¸Åk  ®­5ঠt�çÔ3Z,…t0榭}­g¸{Xï<¼¾«Dä‹ _@ƒÜäv“û\FÔNXÙ‘L{™4èst�æL°�S3ÎE?›bƒ€RJÿ›]šŒÑjŒ‚­KPtAÖc4#,› /K¶p�9#†jÆg®¨^ ̺ ´Ao Ea¬ …3‚Û@fdîs𧸠¡|®5èWt _I·1pˆ.È ‚ÇK`´}Ph[(6;L-3€z6ðòÓü+Ü„`Ø OÐeÃãƒ2e à7!Œ ý‹ 8KJYÄÓ—!¼_ ÞæÔî[~ø× óÝ­Ç0ˆ‰·Æy¬¡q~‚[ÐPD €ûÄ!nBaˆµì©-g%(vß°ÙÀY°,ødl­Í�£ ´ö¯P~*ì]²^x РÜp?ï0÷µS_ËØ´¹Ô–µ¾=¥4?ûûÂî Áf/9¼ñZ aBcŸ¨žæz’Ë'ª¹|¤öõþ$" €™f`Lí{¹|–AÜð€À(€HJmùê[–†<Ζ@ðRUzd--Sv?˜Qð5Ø}A¿ÌíK ú%•óø:ï§ü�ç B/�òÁ¼/+ö¸ÔS'sîR0k®ÕCdak-•¾X*¦î+v�â¿›¤”Z)%7?÷÷I)¥9ÿôs£áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰Ô&hŒÖaƺԨ »Óܧqµ²uÉ.ˆý�†ºÓXgš’ñ P7H©yú±A‰5Md'2®Õ�†�iØ�æ#ÕZÔ‘æ’úÐÙ ]å7–MÔ�F'곃 °èc¤>Ì“9Ìd› ¦Ðf |…Â0Ô¨‘=›Ø§‰¡¨Ô@Kë’S ÛÈYß&kÇßwbjk¤}…Àmµ Rë ¾Þ€¨;ÍLD&(‹­ã8ˆ5S,ðR&”\Ϭ£ÃQ(Ú/¹˜u;Qk’ØçXfØ¢YÁPìØÌô§æ³k¥”&À0+¹Z’ÖÛÈšÔj{œûMîk­YÃl5�¿’ƒ™Àæ¼*öeb�¤>#E ek¹ †�Óc«VLC=ýæhSŒSªÁÍÉò>Á0ß¾ÚrÄw~iŸè3ãí3Ûµ7Ï2;Ñ>(ÖÕ²¶·,dAI«Ú�²Ë£T—Ÿe–£µàóÏíõúýÁ9{û\Å,ë÷º J ”®ƒÍÈnkÀ«_h3¥´ÄðF<¢cØý¸äñZZ‚¬µ]ÍVΚ³[Sv6[´ÖnöéÉúýÕ6v jéÝ_ÒºNÈÀM(zÎÒ]o!Ø;ßú»òÒÃ0@Ÿå¥ è–'c(ÖÓš³OÑy…[óÅR¦¬­M€°Ò»…U² íÛt XÑg1 ”³¢ôÊ‚Rv”€ðcïF‚^R#Ý»¨¼«‹`1kX5/W»$ññC~Èi=§v °èD¹5iüã™»W¼"Ó“„' N œ(@8Q€p¢áD‰Äç;›Åþê:æ#ç¹ýd'SÙoiÌÏGÞæÎ÷;šÌ>Kcþ6‰ÈÚ—À ¯w2¥ýÓS§¹ýx”RúÀ«

HDÎÖˆÛIí¤Ç"òæ'|¿åïïF"rq‹x½‘c>Ï¡® “|îIEND®B`‚ukui-biometric-auth/images/Other/12.png0000664000175000017500000000337715167732630016671 0ustar fengfeng‰PNG  IHDRbb«¥ÆIDATxœí�¿nGÆ¿å? MúäÞOà4J“WPí&µ•6�ýÒ¨Ž·RDUÒºI-’Ò.’â¤à�ùq4{×=zØ B°2®Ð9°±0õ9VPnéÚ^µojP5ø¨9Wƒ{%{ÈëÆ¯ QVÞpÄPX÷58` gŽ=�Ù5è+Ãs©×ÕøìCS×ûy²I ƒ‡! ÃÐs6ú + F��ò� FÆX7:{Àw½B_WL›¦Ø#8>´y„wX/°¬'¨Ñkå¬y½‚ÚY÷¡ã·`æÎ5öŒ[¬sÕuAÇ ‘Ú®§˜mªY 0Ãr¸áDÞ¦>¼ý o~ϲýòrL숂š:×<�ÑsV»VÕ6¹&ýkð•öIײ¶X³ìN7Œ¼ÄŸÝ™ó¼‘‡‰ZÆÕA|اܶ{ž¤iùª¶Mú-üƒÕp¢�9¥¼–èóž|o_‚7‹Úö¯UžÇÚ� ¶íЙió¾Í̶•�´ë~wBg;5Ãwyòm ÜÛ:üÍ¡¶48CÚ·GÛ2²Ö;º€ÙJ»‚Péç}…Úžƒ� ¯Á×î?p\°©åm¶J�»ûÕÖ+øËµƒ½…wæl Ù8Õt_ª€›zíé¯eR½X`ƒò&OP8lˆšgx“ /vÔ¶Líöéƒ,† K; tÿ:� ìZ¡¶3×64iiã†ý.S / ŸÜ×iX:eä1Ó~�Æn�MðµÞË“÷åo&e½Ä â;7Ûhß <ñ<že÷§ÙØž7lúnÇ #¸¼þéM}€¨I ´MšDe×ON‘@ÜGO€*÷#‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ Éê·¨èµ'*µþDfÿÊŸÈŒ¤D "ˆD%ˆ JA” ‚(AQ‚"ñyo½8\}²ùÀUSÙKW[jó«€÷ÍÉw=uæ�¥6_DäË.€S—½téðt༩?”Rþð¶i8pàY;=ÃÒÆ ámÃ`)9“ÝuáýÅC�ˆ\ÜÃngµ›‹È»nøá‘?‰Èõöz'"Ç|Ÿÿj¹IHÄ ¯UIEND®B`‚ukui-biometric-auth/images/Other/04.png0000664000175000017500000000317315167732630016664 0ustar fengfeng‰PNG  IHDRbb«¥BIDATxœí�»n[G†ÿ%�¤8Eà6�¹Ï8�Óä\»Im§Mc¿�ôª£Æm€q•´nRÛA§t]x™ÜŽf©Cš&áüÀb/çpyÎ|{¡Tü �DäXDž‰Èo5õÕöT"r¶Bœ4®ÏDä¸Õá‹:´ú°å÷#yûq{¡ý”ÚÙ €çµíwçþðÇÖßìÿ­G¾ðÀ·µí´”òc‘Ç^ׯç˜AH}z=pZËß <­•Ÿ‘¶©s¿ÔòÓ""o<ð=€?wõT{ªoü à]©�_íð�öYï`°ë§HÍ” ‚(AQ‚¢D "ˆD%ˆ êvüý³ÁÐÕ²Ö‡T.õÞÝ'W‰“ €i­O©mBu-Oé³[Ó6@h`;̃>¤ö�IÚ¦ARÙ¦e’Fš`àºæcʵmãê¼pCýiÀ5ײmP®×íL`(Àm @†Z˪Ûàëu0ÁmÜ>0ª×5_WïÜ¿yùr�N0 ç�iëL[ŸYÂPZKÐ^š¦T·Ë—‚ >Cc1ø cL×´Ü{i+¥ü¬·4‡˜Uß™vmóu”&C°`x¦´f†Ý‹K‘…`gÁ‹Á·3AÛ9øc×õžk¬e0 8CXV¶¹ʼn—0NÞR5 2kêä¼Ùàó(ç™ÀlÐmÀGNûÈ´/Ò€ˆ 1ÍÞ:þYMG5?4åCjÓòA­[p-(viÍŽÖÌð6q»xK‘]†4€P ¦Öµ|UëW5]¸¬éÊäÿÒçof›ˆéŒàÖ`iùÀçîÕ²æ ÂæFË ¤‚�Àîvy²m¼?L�d÷^ŽìòsE9ð‚¯é‚òŽ€Œë3Nõ]:(¥ŒDä¾ø¥?¦Ìõ>÷Üu­õ3Öþ\�ö¬/»¯ÏgVé÷F¥”K ßñI~7§•ÿâ¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚"5W<ÀÌ«Ïú·ªYâ=Ü6T<¢ëGt¿zøÙÜzúY;ÒeN—ìñW°è|É–rÃú^Úî¹{fºl¬¨¦ŠÌ}üÔPQsëíwIuNXôù»ÀÌÓO½Gõ0Åkµ’Ó‡ÕÙBN_к[oÖqÍ'5˜-_;NÚo+Ùïò¬¬µk;mÍ[.ÇìÝÊN—-‡KvºÔú•iãd¯±u逨¹âDD®q[j¶ëY†.ñÞ=^[g>ÏׇÔn½aÙ Ó3Wô‚Ì#�ƒÌ£|ä$ÏÃÕ»‡�Y›RÛÏ<À¥\w›+Jí`Ùõ–+${®Z[Ï1æàô!­Y¯ç˜ÌÁg¯pï™&”{3€Íu=‡c®k@9·,¸;!°ú¸\ fS‹ lõ…tùá©=Ââè× �àÛX·<Ä9鱞›>(gKjï8»Gxžß›vAѵ¦V±¤¶�ÖQmGsËܳ¢öÜ�—YQ¯ãûÊ3”¡Œq{`Y‹ê>³gY~'U'ó³¨êóÌ�\b1à­à÷õÿ^`Ù9žZ ¼3#¼YÒŠ5m·Îɽ¤ñßä™ÞvsµÇ ±¸ö{Á÷Ü“ûœ¡¹·MLYë|X‡çžoòÚ³$ÖÑ{`³'ªL1ÛKXÞ}Ï‹hÙW‹0ì¥|nDk™²3Ã;ÌÃ[¾xÃߨ>õÑ6úrV:ڽѿì¬Á¹•=gÈóç¶æíÀ,Ð\ú¦½—k›%œ= ‡³%¡œ%óÄËP[á 3ô Ííç6÷)ÀƒràéôaDä‹~¤Aí/ÐîúÛ ,’-¥w‡.UöÁï†ÁË /?6è¥à·Õc4A·çj:׺„¥”þÒÀ."žù}*:W:ž«gú9;l–X üòæÌà¥È®ÿvö׸¿Ä0h�åh-}º®¦gÒv�ϵ~¡õ@D4xöEÚËý>Ëíý|¬ý}:f zm/׆ >—^î À‚àb¿–Ú–#-:óžg¶‚¸Éí›|þ¦P†¹\çãkê× P‹È@­ÁËi?—'9Ø Daìç€+¤õY0 À._vi²Áo[š8#Ú>gí»‚3žŒ§*€¸1F¸ dHçö~®õ™SþMÊc¨¤¤”j¹FY¥‡/}VÎë߯5øÛÚö³ö¡ë×Ýž*¥4{Gè×öͺ¯ø_“' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N¤v£}4N•ÖåR�,Ÿà®»åîÛŽrmíFT/ãrY²§¶æŠ ÚÊz‚—¬G­ r›‘®º\ŽÐ¸XªÍ¨u¹Rù3ËQmÿ ²)‘#5WÔAñT¸ëʨ©:@µÜP­öšl5Êv£ÖÄ×ú‰[«ê6(lSmaX^ë÷Ê&ìl3ʆ¼%ßW¶ÕçgëÑ!Õ¶Íþ¯CºçÔ,^íF'"2BY,ëÝj�9¸6ð%gd†¢×”¼ÆT›!/‹ÍØK¾®Öß»4û5ÐÖõØÒkF溺p ÿ~ª”ÒHƒü�ؾdtγ‹÷[ЇW»f› 7(g…µ¤VqkÈÛæ˜_Úž`Ó–Ôì–\‚»˜%õš`æækgSŸêÕ<ËÛLÚKæì™´[3^`3&í6ƒ–5ioÍ‚’z2Û‹úÍCÓ.Íf»œ°×÷ªÛ0„„û æi�Û´-k�Þ¶@㿎-2×¹‘ï²ÂÅnm³É�›—RÞIc`UNÙFˆ‡7æõúeœÖ›w$Â!-�÷õú´HZÇÀ+àËPS5ê9ðØIªŸ8P˾tCO[ a"!L$„‰„0‘&ÂDB˜H a¢6ÀÍÀs´lÜ”þNÒ“áfiW)åä_“�„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜x¤ßߢ~;è$�ê÷ŸOd/ŸÈt’&ÂDB˜H a"!L$„‰„0±âñ`S´ë×Î;`U¯O¥mýÎWpUo^4LËú�_I#¶.˜ËAFjϘ×ëã®”ò¸¨æÀ 8`°V±Ýqá¢6Ø’4Óþû‹-�´¸ÇÞf·:–t¹Ç�×~’Ö{ìëRÒx÷œŸË”'Ïj$aæIEND®B`‚ukui-biometric-auth/images/Other/13.png0000664000175000017500000000121515167732630016657 0ustar fengfeng‰PNG  IHDRbb«¥TIDATxœíÝ1nA…ñoV©éAANÏ Bc®à: uLK“ÜÀ¾�kܤE¢À´i¨m„erƒGáY°A$QíýÉþoÇÀS`<¯kóRÊë"i ¬êâ”m„xx`^¯_tÀI½yK"ìÓxW¯OФ5p¼>·šj žï�M‘¤ºø¤á@Cö  k=El%„‰„0‘&ÂDB˜H a"!L$„‰Ø×�ç² p]ú;I�ÛÍ2\¥”ï�_M6ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H»„¬¿}c<ŒRJ�|"l$„‰„0q°s�ŠÒP>&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜Húõ.ê7M'¨þüóŠÌöòŠL' a"!L$„‰„0‘&ÂDB˜H»!5›b¸~žy¬êõq“Q†­?óU\Ö›W�†²þÌ/‹¤Û—L�e“‘†gÌëõQWJùœ×…90 6‡lϸ�p^lIšéîú‰C iq�s›Ý´éXÒÅ6¼ÚóóÛ�´¾Ãy]HïîóoD+ê9¥õ|IEND®B`‚ukui-biometric-auth/images/Other/17.png0000664000175000017500000000121515167732630016663 0ustar fengfeng‰PNG  IHDRbb«¥TIDATxœíÝ1nA…ñoV©éAANÏ Bc®à: uLK“ÜÀ¾�kܤE¢À´i¨m„erƒGáY°A$QíýÉþoÇÀS`<¯kóRÊë"i ¬êâ”m„xx`^¯_tÀI½yK"ìÓxW¯OФ5p¼>·šj žï�M‘¤ºø¤á@Cö  k=El%„‰„0‘&ÂDB˜H a"!L$„‰Ø×�ç² p]ú;I�ÛÍ2\¥”ï�_M6ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H»„¬¿}c<ŒRJ�|"l$„‰„0q°s�ŠÒP>&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜Húõ.ê7M'¨þüóŠÌöòŠL' a"!L$„‰„0‘&ÂDB˜H»!5›b¸~žy¬êõq“Q†­?óU\Ö›W�†²þÌ/‹¤Û—L�e“‘†gÌëõQWJùœ×…90 6‡lϸ�p^lIšéîú‰C iq�s›Ý´éXÒÅ6¼ÚóóÛ�´¾Ãy]HïîóoD+ê9¥õ|IEND®B`‚ukui-biometric-auth/images/Other/11.png0000664000175000017500000000372415167732630016664 0ustar fengfeng‰PNG  IHDRbb«¥›IDATxœí�¿’EÆ¿Y­dC@eêœó&9^Á±b›”Ä~ƒ»7¸'N©"à"H�ÛUÚE�ÏúÛ;mõ~׳ZIwÚÍW55³sÒjÔ¿ížQÏT`$"'"òXD~Š¥¯.p¤‘‹-ì¤v},"'©>Ý↬7þþÙHD^ía·§zŸovàIìûÀs¿øåàßìÿ­>ðÀ—±ï<„ðm‘S—±ó E·¯‡Îcû« À£xñ= „Cê9€bûQ‘WîøÀ¯C�êHõ€¼""±ó³tÌúª¡GQÔ¨€ÈDD&* 2Q‘‰ ˆLT@d¢"™¨€ÈD€×Þ<ŽcÖkoƒ^‰È§Ã�åxBø(¡)™¨€ÈDD&* 2Q‘‰ ˆLT@d¢"™¨€ÈDõÐpÐ< À(ÖÁüMÛ›¢=³eëe¬…^3¨†¡Æ®Ñ6ze®¹Ö¶½‡­�¶Qm[ n�oëÖ€V80¤C�amt­GTÛ¢}ÀuÏð¼ÃÊó-Kçz…6 Û^˜ëEì»Ýˆ ÀkÃ×hŒ©@µNª§èçxZÅZœbŸ|[¬Ñ—ThÃQ(ú9{ë&A¨ñG¦fÖ+FTصà{à{ƒ EKjëµ5°0G ™cO(7¢FcøÚ)ê &„C•†$oòNAP¥¼€C’5<{€5ö¢ãZË<Ö[kWN,„±ÓgË(qmÁxÂ!ÊÖ:+õ†Ô¤Ìs‚5º’¸Øþ9ÕãØÞÈ. ÔÐ)­Gð½Åó�?*j{!Šå…#o2f£{¡G ½¤zÇeë¹ù~ 3ôœà·LÐi‚¶‘'ð ïÕ#ªkÓæÉ�WW6Té˜lÍ+&6þ&üä«ágX?ñ‹8ŽeçÜÔ<Þ€5´Î¥p_®C°O¿F_[;×5õ³ÇXXÞ’—½CexaH¡ðäË¡F‹†šÚa¨Šmoeçym…fFÁ…!°7ŒáCÓk6…7o.±á+ðWF]“¯5°>ñ3´�žúÍ“ZV§”„Q€ˆxËC-*wŒµ=1µÃàôzDï±^a�XÏHMä^x²0ì¤Ìµõžxg¦žSÿœêYâÚ–iü. CÓKBX©GÔѨ¿ïÄòq¬ïø(Ö“X߉}”¶-0 EÖFh݆ û#�Óœò` ¥kéÚµB²¦`Ë ÀûXf®b{ÛWÞ™þ¿Í}ç&"2Svb²±ï*ä/2š·üäpÞSÌO³—_Jý€óB€ Û¦;ìjŠÛ›&x^¸ìe ’=Uj!¬Dd§"Eû)„°Ê~D6* 2Q‘‰ ˆLT@d¢"™¨€ÈD}rM]EAê½ö=}Þë�ÞèjßôëºN�l•kÒ\’æš4Ϥý6ç¤y&Î5ÙD gbS;v}vêºvéT©”F×]*51Å:é§I¼©i¿7µ–w±¾2×ÿ`�·ê�kz�w…vRï.®gdÙðÖø ‚KWöÕîê¥) Ïè}7‚l&vF5g[½,«…Âm[®pýTH¯\§°û¤¹¹�ÓÞµSófo»rrÑÛ“àäݦmOûÄsšÛK{3”Tah¶Ý²³æšúl ©‡ÌáðڀƠ¶O³�ãØÖ Ýœé³1ÄÇ1íç¦Î,õ9ÀžÀYÓ¾8;«àª‰7ç>­½I‰÷Šuƒ]ŸDkxÞ�àCv¿:µ;Æcóæ„aþV) HÍöPÀŒþ–ò$}í^[¥úå¦XwÛ\�Å5Õö)×ö ~Øá'ßÛÇð¼Á;<à�êã3Lú¤ÚùÑNØ fF}ö¨^Gk¶=N£_¡1†uw=Bb Øã%ÞSÏGi<°{Ô|Àl“Gp(´mžÄŒÂ<�áù†Áô:ȼ-Ä�NÑf ÿxL׿iG�AXèsì²ë¸¥w Àƒ27¯I�òÛd«“什P)½Ïë òMì²Ô—ñ¶S½­TU×BAë>§ý¼I=Æb—ÿ;iV:8½§gxnÓ·Í™W˜¿Á\í§pÎX9×| À®rìÜÁ`ö2¾ÕM�°²PÔˆÞòÓBà“|íÐÄa N­bãk›WvKj³‡hxñ~}ovúè6@Xé�*»jP#3„M¡hÓ)þ\­mÚ¼%.Ï7ntO· “Ge�ï%ôR瘼ϰ5'ìxâ>ˆ±»4ˆ.©�n$îþ—Tö#2Q‘‰ ˆLT@d¢"™¨€ÈDD&* 2Q‘‰ ˆLT@d¢ZÖÿ‹ú»AGr¤Rû—‘9¼Ê¿ÈÌID&* 2Q‘‰ ˆLT@d¢"™¨€ÈDÄ'ƒ�âxõÁæ€ËØ~0ÈPŽ[jóË ÀËxñÍ@ƒ9f©Í_9Aó�Kà €çƒ éøôÀyl߯B¿x;Μ¸7ÀÀŽE÷ÐØX!<‹ ‰È™ì® ï�A"r±‡ÝÎR7=‘;ÜðÍ�¿6‘W;Øë…ˆœÚûü Ê£íýÉþoÇÀS`<¯kóRÊë"i ¬êâ”m„xx`^¯_tÀI½yK"ìÓxW¯OФ5p¼>·šj žï�M‘¤ºø¤á@Cö  k=El%„‰„0‘&ÂDB˜H a"!L$„‰Ø×�ç² p]ú;I�ÛÍ2\¥”ï�_M6ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H»„¬¿}c<ŒRJ�|"l$„‰„0q°s�ŠÒP>&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜Húõ.ê7M'¨þüóŠÌöòŠL' a"!L$„‰„0‘&ÂDB˜H»!5›b¸~žy¬êõq“Q†­?óU\Ö›W�†²þÌ/‹¤Û—L�e“‘†gÌëõQWJùœ×…90 6‡lϸ�p^lIšéîú‰C iq�s›Ý´éXÒÅ6¼ÚóóÛ�´¾Ãy]HïîóoD+ê9¥õ|IEND®B`‚ukui-biometric-auth/images/Other/18.png0000664000175000017500000000121515167732630016664 0ustar fengfeng‰PNG  IHDRbb«¥TIDATxœíÝ1nA…ñoV©éAANÏ Bc®à: uLK“ÜÀ¾�kܤE¢À´i¨m„erƒGáY°A$QíýÉþoÇÀS`<¯kóRÊë"i ¬êâ”m„xx`^¯_tÀI½yK"ìÓxW¯OФ5p¼>·šj žï�M‘¤ºø¤á@Cö  k=El%„‰„0‘&ÂDB˜H a"!L$„‰Ø×�ç² p]ú;I�ÛÍ2\¥”ï�_M6ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H»„¬¿}c<ŒRJ�|"l$„‰„0q°s�ŠÒP>&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜Húõ.ê7M'¨þüóŠÌöòŠL' a"!L$„‰„0‘&ÂDB˜H»!5›b¸~žy¬êõq“Q†­?óU\Ö›W�†²þÌ/‹¤Û—L�e“‘†gÌëõQWJùœ×…90 6‡lϸ�p^lIšéîú‰C iq�s›Ý´éXÒÅ6¼ÚóóÛ�´¾Ãy]HïîóoD+ê9¥õ|IEND®B`‚ukui-biometric-auth/images/Other/05.png0000664000175000017500000000330215167732630016657 0ustar fengfeng‰PNG  IHDRbb«¥‰IDATxœí�½nW…Ï%—’“"p›À�Üç œÆiò ®Ý¤¶Ó¦±ß@zÕqã6@ЏJZ7©í €Sº²õ·ä¤Ø;âáhvER290ç÷g©åÝùöÎåª8 �Dä@DžˆÈµ,«cì¨Däx…8i\ŸˆÈAß Ÿ­pB«÷¾þ0‘77ˆÛ3=O©';ð´Žý à€üµñ+û¼õÀ·ø¾Ž•R~."òÀ«:ø„Ô§×#GµýÃÀãÚù a“zà·Ú~\Dä €û~ð÷¶fµ£úÀïÞ‘:øÍ'´Ëz£mÏ"Õ)AQ‚¢D "ˆD%ˆ JAÔl{=*TFµ:§Í§-¦µ³Ûšìmh FƵŒ¨Ö`�1À5PmWµ˜p™Q=súmí·4öÉÕx àî'8÷À¤Ö æopFƒ9„ÁX¼:TÚ3Î�g6øSªm›ûm-:vz àîå‰È×7£¾ ü��Õrà”ú§õ8ïI­ˆ4¦º"l0¸½àK_Ô¶ÖûîÔ`ÛZ!ìS»Á"Þ7úÒÓª{…í÷휋0¦ì–ÚlrJ�>¡þ Õjû}ÇY½æ™‚hë`©¶SCÅ~Î{èËíÞíNmÛC²xvCç¶·ÉýúííMSó7祔D)ED$ԓ殨”2òMa” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆÔÁ¬ÏSÉsœ\ǯé:Ϧ>Ÿ¾>GËU=›nïÉk/ã×4íé ‘Ñ¥_: û¸êdvs³;¦ 9˜i™P›ÌØûÏ3Zô -lkºÕÀ3Yä ôÙ‰ÚZ­äΨ¯Nfj§µ–�Xt2ûˆÎÁLÏq`OD΄õ¶Ó >­Á;¡€öyú±}œ >·-Š-žá"ƒé ¾g ëYÇ ™'ja+9rîäyú�8su0›‰H _ÖÝ’ïô>ÓDþLã|Î3Y´¶¥}ǟáùöy�×¢ŠtëéÇ0¬ÏŸõükÍgù¼ Nq¥”XÎnT­u§w—5˜ÓÖ *¼s\o=:ÆÕ•Àœl5º �³çõjÝ-­µ¨]%×ÙŒZ0|=ÖkÊ»¬ïë ÝÒÓé—M¨Ör^ë3tÁW7G6å2âõ‚ïíÖ€·ÏÙÛ,yoàýÁî]-ËøÁ^YžVuBž¢Ëq‹6ÔÖh׿}›b†‚Ïž³ÖçÕû5æiè× çg»R ƒ±P8�Y@<¾´-õºÞà‚î.=½ãÝýžÓq¡1[NŸ¿«7?ûÓÔ¦U»‡0�>(võxe%OpU#ówQÿ²Î êë] «Eƒ®«Às6¶ùߦ!¾·',cÒ®5¿ÀÃBñV†ÝOúŒÛ§X3ð—“­ñßä+2ûÞ1ôÀÈ€Åà÷=Cèǫ̃ÏcCaŠºéßæû"¬Þ›}£ »Ñ{âà{«Á{êÒÐÆ­ãÖ•xkÚ$ˆëÄAêƒõÙ*ÿéD "ˆD%ˆ JA” ‚(Aƒøjk³Ø]]Æ|àUm?ØÊTv[óW#¯kç§-Mf—¥1]DäÝ‹Kà)€[™Òî連ھ?*¥üày8pàÞ&¶+º‡.Æ áyeÐIDe}{߸ ‘ãÄí°ï¤Eäå'|¿áë#y³F¼^ŠÈC>Ïÿ�1†ôhIEND®B`‚ukui-biometric-auth/images/Other/08.png0000664000175000017500000000342215167732630016665 0ustar fengfeng‰PNG  IHDRbb«¥ÙIDATxœí�»ŽTG†ÿžØ�s[X�û p‚¿1‰cpêÞ`÷ 66 ©%&²SÇ`Y²C ìܶLóOmõ™Ë²3%¦~©Õ—3œé©ïTw¤ªH"r[DŠÈoµlª3©Däl ;©]ŠÈíÖ oqC«×{þýa$"/¯`·ÇzŸRovàQûÀSøcï¿ìÓÖ]_¸àÛ:vZJù±ˆÈ=Ïëà#, ¤®_÷œÖöw=jçg$„}ê)€_jûA‘—îøÀŸ‡šÕ‘ê¿xUDDêàWœÐ1ëèz©…D%ˆ JA” ‚(AQ‚¢D "ˆDõ¼ðæÀó8f½ð¦hOD¾<Ü\ŽW¥”�\šÂ(AÑàÐ0*X<ZŠ)=ú×VBõµ¹ÌéºØì[û¡Æ`iì>V�Ï<+5¬Ù– ºvaÊŒÆgX»v]'ˆ‚…‘‡X_�Þ¯}ý ÃècÕ3< »‚ðŒÏž1§þŒúóÚg8Õ‹>&ˆR痢ߨ ƒ±0Øø}øº@xeŽU(s¬™ÓŠ%„©›Öñ+éª ØøCÓf¶ßG7 ƒ=Å°Ž jÛ¥ˆ=bîÔö©ŸS{Fm afÚ[{Ë® úFXõ€V�>4×méÃ_º V—1»dYÖ+x£ö6f6¾5<·¹žb�MÌøKXï/Û‚`C§6ƃÚdùjmäžwí�¹ ‚õ~Âç¸üä3€QÓÏ k[ë V½ÔÕ¦ –Oü¨~‰í3ŒáÒÃÒ[ìIËÂ`ys×ÚoŸz6:Ÿ�=­óá¶öÕÓ§X>Húo›€ˆ¬;*Þ ãk±ý�¹64íu ªõö …aOU þ?è²ÔÚìÚÎË _›ÒØÄ€™ÐØÀع¦cc˜ƒˆôJ)êƒjl]2xù¸àsŸÕ¶Ö7kÕ1ýìÈ€Óz€Ë`Z§,{¢ÚäýNß;²Z8vI²Þa¨a'TÎk™xOý÷T¿­í·ôc#™(Þ\ôKùDôÉ.%Þ:ï³eXûÞÀFny)œšåyˆPŸß/Z/v]Ç[{¢² ÙÛØ«x3çýIPJ¹‘+Ÿ…SÛ«”2ò?ýÂ(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA” ‚(AQ‚¢D "ˆD%ˆ JA´.†NÇZÑ�^<[+ĪýÓ*pÚXÓnILÛFqÛËTÐjw¥’𢎸/d] �Ö7±Œ¡»iŠÆÑ�œÚ xä:/ì·+ô«+OІ±I¨oW€#×c,C¯4ŽnLísªµ¼Ãj,Ý;,bè8à±3†Nðy5Þ9–ÁŠZØàÚ×Ï´pŒ¶�*õàtÅ`[0Öð6¦º¸è0*€1V£JmÍ…ϱ ‹Ë{,áë\6Š¡³¡ºlLŽõúlè Ûç¶Í`À©#Ø+t¯ãe‚›¬{Ú9jÔ çµ!¿^ˆïtÍßÿƒ4†n“€÷Î@møîï­‹V;¯ßËOŸÍTУ¾ÍÛa¦teà´?J+À�S8X0šq€¯Y€-zW›fÐ$ lè!|ןѵ –O¼Få{O:ßî6Ð}[œ‡Ã.QZ¦¸¼<[�aCs ë ^¦…ØÔ6¹8æX¬ošg‚¿�óOXOj=ÆåT Æ]~ºR?lš‹ƒ7jë!ÞÞ±É>ÒŠ£ö®­Õ.ÙiØ…[YìSß•Å.=-ðŽÄ@pùÈéyòÙ[)�xŒë­3Ó»§ Môþ’có5ñÒÓ2¾ç]¹7·½ü}6›{Hk“÷’¨ðØÖÆg]KÐN!×Z÷½ãhWަ.ë:_ïå«å!^Ú‡ÎÍw[},,}¢x’ ‡O>­Üüä+иÞo:Îo·]¹7ì~rmÙ0¯„'ŽŠ—�u‰�Uë¾³•VÎæ÷c×fì.í D—øýbÝ;Ë'«üß× JA4�åߢþé 39R©ýóOd^ù'2#)AQ‚¢D "ˆD%ˆ JA” ‚ˆA|q°Y¯>ؼàymß=ÈTŽ[jóç=/jç‡M春6QDä6¸xz�)Ÿî8­í;½RÊ_žÔ�S'n`bÇ¢[XØX!<© ‘Ù]gÞ7ƒDäì v;iÝôžˆ<Ûᆯ÷üûÃHD^î`¯g"r�ïó?Íÿ|’4g ˆIEND®B`‚ukui-biometric-auth/images/Other/09.png0000664000175000017500000000343615167732630016673 0ustar fengfeng‰PNG  IHDRbb«¥åIDATxœí�½r7…V$»HŸŒ3vŸ'p¥É+¸v“ÚN›Æ~é TÇ�Ṳ̂ˆ«¤u“ZÎd&)í*’ø£›‚¸ÞÃ+`—?÷NxÏ X,I�çÛ ,5¸$@‘‡"òLD~Íe]�ã@%"çø¤¾>‘‡µ|±Á Z½ßóûw#¹ØÁ·ú:)¿Ø)€ç¹ï7¯üà÷½¿³ÿ·ø Àßä¾³”ÒIDN¼É�ϱ„º{=p–Ûß6žæƒŸö©W~Îí§ID.<ð€?†Õ�êk¿x—DDrç—è�õ74C�"´T€p¢áD‰„' N œ(@8Q€p¢À;Ç!ë€I�Dä‹áÆr¸J)ýÄÔäF‰„' =€”zÎKÏyWò¢Éåm”j_*~^I7Ô–B¹ÉE�Ô7ˆö "ai´šÝä¿ßйƔDç,„dj•˜ZÛj¸‚` 7æÜœúçôø;Ó]‚8Bkô(—”k¢�áˆPµZU›ž,„›BÝa‘ Ïé1‹ ýèÔ§¡&�ŒÑ‚8¢6ƒa6R´�Ð?EuEDiJRÙl¡¶–3¬¿ öÜ”�"fWÖüˆ‘i3Ój†Á@XºVØ9¾ dAmŽ6›(˜Z|Në�µ-ˆÀK³×Üߦ¤´^(œ®hPqTð´c§£Ú”£5o£@û¦¦jž»–6Ñ`ÕpÛfóT˜ÚôÅë‡�­�úÔT[JW¾–mŒ™þQ®�¨¿wÚÚ„¨O°jþ«&¸)v ãRŠšÚbnn­9ì4T‚ÀW~iÞŸÑ9m�©=Ëã›å±Í©n¨Öi«ÓÜu¤†«ù#s\Âu)‚J`º¢¥¤¤žïBÉø)ZÓÕ`6[/’)nO¡S”ïòª0F "z—æì €ÏÜËíã|¬ýc:>F G��rÍ0íTŦ+.öÖ¶4=•q^ yMàRº Ró§hÁ\£u�Ï]Ó±ö]Ññ•Kj\àEd`¦Á·�j˜x à~6û8aÚ710´ŒrŸBµ‹:·¹t}¾¨MM¥©Ê~š¶ ¶� Dßk:fjþUn«á×¹­è&òsSC � ¥4‘K„ö®”Òÿ}u£áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áD‰„' N œ(@8Q€p¢áDµMÈZxG÷¸RÖÙr_Ë*e ÕÒ¹J‰Ž¶¶¥´ßÕ&©”²…l çGØmú¼G–7.ëÞØõé>Ù�ûkû6!k­›Œï£Ý~�Ú¼¹´™w†Ûmý]yµ4®¾Mȶm7!Ûíúµ]á6)Åš©&ëÆcmÛúßB ´ÛöÕûÞMÈ ÝQÁ÷=¦«ØäΡàhµ9 ‡UKH©<ÇêÕÌyl|í¸ë1!ü˜Ö༠¹/QEÐn!Ÿ£ž‡P{.N)]�œ¥042/QŽ;šíi“S,žb8ŽÍ³€Øtûš¶ÍIE­“1tƒe¨qx×RgÇhÍaÕh=7EA6#õ ·×›¾e× `5«´–aÓvm^„…b�ìe!ÙHèÍ¥[7uK°„a31ǦÍ5›l¯sÍÉ‘¥ü¹Ú‚Íëp;‡®–ànÇÏ µÍ§³©¼µÚNi …¡ujÓ¬R¾RÆÔÞ4Y±vÕÛt-†Qº+êÑ75–¾a€§»x—²Š8�·j-m B¥ƒÐ+»+�·AB)OŽ�õ³ñµ;& 5¸ d�Õ(Q󆮋]ÑRº°‘´‘¶¡Òõh ¯M7µÄv»ëcø QjŸ€2­K·¯œÏQR»¥-%ÂÛŒT}îÖÚ‹¡\¢þ¡­t÷£É~µÌQû�¬m—ðÚ7ÓØ±QÃѱ“ñVŸ„•¾VéÓsWê®ýÔÜ5%Y•’ßk ìRúä}§ºK%é-}qˆýò›C]úÜP‚Qúž& CDz0çÓ¾At‰¿ªçàÿ}u¢áD‰„'Iû[Ô?:’•ú?‘9¼â'2=)@8Q€p¢áD‰„' N œˆA|>Ø(W=o¼Éíǃ å°¥ž¿i¼Íß4˜C–zþ6‰ÈC,¸žx5È�OOœåö£&¥ô'€—¹ã À)€ ìPôK�ÂËÌ`)9•íu^ú‹‡ 9ßÁ·ÓÚ‹žˆÈë-^ðýžß¿‰ÈÅ~½‘~�ÿíšPYB1]zIEND®B`‚ukui-biometric-auth/images/Other/10.png0000664000175000017500000000353615167732630016664 0ustar fengfeng‰PNG  IHDRbb«¥%IDATxœí]=“E}³’î09”);ç˜Ä$üÇNˆmRûÜýƒ‹qâ”*Aê„Ø¦¨‚ÐŽðYÒ];Ðôém_Ïjõ¹]h^ÕÔôŽöV³ý¦»WÒ›:€ "÷D䉈ü–[_\àH!"køIýúDDî•.øl� Z¼;ðý‡�ˆ¼ÙÂoÏô:)_ì ÀÓ<ö;€þðÇÁïìÿ�¾ðÀ·yì<¥ôc‘‡^åÁ§X�P±<pžíï�óÁϨ$/ü’íÇIDÞ¸à{5«#Å7~ð6‰ˆäÁ¯œÐ1ãh†žEÅ•ˆ ¨DA%"*AP‰‚JDT"‚ •ˆ h¼ð~ày3ÞxŸôHD¾n.Ç‹”Ò¿@MMaP‰‚JDT"‚ •ˆ ¨DÁxè ì‰l)ž‘ˆhraá\n:Ú$0„zn×ÎØU¿ÞÝ­¬�C¡N¡íøÚ×qd›IièZÜíˆP›�MãL·+c_á‘¶o"Fù=šÜ�Ènè˜ÉhŒÍ=7`óˆèKÀϳ=ÏÇ;Å®‰P'Ž©�hŒ‰±äpïÜ&èŽêT·Wg³ÓÙæ^ÛÖ³ "–NŸ íð’Í„pªb’¸qÝnG†G�36,jÏéõ¹›ÚF¤lCÄ Çk?v�3 úw¶�±$Ö#„#N_JI¥t¤Žc‡¯rü€|¦ôúZÅ"'X8îm§31óš—²¼ˆ±uƒI¡;5m28ýp}ðœnÓ�µ=çÏò9Ó|<Éccz½!ë1qÚ«‰áñ®H±=§,Ž›ª,øÑ”�oû®¼¯Nž9cÖñ#zݦYýûNô%¢AÛéLÂKG{Yb¼4ÖEŒ-ê!\Èöqµ«Û•o�>Ë÷`ß`Iˆ.×hž¢ýÐ1EGýèCD‚O‚¶Ü&Å’Á¯[›IÐÈâTæc£‚k„�†®Ôã9_s½ÎiNŽäÚ¥ŽW‡{jÇŠdŒ@D4}xÅóÀg¹�R’í‰é™ˆj!–[+4m­à~ §ð�3JŸ4Bfð‹ó í¨˜øˆ%Iz<ÍíÒØ—ùõKÓ>äþæýDäÀL#‚o˜ îinŸ l+!wÈá§dOè:6lвµÁ~¾ðžœJEÛ‹[¸mѶ)Škñ‘Ž• uô”œý1Ûì]HEêû4€”ÒLD>À‡ÍÇž#V�ïãïÃ�÷}’÷GŸsöiß ¥t ô«ƒ~v,¨¿GA%"*AP‰‚JDT"‚ •ˆ ¨DA%"*AP‰‚JDT"‚ •ˆ ¨DÁ*ñÿèïišìïÏ%Å_Izéé_K³.ÕŸ'RNðÅVÛäIm<½Ó m‘�Š ÔÖß·§h f4¦¿oßúŠT À‚�;(‹X8À�HOȽ'` “=áPV‚["úˆ¦¦W�ÀKņíÿsz`CñËbJš¦®ÈéŠ&>g_åik­`Ù:Þ[á%ÏÑ^ÍVF3]qÜuGŸsƒuļb¬²bÖñw쫼cY‹^{BNê’Ú¨HÙ ’ù=9±È¬$«œ¢œr8íXJ)ËÓGé|\ôUqLÉ.9Ö*®çX¬p=Vù¢Nl‚¥ŠÎ“\rŠ*I.»ˆ°óaÅŸjZW¥$«òîŠ^ý‰[K.‘'™foNÇtÒø+œ•Ò]û(JuÂÛÀÒ%BîS¨u¥–Ôß«DÈ]¤çíT„¬Ð‹v­pN-ìpoÕ«¬Ò*üJ[ºJš×·�U„{;„J{[bô¼^W6Ù!X<$Ü^áüdû®•ÏŽçüÏû!,žÜ²k£Š'Ñ/mR)ÕˆÑ~-lB„BÐ~^^w3Š]ýü´JïjkƒGp[bikë`¹~”v•¤ü×Ôo„mˆ`\cA°\½6íx›OǶŸ€n½+p›µKºS&À>`°Ý'Jv‚]ÁÐpçIò'iï)¨ëƒ›6ü´Äﯽ·™ÑKU^!/³ìƒºšºº½'¢Rxx;†€r½°iêʱ¯ÑŽ®½ãPDxà'˜®âæè®Í)\ôضp’ˆ¾ë¼]¢~ •ˆ ¨DA%"*AP‰‚JDT"‚`,ËÿEýÓ 39R¨ÿë¿Èõ_dFB%"*AP‰‚JDT"‚ •ˆ ¨DñÅ`³8^Üø¼ð*Û™ÊqC}þªð:ü0ÐdŽêó×IDîañ�Kà)€ƒLéøðÀy¶ï7)¥¿<ÏçÎÜ`bÇ‚»XøXIxž9X@DÎds\xïx ‘‹-üvVºèCy¹ÁßøþÃ@DÞlௗ"ò�¯ó `ܯƒ®´çAIEND®B`‚ukui-biometric-auth/images/Other/14.png0000664000175000017500000000121515167732630016660 0ustar fengfeng‰PNG  IHDRbb«¥TIDATxœíÝ1nA…ñoV©éAANÏ Bc®à: uLK“ÜÀ¾�kܤE¢À´i¨m„erƒGáY°A$QíýÉþoÇÀS`<¯kóRÊë"i ¬êâ”m„xx`^¯_tÀI½yK"ìÓxW¯OФ5p¼>·šj žï�M‘¤ºø¤á@Cö  k=El%„‰„0‘&ÂDB˜H a"!L$„‰Ø×�ç² p]ú;I�ÛÍ2\¥”ï�_M6ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H»„¬¿}c<ŒRJ�|"l$„‰„0q°s�ŠÒP>&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜H a"!L$„‰„0‘&ÂDB˜Húõ.ê7M'¨þüóŠÌöòŠL' a"!L$„‰„0‘&ÂDB˜H»!5›b¸~žy¬êõq“Q†­?óU\Ö›W�†²þÌ/‹¤Û—L�e“‘†gÌëõQWJùœ×…90 6‡lϸ�p^lIšéîú‰C iq�s›Ý´éXÒÅ6¼ÚóóÛ�´¾Ãy]HïîóoD+ê9¥õ|IEND®B`‚ukui-biometric-auth/images/ukui-loginopt-voice.svg0000664000175000017500000000330415167732630021300 0ustar fengfengukui-biometric-auth/images/ukui-loginopt-fingervein.svg0000664000175000017500000000255515167732630022336 0ustar fengfengukui-biometric-auth/images/CMakeLists.txt0000664000175000017500000000054415167732630017411 0ustar fengfengfile(GLOB images LIST_DIRECTORIES false *.png *.gif *.svg) file(GLOB children *) set(dirlist "") foreach(child ${children}) if(IS_DIRECTORY ${child}) list(APPEND dirlist ${child}) endif() endforeach() install(FILES ${images} DESTINATION ${UKUI_BIOMETRIC_DIR}/images) install(DIRECTORY ${dirlist} DESTINATION ${UKUI_BIOMETRIC_DIR}/images) ukui-biometric-auth/images/ukui-loginopt-iris.svg0000664000175000017500000000177215167732630021150 0ustar fengfengukui-biometric-auth/images/ukui-loginopt-qrcode.svg0000664000175000017500000000203415167732630021447 0ustar fengfengukui-biometric-auth/images/ukui-loginopt-ukey.svg0000664000175000017500000000367115167732630021157 0ustar fengfeng ukui-biometric-auth/images/ukui-loginopt-face.svg0000664000175000017500000000210515167732630021067 0ustar fengfengukui-biometric-auth/images/VoicePrint.png0000664000175000017500000000252615167732630017443 0ustar fengfeng‰PNG  IHDR  ‹Ïg- pHYs  ÒÝ~üIDATxÚí�ANÛ@†ÿ ìMP‘À"Ën(aÑ}.`‘ž ¹AÓÀ êÊ€®Y4À¢]‚|�H\ >AºÈD “�¶RüÆq¾Ob‘ÄB#ϧ÷æ�Ç3�Û»_ ðáä}G°3ÜÝÿ6ñâ€[ 1A@@@Ø_ºŒÕÀrÌî�-‰€@ @@@@„ý¡»­T”º�t()ÏRM¹µ`‹R‡’F’Î%ý,JÍŠR#n/X¥à¡¤díó‘¤oE©yQjÂm C$’¾¸ˆ8ävC-f©†’>Iº}á’#IWE©iQªÇm‡­WÁYªÌ]ñ¸}ÖD<“ô¸ä\Ò °V²TÓ,U_Ò×ÀÏÇNÂ>]�€u‹8qѰBB0p %õ)9‘" �„sIƒ€„Ç�ð0²„î™2 `4 ?óÔ-% ƃ{B×U¦1%\­œ¹òŠ’±ÄB†òÌ·Îb±hD«ŠR¹–“Óë¼ËRÍè3R°ã@*ÓEh9ô+à]„€–\xQ0¡"F@ë(xí}�€hŠ/à€nj/�©‚½ŠØoÔ�h‚ÿt„•2h Ñ ý²£r¼þ� /Ú-``ËŠnB@K|è&@@@@€½²:)B€ €€€€¦°4 Mñ‹ŽÝ„€–L½Ï G¾" nÿŒ¹1§l" %~ÄK$åtZEÁ™6Ï–;%·�Fn϶¢(õ ïýIg¼#‚€Vö]Q’¬}]IêYïøöãäÙ�zº™tšt¯šÞ¾]®Rñƒ6wÊO´¹‹*0¬MÂ\Ò%ãAŒ)áX›»¦25ƒ€¦Œ©˜(ˆ€¦ãAj†#ДÐA6º­¢à\¬�nÝls£—g1_ØB]µÛw…ˆÿddF!Ö!Ý¡–Χ¯\vËyÂXÓ@´[§ÒÎ&eÆm_#‹÷ øoò ÜÔ M �ÊUÀ×’r/DÀ: E¶!˰ÚGS¤Î%Ýz_�è.´.BÖÐ]¤`«"$—tþãB ÖRŸ~b*ЄPª}ÔÎù1¿·ík¢€~\e©úÄ R°U<Õæ’«]E ¶û­þïçžXt€€5s¡—ðÈ��K»!` *I_Ýq@ 6‡g¿D@@@@@„}Æ{øª,CIWíª˜$‡°Ú�ê‚®AÀX~ÏRöý#‡ÓoRGºÕrµËLË÷}I½øOÑïG–²A$Ø¥`_6^é·B@°Œ€Ñ�E¢U@n˜J¿YŠ€`Wïjô;£}Ío_k|º™Li_óÛw@ú…&�)>a$ýBìHô„vÓ%ý2³}Ý}�~ÌÇÅmßé5¤ú…ØEÑ¢!s-œ&HÑP7�Åbª‚]$òÞÇŽU°‹€«³Úr÷`:@@@@€8c@ º�Z�‚ ¶*øîþ÷³*äÃÉû·êÂ÷�¤`@@@@@@@@@@@@@@@@@@ø/6ö†ñßZÚ¼m·[ÔåHÁ�àd›|"%yAIEND®B`‚ukui-biometric-auth/images/FingerVein.png0000664000175000017500000004203415167732630017413 0ustar fengfeng‰PNG  IHDR  ‹Ïg- pHYs.#.#x¥?v8(iTXtXML:com.adobe.xmp Adobe Photoshop CC 2017 (Windows) 2018-06-22T10:02:14+08:00 2018-07-02T11:02:17+08:00 2018-07-02T11:02:17+08:00 image/png 3 xmp.iid:105d8a11-238c-4346-b82a-5ee9136f7d21 xmp.did:105d8a11-238c-4346-b82a-5ee9136f7d21 xmp.did:105d8a11-238c-4346-b82a-5ee9136f7d21 created xmp.iid:105d8a11-238c-4346-b82a-5ee9136f7d21 2018-06-22T10:02:14+08:00 Adobe Photoshop CC 2017 (Windows) 1 3000000/10000 3000000/10000 2 65535 160 160 RoÊÏ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF nIDATxÚì�¿oãØ…� #I'/Ò¤™X[¥ cM·A°+m1M Ø4)k«4Vó˜Ó%@€á”©†6i‘k#Í&Èv+‡Uª•a¤—ÊTNÁK/ýôH‘")ò‘ç*,É4ýôéÜ{ßÏ£‡‡PÉzöÂ8�=u ` yë<þÃý�3gëíÖ|­`$pE�^ —^XX˜ßß8K¶6Œ  tcgú³qË€Ùý�³&€Ýsº)€IIWT×¼ûgFÛ Þ€`X‚ƒ©a´_‚ƒÞpÆ5ì.x·ØJBå:oÞ&.=¢|r˜p€Û[  T¯n†~#ùؼêœL¾ ãŒ9ççþÆñ Yà�Šã}ÕäÜK¾ S�±·£ŠžÜß8+h†ëÍRÜ%r;§)¨|aÆò¥I»oçþÆq `sá›x�ò–w¦MΫž½p&;@¼7\Àf…\ÀeB˜ü?SW)¹á¸-ÚF(ÖÀyBØš˜Ú¿&é„—ò¿�Û0Üg,€;àkMâþì…㤸ᗦWÉG‹ÿª”ÀÏ>ý䨂¥�°¯NW=¾¹¿q¦-«ìGR<õ á‡o¾­Ü�Ž u¾´£Uð�3kF;ÉU½•âÅHŸ.ìn|ÞæN[):’ t%g$€ËK€oÔ…ùwÒý¢ƒ°`.©‰¹9`ùZÅÉxßRJ$¸•öX7õÞÕ¼òØ�%T‚Ó.NðŒ9á�òÒ9Â>Q†à ŠU/Û>PŸ±D�¸.e¢-,1ïS+Þë6Ž‹îY˜èª~O¾¸°„Ð{¡<}‡p63Bè!çV‹—–ã~ª&]_G¡Ë…5ùà¥|� `�ªW�ò†ËóA]Tpàþ…‡šÛlLhÐ!œ#œ®×°é.ØTœj ‡¡7S»å‚dž4ä«ÞL.¸ðÆ$l€2°Þ3-—i�ÜŒÎH¤&Ó›.w8ïé‚j·ÌESljOæ~}l/£ü€·~€A$€u!gâtňàN ¹c„›Z®8²ÙùT*ã$ý³íðµÀ€+â~qü*î€ ¤ˆ€¿øBs�ßBºmLì^é\7Œ`âx�®‹«œðm¤xøP øPóÀ'ņn€ô!þÀïÜk®Óðw_>%€ †ÀÛ=€{ à¹máÔ¶0ÆöÎyŠ�'Ý1š§G)ïÿ€_x“ð– qÃ1C°™ðmÄ•æƒY&\gçÈG©Ý1ã47•°<õÌäïž%¸á5¾ÃVä†Ç-…Oëp¶7e�çI‘â#Cf £Ò)=芞´¾w26›çZ}ì1ò±OwŒ<¿ ¬nøJfæÐM…O4-©øxR``ûä÷qÎk¤¹á-ØQÿ˜ðiÃï^ŇrŸ�s öym[˜ø\Ú)z�°ðUP|¤]cïp©¸á¶Š94sÀf8_Åd–‹Ú¥s]´C9Ê ÛÔ cz?`!øª(>$ô^iòµ (sWú²D竤øHxÒö1ÝN8` Â2à+½ø¨*ô¶YÆõ „…‹„²‹†Þnæ€eº_Ñ⃡—ÖS|0ôÀÚŠ†^XwñÁÐK ¿”½\N÷¸C/,ä~ÿðS„{¹¬ü ûHƒ-/ñÃFE ½0wñWÀk?À2ëF?2&;°`èͯ®-ËÔ¹Û�5Ï�#\0þÀtT’?Žˆ0wñ�pšÓmÂûs‡eŠæ)><ÛÂܶ0Pr¹Ba™"€YÜïÉȇär}$ïõ…e¯­K$ àa‹O“ËE›N2,ÀÊ‹7¥¨`X&€ÕYF>– `eÅGÖßgX&€•9@dX&€{©¯ü¼.r±ayB¼ ®Ø8+º­E†°íEC@xš�YJ®––Ý6,'€å@²ÖÃ2øSÂò�éûµR]™Œàâ鎥‘ NJ�yP ÇJS4\êTKªãÆrAUt,x0œ�Â<†aŽ`À:]°´oße£Š�ß|ûäðÏ>ýä¨Å.èÉÞø¾}Z°Ñ£)Ryëâ¢$Wùù¬�»Ï37; WÒ1MÀ,ax�Š;¦)˜7 Ó àA]pvLÀ䂪"Aå‚slwL_úþÁ ¥ðPú·æ¹ß œP:gaB«ÖÏS^øN17$€åJ ºÈðÖKßDX¶&9ßO `­DXZøcû AU_#yåA$€¥ºßFÛû?&ˆ°êâÃCòfã+Y‚I `e¹Ÿ»kÆ4A$€eiªüߨHuÁ­Ó‘ ¿¤lT${ÆÜ)¯;ºk) ^D¸Wñ¡Ù¨ÈU~N�1- ŽnÓ± ˆ0­øî€-rÄÜ3¦e›ŽQâ§ÙA]4R†²Ðiœ› ÒÚàáéN C?ÀÀ¶°Ì"€‘̨q�|.ɪépTÁBgPöoy+®S6r3/Eñ®àѰ Á†B¸”Âá£4 Êœ1�"ÃoG‹�Ç0›aû4/C³ˆÏé~±°Í Ñ B:÷,”nêp‹œ—%�lŠÁÆ1QËå‚ÜʃÔ=d옦`UŠWÄïÀS1ËÍٙðdz€ `-3RŽõ¢‚)HQ�"€E)HQÙtôððÀV jÓÿMé‚‚ž¡IEND®B`‚ukui-biometric-auth/images/Face/0000775000175000017500000000000015167732630015504 5ustar fengfengukui-biometric-auth/images/Face/16.png0000664000175000017500000000743615167732630016452 0ustar fengfeng‰PNG  IHDRbb«¥åIDATxœí]MlIþjfl¯;Î*ц »²aw�¬Cl”âHÈÃ"Ááp â„!!àbnH{`Â…ç„4$ö^,-"²³ØZ­×“훵7Çq¦=�C½š~SÓ=]Óîžg?©TýSÝ]ý¾z¯^½®šˆh”ˆf‰h�“+æñ˜‚ˆæ[�“‘ë,�†Ý°Ð mlµùý»D´y¹ì›Í‰“ D4CDSz·C "šbÙ.yÏÉ“3®ëc&Ä`JÚ¸ÇÖÎw Dt­&{aã&:]±Ç D4Á²ßTDD ”R�®Øã#ÿ\§+bƒ´[7�\± `…óëJ©ÛIÖ/-t…F°“0É)ŸðíK®¸Ú�¤Ôäß)"ˆhÀeQßâMk6ùbŒÛçEn¶Wä•RǸ_j0ò‡ñŸÚüðá$l±÷0Ma£Íƒ?ÏŒ“6»Í)©É¿ÝD0 ËüØk¬íx®!c«›Èè$ËqÂÓ”4vCˈAT×�Ñ"Ò*ùš¦a҃ӦыŒ¶hcD}ÚK ”b®u(7K&v]ŽX;;JF'ˆX0ýBŒk D´àPnÊ¥—Ýäú¢K§‡¶aiCËž›´È–Îe�Þ…ü°Gû IÄ&¥ü=�dp«ñ\`°‘´w5ÅÛä´@áñÿ¡usäà‹ò›Ô!ÕùˇLXǧ‰hSìO°�°Èïà§™˜@áò¹)&}�ó-NóD4m=w–ÉÞdÌ1ñ]áQ% ò#Œ ¬ó‹_ã|KcÚ*çl:Y�±?ÊB—c—"Zõ3dDa:üÉ]ò=”kÖq9º¾Ö ©…8ª<“bH'bw˜ë2Í$Î ÒllÝ·'@~ÿ0+ŽøØEÛq'—T”¡›Ëe¸‘®4ùæ±w?ž‰Ö7!ŽM»u¸¾@-º˜DÉ�9¸l�õ„YZ9ç2øZhU.×pcps� ¹A&­³\áÝ‹E&¡CÓQƒþ¦Ð Jˆø˜¤”ºÉuh aº\꩟„Ë!dÆà&à±tJpûª·æ$µo&æ=®·X‡Îƒü‘th`ÍÑŽO™5‡ë¦É!”ÂýOhg-�Ͱ÷H iiÄeί}ãVè¢êÇ¡¿ÒµŠm¾6 +hnžòœ_ï¶/{‘ í«„�‚[i±±‚rŽ7jwزå[nvÏi„é˜k3(ÈŸj8ÂÞÌO‘rçç®_žëeÜémÑ€®À×®Þê#È(ÉÜ”°·.A¹X¾{Ôµ¬ Ólÿ·H�¦gí–Oõ!�ÞG!‡…,æ…º›Žð›�ZÄ”É[ŽcšŒÉág�ˆûÍò³6Ås—e£ ¹Ÿ1Q-KqEâShˆ¢§çp™1¥Ômü¤•ÆPï‚áŠIø&Ò˜–Ehs¸`E˜Í×÷Mê;ÊõÙVJ=ÙB=œÑö™~¬)5Ap~À_¬r ÐDlC ÁÅ 2(‰í‹J©×â×XבÛW+uh �˜réä’*¥¾JD·²à¶HX„v·C5¢Hsd†1´²ˆƒRlÁIã05Xë*t‚ˆnC ­Í6O‡Y#œÀÎÂX§ëѵD�{<êP "¶�𠂏¿ÄAþ¤�RZÏHƒˆEÎó)Ü»S¨ÅÏÒz@[ˆà�CWÎâz-rLišôD;Òšç¼7ˆ`~…wóâTÀUÒ³+&\ìbXà‹Ðõ[�Ž a‘óë$u¨~7QÀ‡ynu "âIäÿ6…= pFíbÔgšƒzSâØ„¸¯\§A1g‰ü`¥ó«V�XÐ�[ûqèEƒßoR®d¿¼ÈKЭSÚå+ö}p~‡¿¿ÕËÀßMá�5ý6Î ¢Ä÷Ì4~e#‘XWÒ„ÂÔ»A?Ì|"ÆàzuEIl¯@O`“�¨ J©�‰è ×剑ȟ,à2al†fÌ‘?_5®išáë£>>�F™%QÖ¼gˢЉ] n#ÙèèiÜ�ö%¾>j*ÎÇB«�au3E× ]�æ…#Ãή±n}ùÔÉu&añÕ'ŠDˆàé‹0éhÓKQ¶»‘æ"IÓ´ÈyÐÌ&‘"¢,-Ñ׈¨Ÿˆž ¢ANGš¤×ˆèë\î ¾¶�ˆr|ÏWX#¤g×QÚ>ÜúÒuÀg‰(=ÊÏrn’ð€/¸Éû&Ðì3ï€MC¼O"U¼`À7¡GÊß°CD¥T5‘mm%‚ˆ´° ·9ýÉñ[îC ×&ã}/8_ø’ŸP†ú1óhh w|…Ïýš´aU"Úç²çûJ©Ôá-u"ˆ( -\“rÐ/ømè˜ÍüÀ�ák…tÀ|nž�Ëd`H©øt‹?†zM0iÀÏŒ¸à`øœ!¡¶ÍäxФ¤¢1©AD¾w¾ðíü€Ÿ@ â~à�h$ãcÏÀ׈ "Ì68=!Á&â(ßkÀ÷¸üo9F ¼]Ë™” &%Q"ØÖ÷A Òä9„“r Z?„nõÿp À§ 5á h[þ4܉8àOž0àËÎØ�&þW\vÀ_áNBEì{Фx*J©ýøR«�A`r›Œ rL~ Zp¦cý;€5h“õOññøP¤ "ž…6y€Ö€Û|Ý?|àç|Ïè>ê]4 ^¦á‹T±÷•R^‹¢kx�X!@³·¥fHR†¼ Ýr­!¡MÓ€8 í9�àT÷Ðfì €�à÷ àeßå2¿„î ƒHÓ™ä±Gð iYCb™&Ñô#œ›©6) Úd¼ íª~ÀÛð;ìeè~ä5øžÐh¢.Ào¡C¨wYÍ¢ÈE[|>Œ© Fè}œ›w©ð¶ß©ÈQšgo«e",-0Dô‹ Êí R²6_†8mZÌøâ=h·ôYhOÇ`ÆfZä0Çý\æß;ˆ„ Ößgíç87Â7DØã ,=rÕŽ–ˆ`úá ÛaR!’8ÛdhaÍËø—µ;m9žø7´€¥ÇdÜÒ÷¹ÌsÐÚÕHì–/S~ƒ°]oÅdDöÎDX$HÁ‘"MVØv�¦œæÇÝG½Fw·ÀâÅmÓ4j‚éðùã|ï0á7kùµÖŽÆ@˜GÒsk›’áD„ A Î&!h?Jkd:-äÿA›¦ w×D3"$ Æ ¼M¬º!A¶|ó¹-[;ì¹™:X"$jf¦"‰³†lÉAûQ…iÍsüÈ÷à4±[¤-9‚–$ìC»­G¡Ç%wÜò+âÞ4¶òfž¦=Š7ÏÏÁ'#pè¢24‘ Ø· 2=.×µ­A„‘!…F‚IA1  êd›išÜ–ñ+ó,Â1ûYøÚ™áí(  2Æ&rn¶ľÙîØ–&,hÛ|¸{ûöíí´û­Ô‰XZZgWØ —Ë}X.—ï·Ûî&‰µµµ!ÏóŽg2™aû=“0±‰iÄêêê„é|=ÏÛUJ=ÈårÛããã÷ãV®[!µÞó¼“pîܹ¹§‘í'¤R¹N»~�@±XÌ.-- ô>5ù“�Çgn—€Ä☠çO¿õ òœ/fà¯EvþyŸO�ŒÌWäZ¢ÿgúÄÕ/œ5 âà<õàïdô ¨qÉpÁ.0GñÑ[ë�„%ÔV¼d˜Âÿ‚& ‡%f(üÿµ›¡aÉðÿç�êCÁ±6IEND®B`‚ukui-biometric-auth/images/Face/03.png0000664000175000017500000000622415167732630016440 0ustar fengfeng‰PNG  IHDRbb«¥ [IDATxœí]ÝnÇþÎì’2EÊv Ä† r¬V²DÖrá º‰¡W¼)Šø¶wé$}‚è8¹Ý›ä\  ªL„K×B˜H°áÀ†ËZQÉåœ^pÇ-—&%ïpW‰>`0³»äüœoçïÌœY‚fžð§ÀÀ=Œ‡oü€ 8ë=¾òEÖ}¡=#íiNA…Y/Žæz�/µkø*ìk×Êuß�pÝÀÿ'€?�)§‡�ÿ=€ï‰h+\0ó—¾3Â0vÌ£/h[óÃa夈Px\2Ž”‡DèþqIðC~7ÂW$tüÀõÈ ¾"¢¿¿+3 à‹àáCߨ$¢Eý›™•°²8*üaaå[$F¯ã�AÁ50X3€ÃZ #ÂJðJøÃHÐk‚z¸&„ pD¤×P0ógn¸�ÃÖæDô7 > nÞ'¢o$42]¸Šˆ,…­‡£H±Ý|— Ò®�dGIP×ã�õö‡ï‡�zÞ Âí~‡ˆzCäø9ú/<ܳÑg¾“„,…­ˆPn!:qá&K'B…�K†ŽqH§èùéyðµ¼é®«åÉB¨ eæùaYѷ̬úãûÄÌ?£_]îQuLtÁG‘¢7YÃÂÃjJTÿ1ŠŒ#YƒÝ ÿ}o~'"ÜÕÂz­8ò<Š f^ðÀ&13… EB˜�„¨ëQµ&ìÂ}Hx„5ŒŒ#Ù“„¨æ'ª©‰jvÂÂ×ï ûMd3¥äo¾öCõFêÍGxT¤_�"hT­ù(pç7 �Á0lÔäð‚¿ÐÄ` èiªf§‹Á¦FáaéFŠ ƒ5Ri033ɨ?Ž$GÛìp‡ª;ýÍ>.A·\ð €+cäi> ü[¼ð ÀÛ|½†E �¢æ(G®ä¢_[8¬�"à]Ó„ÃŽFï-ô…5¥ù*¾Ÿ‰xžyOxÀüý7_¡n7Èô[íU¾ôQ“.4ÄÍÎáðeÛð?Œrb°ê q]í ÜÖ®õ{í^ý—¢�£úa"òÍœ \!ðs�;§ùSAX‘p.D’NTV‹w%¸ß°ª‡ÃÑGXøa÷¾&CŸi«ò‰ ÜÆðá«Þt…IQ‚íh×-MÈ*¼„Ðo[Ú½fPNWýÉð"²¡‚êÍOxn ‡ß§ºp½^/ à/Ìœ'¢ÿZ–õD^XÐa�‡]˜€(¨ò}êûþˆˆ‰èßBˆ—œì…'}ïS�øˆ}EuþzÇßÅsp„ˆ÷�šâÄ?ü°ÄÌÓBwwwcmm­5‰t`}}}6—ËÝH"íaPòO†Œ¢Z­^KŠX]]ÝnµZ›RJûüùó ŽãX£ÿ5LŒ×u DtšÍæó¤ÞÆÕÕÕmf~&¥´—––RCÆÄˆèv»W Óé쬮®nO*Ý(¬¬¬¼bæ63O—J¥KIæEa"D¸®[BÌ@.—{6‰4G!“Él€”òR¥RÉ%�`ÁÊZ­Öe°mûu±Xì˜Lk\,//ÿ"¥ô¤”v>ŸŸO°‰Ú°#ˆèS"úÈdJÙlö"ììì¼2™Îq±±±ÑBøD4µ¸¸¸T­V¯Õëõ+“¬!JþƇ¬•J%W(–…~©TªÝM •J%wþüù)åHuO>Ÿÿq~~þ­‰|ï#òùü ì™Në$X[[kÕëõZ>ŸÿѶíÌü’ˆö£~»··wÒ%Ñ‘Gé÷Aèv»3Ùl™LÆ3�ÖIQ.—{èë´"ßöjµz�ˆ.›,ƒñqîܹ4›ÍÔ1 –eÍ3v%¢Z­^’RÚD´ŸuÂI¡ú�b±h¬y5FD¥RÉÑuB4L¥cëëë³0¬ßˆ ƈ˜žž¾¶m¿HËÜá¸pÇÊçó×À²,£s-#D¨™´¯Õj©š;7oÞ¼!¥´™¹mºFˆPz%!Ä«`Dr*¡vL—#v"\×Í*½’ÉQÆ$ „xôGM¦U ±áûþE ¯e=­}ƒB­V{%„ð¥”ö¼ɴb'‚™/Hõn\”ËåÞîîî†ÂB̸®[ý¯“!v"T³tš'p:ÖÖÖZª‰RZd06|=͸0T_§uÞ±c¢kÖ§ª¯GC{Rœ‘œ‘œ‘œ‘œ‘œ‘˜˜Ðù@="B£Ñ¸ÌÜ6•FìD¨MjÓÀ¯ívûb4¶&;JÇÔív5D¨²Ø¶}:ˆh4„³€YuÀ¤¡^.f6¶#06"Ö××g›Íæï˜y|ßÿÕèš–——·lÛ~mRjm×¶í×·oß~tçÎ��¸âNjµÚs“êðXˆpÇR ±Z­ö<Ž8Ó†r¹ÜSêp"š�;þXˆ(‹9�Rz§y�z˜Ù€^¯7wÜgºc@m0Sý`œ8#"%ˆ…ˆ·oßöÀ²¬TØ£�FÄB„Zeæé´š€É²ÅÖ4I)=˜››»8ê·§wïÞ-‡e�±Ñn·Õû•_k­ð<ï2Q쪎؈X]]Ý&¢}"šZXXHÒ8Ðôý¼&tN±Žš<ÏÛ$¢}!ÄL©TºgÜI¢R©ä˜yz½Þ¶‰Œ±3:Žc----0ó´mÛ¯———·Fÿ+�p]7KDW|ßÿè«oL•LjU©ëºY)å<3O3s»P(<3e�'Ô¡)QϘùåÊÊŠ1õ�1ó^Çq¬………yµSÁ¶í×µZíyÚT!ŽãX·nݺ¾ßétvr¹ÜK“f[€A"�Æ…7oÞ|¬ŒÞ�¾Ñòòò/¦Ó>”åhRöà9£I¡^¯_ñ}ÿª¯×ëµ´Ô ×u ½^o˜ùÙÊÊÊÄ­œ&ªkÒí Òr*Œ>"êt:;I�L˜]§/¥¼”ô\ÃqKÿ@Dû?ýôÓfRy™¸ö5-µB ³•±â“'O6’l*'NDZjÅâââ¬:Ö®Ùl6’î¯Y�ÐkEǹ9ŽcY–uè,¦Á¨&"tÛ4fž¾yóæ�I¦¿¸¸xEJi§É|¢Ã×0’6¦a¨…D—J‹ÅâžmÛ/À²,ã'‡9Žc©¡ª”ÒK @ Ö¬õþ¢P(,×ëõ8i€>JBø™LfÓD:'EâD”Ëå^½^¯©U/ß÷¯šè¼õQÒîîîFÚŒñí#Âxüøñ‚bƲ¬§q+Ù”z%�z. 5"d“Î@RI„Úž'Ô.½´š ¤ŠÛ¶s€™S \×mMÅwH ÁªžmêÈ6]…aòp““"5DìííÍfö )(8ß÷cß»ú¡H SSS³Ðl6�¶¥Yþ¤n\*ˆP{†¤”žIœçy{@ÿ(#×uS5zJœÇq,ß÷o@&“ya2­­­­e~lÂØäC ˜ù3?H*¥RéM1³ñ�år¹×ëõ¶ Ûí¦‚%�þGcï'‘‰jµzÍ÷ý�‰hÿéÓ§™í>}úôµ5Ô”^똸�ࣱýê–‚¾£ƒˆžLR÷ãºn–™—¤”vÒ*�D¾ºôû„z½>§HHBW,;¹\nè+ëõú\Ò&Z#�Æ…V«uC©¢“þœ¾Å2X»~>éQ½“ÿ$ˆh4<Ï»¬¶_Ѿçy›iX+v]· ¥¼® ‰h_Jé´¶¶¶ŒŸ€lœˆJ¥’Ëçó³–eÍ*ìÀ`üUÚÔÐŽãX¥Ré’ïûWÃϘ¹�Éd¼©©©�G�íÅMLìDT*•œeYÓ333…n·;£+ׂÂl×jµTŸî8Žu÷îÝB»ÝžîõzÃf¼Bß÷ýV6›õ˜9;‰XˆÐ·ßG=·mûµçy{IðCàºnÁ÷ý‹Bˆ™p9ãhbc«µZmEu¾¾ï·ˆhß¶íÓ“³$ ×ze¼rûöíG绯's€É\ÒC¿$à8ŽÇ®“wòçC\ˆ#ƒgÌ|A _xÜ¿—\–~³¸ø€ÇÁÅÉäå7 %óÇ`æ9­yú<Ñlý†ÀÌŸkrŸS7¿Ôn>x÷à ±#xñhòþ2üƒ¯ùäHl=#i„„z\|=,ÒϘù»DøfÂåO ˜ùçÈë;fþL�çÿTÛÔ§SmIEND®B`‚ukui-biometric-auth/images/Face/07.png0000664000175000017500000000731215167732630016443 0ustar fengfeng‰PNG  IHDRbb«¥‘IDATxœí�]ŒÙUÇ·ªzfz>l¯lìµãÝqv’ñzfäpÀ°lX£) ¡! (Y$@¼ ‚"„"!!$´ðÀâÁû€�(›  a/I&qÀ¬mºÛØaÖvö+ql<žž¯ž®®ÃýwúN¹mÏxªºj×ó—J·ªºê~œÿ=çž{êV8‘ayQDN›m£8Å# 9µ 9Y¹¾("Ã÷Êðä&2Lâv—Û_ˆÈÕ-Èíd2³—œO‹È§D乜Úöž…ˆ�x`ÒÏ¢{÷ÛèöZ0¯ÿNÛD} ÝcUbK¶Cë¼lŽ÷? ü4ðAàU³ý"ðKÀ€¿F“ñ <üÐ$eRR ú‰H”ÐB¶éGÌÏg�Ú$<ü$ºg¾Š6OWi ZÀSèÞi�DÄ·€OÿhŽ—€¾ì>ü.0|8‡ÖÂ)4)À1t§IâO�/£µ#‘h*¥Z›“ÔÝH…‡›ºd,Ò&È’à’ñºÁC¬÷¦¬ð]Bì :@›KBìÇh/é Úšj…%Ò&ðó&ß6mhš66�kü­hÈCáŒ=Ü›ˆºí@›‹·€²9ÿ´7ômÚäøt&c Ýc]Ó䛪$5´°_޳t&!F{+?DgšÎqÝ ªNš¦Ž‘SwKHMȆ½­M‘ÐK„uGÝý1à÷Ìmä4Àš¬ÿÃzmèDÆ AgÓd�×U=è@›§~®¸s ['ý¼gu#cdž‰H�à ¾)?|?ºg~É4 iÊ£'sIMqÓÇѽÚ:‘±®ªèqgÄÜ׉›ÞBìÿÇÝ¿�6]ßCÏ1z¹»ç'ërW�D„‘±!"Ü1 I‚{ü«æÖ/šö²ž¼aô˜ÑÇz�ò�2t�lÑÙ›JÚkÕ5y”ÑZt/šh‡á z’™´ùmö5s�%¢S˜¥“ÓàˆPä~fê�D8³k>\a%�Ÿlˆû«tÖš½è™o'Mqó{Ýk“^•Û#“ô˜ò}h�H’`{~Ú}~œõ&ÇCk²|íÙ= |ÞÔù~“`Il¶´Éè8 ܈F¸6;9 º› �7|ÝãJè�{ºç=‰ž%ÝÃ:�5îæ¡Ç«1I2\­pç  ‰èdûgÿ}è±ä ´<üz>2cêÚ¼ˆŽa¹åĬ¸­Ÿ{ìÓ§<Ú�Èu@‡œ¹ÛÆÙÆö�ÙÔî'Ï—Lúa“÷[h�§Ç¤'Ð1#‹÷£Cw{aöx¿¹f�sÎ%#©®p–Ñ&p!A‚Ýo™¼€_6y| =áëGkJ�z=¦}í¯šßf¿á»çV�s `ED¬'P”R±2DtšŒ•Ð*Û‡6 }h»[vöûŒðËIŸ1Bù‚i¤KT:°÷¸F�hˆ�xâ”kèqï:Û뤩 qOdòZB›—°¦©[„îÃèùÏ×�:/;B¶ûKfí4,;ç�L,IkdZÓÔrRÛhßd MLrÆìöÐ5³EÑG‚ 8ÅÝ®žÝ>‰3Ø�Ü9E;$o{,¦N®“Âßhðò<ÚC²¦BÐÞ• ç4ÉIŸusKQýšRªéûþß±~¼q÷]­k:û«Î¹†“oË©Gº¸xñⱋ/K=㜑u»’“¡mä„m" ‚m" ‚m" ‚m" ‚m" ‚Ô‰ð¥TꡎԈ8~üø-¥Ô’Rªwtt4³P@^¨V«ƒžç yžesJÕkª×ë×”RKžç MLLtzóó]‰™™™²ˆŒ´Z­[ããã«i—‘úËŒaúGŽ‘þ nŽ��î?’6ŠjµÚ£”ÚEÑÐ᛬ړÉ[¥Õjµ'Žãó�ÁÁÁ7FFF õ?I�pöìÙÝårùP§ßD仓““™…o2{Ï: CtttÄó¼uÏ%‚ ¸Y©TÞ,Z($ Cÿé§ŸžJž_]]�+—Ëßµ³ê¬�ù ï³³³;oß¾½§§§gÍ­ ‚àí±±±w².{3¸páÂA¥Ô>Ï󢉉‰ Ý.¿«W«ÕöGQtÀó¼¨V«UŠ¢Õju°Õj‘7&''ot»]�5U*•žçEq{»Yö½àzD«««sy�]&Â�éÇq¼7ï¹F†þŽ;Fã8”RK¯¿þúµ¼êÒõèkQ´ÂºÙq"Ò¸téÒ•|x·ˆô{ž-..Îæ=^åò<ÂÕŠ#GŽŒv›Œ0 }ß÷÷xžwÃF�óD.DLOO·æçç¯xž‰HÿSO=u¨›å>|xÇ�çyQ¥RÉepN"×?fÏÃm,‚«Ú ¹>*_‚àmß÷÷g½^6 Cߺªq׋Bà™µ;^ ŽÕjµýY”ãzIžçE¥RéZå<,r'bzzºU«Õ*ö©WE²¼]/i~~þJ¡ì­ Pï8þü¨çyC¾ï_N;ÈfÃ+EŒsA4"ôä]�N($vyNš°«ôŠúº@¡ˆ‚  íå9i¢Z­.(¥zÓÎ; †óT/PJ-e‘¿ÂÈb5÷VQ"† ›5Cö¸(ŠR_»ºU†ˆÞÞÞÝ‹‹‹·²*Ãyó§p‹à A„]3Çq=Ë\½^_0/›Ê{Ê�ˆ0 ý(Š”J¥·³,ëúõësöõã,^6Ù <ÑŸƒÉí;¥•R½"’ùJ‰éééV«ÕºÐl6 A„•¿¼`¶®ãÂ… £(Ú£”Zº|ùrWf»—/_~Ç. Í*®µI¼¼�ÛÝJ©KÝŒýT«Õ9Çq�wÈÃÊ¿ëcD†~­V¶$ä€_-—Ë×@kµÚpÞ ºª³³³;———ÙPôüüü•<SºK,ͳë7�?ž™ûÜ kòï³³³;ëõú>»üR)µT¯×¯áYqµZŒãø û‚¢Rj)ŽãúÊÊÊòõë×ç²^T�9333å���ݾïï¶ï`›Æo- †¡?11±7Š¢ÉßD¤Q*•ê½½½sçÎ�[H›˜Ô‰˜™™)û¾ß?444Øl6‡ÜàšiÌ­J¥r#ïe+÷C†þ±cÇ�F«ÕÚ•|�×ó¼(Š¢åžžžºˆ¤òžD*D¸Ëï;ýÁÍz½¾Ðm»›&ªÕê`E»<ÏJ¶3 ›šFT*•I;øFQ´¬”Z ‚`.ëÉYpµÞ¾¼rôèÑs[ÉÓÊËŸÈœ™™)çíúå�0 ý4V�¬É_ÚÈýK¶�DÛ[Ä|âŒ9"¿*=²8aÒ3ú�Ë¡ý=ÑmtVæç‘aÇ0|—Î$4�7€þøWà+h2¶$ˆD¤ 4H˜”D‰‘( icKÈŸš¯ý'ð DK ¶"ã€wXOB'">Λïu"Áš¨ï_N¯ßdkÎu„&%J©æî¥¦‘6n'ãóhaü#-¬Æ<ˆ xø€­‰°ÑN„K‚«_¦€ÿ®›ûnØ |'4L\p‰v'AÝèÀáÝüxÜ{6ýŠùÉ ms-’þøZÄX2JèùÅIàçÍïŸMhÇ÷�ôËæúà6’£Ç‘I` øKàk¦n›i‚7LýÝ{þ.5äp8PJ}z?Ö�=lN„›þUóÓC“`IúEà- 9ü Ú«z-ÌšôE`ímÍ›ü\Ͱíh˜|ŽÏ˜{e´i»Š&aÝù¾ü-ððOhÍX¦�ÐÖóMlÛÔ0鈖³a i  ÙÒÛ²òß±§Ô¦–ˆ§‚n:@÷èoš~‰–É*¿ü$ðcఌڻÀ5Zò×è^ÛiNÑކϣ{¾°£èÞ?„v—ß~ íÅ= ü!ºƒl…?C›´†,Yk&½æÜ_Û®vìhŒ0$ôж%†N„ü¬ùy(ÒÒ†ƒæ³A´`¾�6#¶w  ýi´íw÷N<‹OЦÌ�°UL%à ðpø,zløº)gè>ütüð–SG«îÈõö”ˆ¬mgìØ6m$¸‚ïDŠk²~Æd1c_@Ï!žGkÀß µÅG÷Êv�ëShsd‰éD†‹U´–¤mÖŒî¥oß~ø]´¹¼ Ô€ÿcý8`ÃГÏ2š¨N“ÎöàÊŽ­ÈØ ®Ýo'¡Óu€¶Ç mn¯¹ X~m÷‹¬÷´Ü9Ⱥg[":‘±®º¦Œ6’à³Àô8ÔÇF›ïN4/˜¼ÿË´¡Ó2‹›nôzÒÌÔ–D8³í¡î@ÜéÚ%áô¤í}àcÓˆpnÑ"§Ó@GÑÚäNþÜÙ.î¢5éI°6ýÇÀº4Øhj<“V´Æ�˜ºn*®¶`;A@‹ŒŽ“Àíh„­ ÛKÝëvB¬ŸE»‘ í»Æüp“õDt %Ówî±™VXD蹇@ÛýÿXB{c25 µ´+\h+'f½ÀmýÜkŸ–‰ôh-D®C÷{}{el¦½hÛnãFp½NÚÚ~÷ÞWLo¡ä§Y?Æ ¡—FÙ\to|Ú¹î¤6Xõ¡{z?ë'híš±Œ¼ëlFh/šv|‚Öâ5'¬:Á^¯tˆmX‘6N›V#\ÛìÆVð%M8àĽ&ÝëqÜx m’>ÃúA¼€öÝ?4$µk—íI=¦¢GYßI: Ö�ìu?Í„;€Ðæi‰�ZÓ@›·¢â=´+î’°ìaÓK&½‚—�{‹hÇÄ×0éØa{J»[Ø>8vº·Ám[YYùmàG¾ï¯P(¼å|ÏÆO 'rÿCg�à ò'Г²·Ù(ðÍ�£;Ãçž»$nÓO˜ïÖh™ knduuõ |ßÛ´£“9Ú,4;¤›Nú~^J©8ñ¥ïJ¥ÒÓl6? àûþ;ãããkI—Ñ-T«Õ¡(ŠŽzžU«ÕòÔÔÔC/îm†NW QX[[›{”I(—Ë·<Ï‹â8FGGGÒ,+q"Dä0@¡P¨'�w·155ÕœŸŸ¿îy^äyÞ@¥R)¥UVâDxž7°¸¸øÈpîܹeÏón,//I«œÄ‰°8wîÜrZyw"ràÀ��ŽF<ްc]ÇÛ™ï ûDäûDäûDäûDäûDäûDäiLè"€ééébÒyg…Z­v@DVÓ*#q"VVVúûû’Î;+¬®®Ú}_si•‘8v�©Ñh<6DضAðhQ«Õyž7é.t¶s‰ÈH†~e$FÄ¥K—Ÿ‘>€(Š›µ¦±±±Ù n§¹žýýýÇ‚ ¸}êԩ˧OŸ¾žTÞy@¹\¾™ærx"D„aèÛ±r¹|3‰<󆩩©¦]WJuÚýPH„ˆñññ"@Çõ4'f ©4›Ííì“Ýö't;Àøøø€“Ä>9A"DÜ»w¯ àû~*®Ý^@"DØÇ¢"Ò—–Ÿ�¤Ù¶ÄLSÇu€ááá]{pæÌ™´Úš$#buuÕ>`z\µ¢^¯PJ%¾Ô‘gÏž½£”ZRJõŽŽŽ¦¶�*•JÉó¼Ïó¢4Öœõšêõú ¥Ô’çyÇ’Ì;KLOOEd ÙlÞIccâ{_Ã0ôOž<9*"}AÜËÝ;’¶‹J¥Ò£”Š¢èIÐË7iµ'•÷oT*•ž8ŽGÌëzVK¥Ò###¹zOR'\ºti°X,ïô™ˆ|<99™ÚòMjo¤ Ãб[0-‚ ¸].—oæm)$ Cÿ¹çž;Ý~mmm®X,~lgÕi!õWÕjµCwïÞ}²§§ç¾[Á‡ccc¥]öNpõêÕcJ©#žçEW»]~WßäÕÍó;A¥R)5›Í"òÁäää­nס«kMîyƒ‰‰‰§ºYöfp=¢µµµ¹,H€.á®éÇqüTÖs�0 ýƒŽÆq(¥–Þ}÷ÝYե뫯yÑ ëfÇqˆÈêµk×®gi*»ND^´âĉƒ"Òçy^´¸¸XËz¼Êäy„«'Oží6aú¾ïxžw+‡j2!Â=›&"}Ï<óÌñn–âĉ¡8ŽÏó¢r¹œÉàÜŽL_D›…Û˜Wµ2}T:>>¾Á‡¾ï¥½_6 Cߺªq×óBäà™µ;^”J¥±jµ:”F9®—äy^T(n¤QÎn‘9SSSÍjµZ¶O½¢(:šÆàízIóóó×óv?7/+¸råʨçy¾ïÏ$½Èf—Wò¸Î9Ј ð _e†\a·ç$ »K/¯ÇrEDEHç­•Je@)Õ›tÞI 7D˜§z�Rj)�üÝ%Œ4_n²[䆈………HgÏ�…=EQâ{W¹!¢··w`qqñNZe8'r· .DØ=Cq×Ó\€«×ë  _eT©Trå=eND†~EÇ …‡i–5;;;g�§qØäaà‰þ¯ÒÌþ§tbbâ˜RªWDRß)155Õl6›w�F.ˆ°ò÷Ð/É}9‹J\½zõXEO*¥–fffº2Û�™™ùÈn Mk]k‡xx9³?twt(¥®usí§R©ôˆÈÉ8Žƒ¬—<¬ü»>F„aèW«ÕaKB pãããkÅbñèEÆjµ:œõF†®jD­V;´¼¼|Ü.EÏÏÏ_Ïò1¥»ÅÒ<»¾yöìÙÔÜçNèêÖjµCõzýˆÝ~©”Zª×ë7òð¬¸R©”â8þ”= ¨”ZŠã¸¾²²²<;;;—ö¦‚Ô‰˜žž.ö÷÷ú¾?hÏ`›ã·ò¶ †¡?11ñTEGÛ?‘ÕB¡Pïíí�»|ùòBÒÄ$NÄôôtÑ÷ý¾���R£Ñp×Lcî”Ëå[Yo[yÂ0ôÏœ9SZ]]ík6›‡Û�ñzžEQ´ÜÓÓS‘DÎI$B„»ý¾ÓçAÜ®×ë ݶ»I¢R©”¢(:ìyÞ@{;“0±‰iD¹\ž´ƒoEËJ©¥ æÒžœeWëíá•S§N]~˜<­üúÿ¬§§§‹Y»~Y C?‰]'÷å/-J¢‚ûØ>DÿÁºˆùK›7Íý ÙUiÏ₉ßôhýëÈײ©Ëž†•ùDdØ1O/eZ­=yÉ‘û°½ùªsóâýö‘8LÇ¿èÈûÕö/¼&»GfÏ3²F›PwŠ×6Ëô¼ˆ¼¾‹ ïv¹ý¹�ˆ¼· y½."çÝ|þ³–[/•vk¿IEND®B`‚ukui-biometric-auth/images/Face/12.png0000664000175000017500000000766115167732630016446 0ustar fengfeng‰PNG  IHDRbb«¥xIDATxœí�MlGvÇÕ=Cz$R�cG–bdDŒD®©À ;qˆ$r(äÀ[`mÉ%€¼·|ä‚$Àò!H�Kä �æ"XØBY0ë$†$€3^y#“Ê:öZ±BŠC‘"ÙÓ/‡zÅ.6g8=äÌôÈÚ?Pèïª×ï_ïÕ«×=ÓàADN‹È™Ñ’×yJ!"×ÛГÓë9ݬ«mT˜ÆR�ï¿o " ÐÛÕte×¼ƒ3"ò†ˆ\ÌéÞ¾´‘‹ªÛOß×üƒoä,ëS%Äá¢ïãžZ?ŸD䯶î=7‘·`ODdBu¿`DDŒ1&oÁžF8ýò$ ±aÝHƒ’ËÀ-]¾kŒ¹×Iùº…¾° .h™ìpõ‹À;À;ýHʶþó"BDŽo—ØÙã]ovËÙ}T?é-Ýú-`Òópõu Nÿ¸ø©Ç�õ‚„%�¦¤Ùlóàí¹yÒB¿%Ûúï5JÂMmö†ZF/Úud,õyqs? Q‹Ù“4 ›žãM¢ú†Œ\ˆ8H¯ÔköL»ˆ�œî™H‘Ñkl!Oo‰�¤Rܵλ".wÓú®½*"3λ˜å<=wAå¹Úúìî¡§D¤¬¡íÈH]ZËž®çfºIÒþ¹Ž> Òåç â'·vk˜l]]T…-h™‘æùÿÏê®I†pØ;ArrQ½Ð¿ß˜ÃDjÿ”ˆ,xÛªD§ìIø)%¦¡rõØE%}F—KZ®‹ÈTªÝ+Jö’GÆ5%¾/"ªŽB’ ã.ÖõÆoèrÉSÆTê¼Ì®SyÕÛ>­J÷ç.oˆÈMO>GF+L5o¹Ï!I„r#µßŸ]ßhÖ ¥�¸ÕùJŠ#]DÃa•eJI¼æ‘–ÆB£zŸH2>\ñö]Õ}KÒÚ�g I½ó�J Ÿ«ç̨ -CiIÜã“ûðÌë}Þ¾ Ñg·®¿*m†˜"�›sè¹;,艃ç–n69–eò5Ó®²\£�!ëœC²�{ݪX-àmݼÔà” ØÔt+Œ`Ÿ)´ƒEZ:…nYÄ[º|»Ñ1í…YLýö)]»XÖk[á{»§I]¾ÛoOöZBl¬îÐlÜN�ÝWR.£Å�NØ~ÏO…ÙOœE¸�yû I^5<ªÑÌ›tyðË•oRåráô²×�Þ&±®'kŒ�d¢äOà.zþÖG–¤Ü¾b÷Vת5L©ÿ_;›¾’îù²3òäÌ#<%7KY\÷ÌÝ „7Ô lgL•¼›ûqMÎåh[G½ú®h[ ^»7ýNÓ¤>ç¢Ú~–’…F¤õë9zΈ1æž*þBªŒ°3u."+.�¸HçZf±îp¸å¹Í«*ïŸì!ïi•gÙs¼ 92£çoú©¥l+B—÷€L�7ƒ%b«„,Q�â·~ÉóÞþ%¶2jÿjG†¶�Ç+—™BRcÌ×EDöÛUqËH˜Å†ÛM-¢èæÌºFh?e±,ÒÅÜi|™‰h5Yë+äAD¿a‘öÞ6ï ¾Ì‘ ,Œä-Gß!ÙóQ_ tƒˆeØVäA°ß„_Ç!ÉK‹Ýj£DÌêr² uç…íüY·è šrh×B ö‡4)ŠÈ€ˆ<#"%-‡ö*À è5ZGADBÙžõ«\³šSšû¢@:Óêî¥kDttB§&|Y7'½C“À›"2¢Û—DdÙs[Dl‡€Ð[?¬ÛGPR´¸ÎÓ*=ã®Ä+±UêZ÷,Ö n§?Ô5«÷õ®ˆŒtãÙDLjû¤ëo×ö c¾ |[D.`óF—€Ë"r øðOÀ¿2Ο§€U"`'!Íð<°üð},ç´¼ŒiqJýo•«Ä"2 ×Ô�1ßЙúe¬U|=“RÚ@Ç’~bß%:†ýÑà7¼ý!V¹®ü1V‰ßÂFP_^Ç*å€O€¿ªUü ð÷ì$Á'Å¿ÿaз°ÖPî_Ózü;PÅ? |ø%lÎ+"”oý0ðC½ÇɃæ¯ÒèˆE¨Oué„7ÕÝ´„©å–ˆa` ˜ÃöØ‚îÿ9àE"¾ü¾×\–Îócï¼ÿþø&V¡Î=9×ô‰ž·¬25"Á-ÿøCàwDä_�1qY2¡S®É¥Þ6�C@‘Dù>)ÿ‹u C$n¨à-?>þ øuà€u=nÈnw€ßþRëÂ#H”ýSÚf+¶€ÿк8$"°eŒ©·©¯]è¡. DBB£ål/?LBNšŒøxL2àºA<+«À†ÖÑŒ„:ð3À}•§ž*[$dDÀm­û«zŸPô‰ÚÒš‡!"¬ruWHB„³½€u§H,Â)Þ_/`­Ê'Á Ð>°“ñ–Ïb­s/ê^;Cì´ßü¥Ã¡Ô±ð ²/"¼1`«èu=t xF÷9üe¬?­7’C|2þ;^ø.Ìà,0m�„©g°=ý»Ip®'ƺÕj;iåGº©ü~�/©¬‘'»#d KHæ×4Û&³Ÿˆ�õðylظÎNÒdÜNck,I“‰E¤É0Þö± vVêˆhDB¤÷ X×”îý[*ŸÛvu‚íp! éyP("›Y­£-"”„->ElHø*6nÿ®wŽO„Û÷m°“·î¶açøÐŒ ®÷z×§IðÇ�QàŸ±yÅ'Áõü¯i�7IˆØòd I¹P%£åØ‘™ˆ N¹>)ßÁñ{Àbý³O–¿¾ œÄF+>éå'؉ÝçìMÆQµœ$q9iüå ¬§}~A—®cDÀoißGS( dÙ%“ˆÐŠŒLDx$ø.&mß~øYàO�?ÃöxŸ8w]xY—þ±ÐkùªI„ÕŒŒâj)‘ öÍÂÑÛ³7Ùíó];n}-=†±4ŽÜœ )Šìå¦Zá ̾ûHGEnû/°ž àw�¿¡±+û àl ÿì&Ù­XE5аüÞè+À•ÛËýù�ïv°‘Õ7㻚@× 6Üþ¦¶ñvlh¤®Tq–X !£á$0‹Eø>;= ú¥ˆÍ×üðçÀ¯èþë$$8BÜ›#À/bgÂÙiE½áØ=–4³ §7kޱ֔öý%à%좆%ÂO>º:�ë}¼ªõÛqŠì ‰�Â�|þvH,º¾ ¶óA�ÒE²¤K·>èm»õoýy`ë¿Àšò£XßÿP…;‚MÐ-©Òë*ó*G�Ý–°×L% F2P;’´½M’™þX’žÁ†Ì�p˜Ñë6tùX×ý²®ûý¥+kZÒcËÑ,îwÊòH(±“œA�Ÿ”al¾èùÔ ýk9gT1÷µ½!à(IïÜÔuTØMš“�ýuÚWû3æKÈ’Aú»ñÀ�TÎM¯8¥o¤Ö×HHxDBÀºn»ÿ¦¶»lvý_Ë677_ÝØØÙÚÚÚ~ÇhmmmöÔ©SÀ1ý Õh±Ñ«0·š= Ð<ÍÞcZLÿêȵᲨ‹‹‹çŽ9òËÆ˜èøñã›íî:‡žþ}\µZ=EÑ ADÕju~zzúÀɲN R© ÕëõQùÑÄÄÄý^ËÐÓ·8æççïAÅq\®—m7ÃÜÜ\ID^ØÜÜ\΃è1ÓÓÓõ îÄqü\¹\[]ÓM”ËåðÈ‘#gã8.cÖ>þøãżdéù{Mýbår9—Á9�\ÿ˜=�°±BÕFÈõµü±±±ÕB¡ð)@†'çææJÝl¯\.‡.T�ã¸Ö/$@ü>Â/†††ÎW«Õ“ÝhÇ�’‚ ˆŠÅâb7ÚÙ/r'bzzº^­Vçã8®DQôB7o?JZYYùhlll³Óm}õñŽ[·n� ‚`8 Ã;ccc«�¬Û¥W …§çÏŸÿ¬“uw¹[Dhô@'wô%>ìøäJDj[[[Ã�®»è+" …B  ¬J¥²`Œlunè"*•Ê€K¾u£~?…Q©T†ºÑÆAÐ7D¬®®ƒ�ï»Õ†ˆlDQt¨[mì}CÄààà €G�=èVÅb± ?�é+ô•Je(‚á8ŽkÝLÀÕjµU€ †+•J_EO¹Q.—Ã(ŠFŠÅâ§ÝlëÞ½{ËADƘÝl«]úçR¹ýÕòøøø‹Æ˜Aù¼Ó“¸4¦§§ëõzýÀÖÖV_áô` w9!nß¾ýbEÏcÖîܹӓÙî�;w>3Ƭc»•×j—�˹}УÃóa/s?•Je@DÎÅq\È;åáôßó1¢\.‡Õjõ´#!�ÜØØØf©TZ›d¬V«§ó~‘¡§q÷îÝ£ëëë#.½²²òQž�)ßÿý¥Ri@Ÿ]òÚk¯u-|n„mý÷‚ˆ»wï­ÕjÏA0¬m­ÕjµÅ~xV\©T†â8þŠþmƘµ8Žk�?^¿wïÞr·_*è:sss¥Ã‡ŸÃðDǰ½.‚ûý–†.—ËáøøøsQ½�>&"Åb±688¸üÁ¬vš˜Ž177W ÃðÐðððÐÖÖÖ°Ÿ\Ó›y0???ï×VöB¹\_yå•¡���Cõzý˜³‡ ¢(ŠÖj"ò c[GˆÐDÝKi� …µZmµ×~·“¨T*CQ ‚`8}Ÿ�p±³ˆùùù 7øFQ´nŒY+ ËÝžœåßê£(zàå—_þà u:ýø³-sss¥¼C¿ášìOî§#ˆ”RÛEã"JóOдBo¾Ç܇�æß×Þ 7$õ™œÿ!„±ˆ’éµIEND®B`‚ukui-biometric-auth/images/Face/04.png0000664000175000017500000000655515167732630016450 0ustar fengfeng‰PNG  IHDRbb«¥ 4IDATxœí]MoÇ~fvEŠ"e©�kCŽ\¹V+E"+¹5jÑøØ^ŠR^ãþƒô^ é/Hÿ�èa�6)z(Ú“‹Ä…péJ  1œZµkY+Š"¹Ü·‡Ý‡«¥ø¡îÊÑ vv—œ�÷™wÞ™wgv$Ñ,€_xî 7|ÀûU�¿mq"hRœ`Ò‘Içðâ§& À‘â$]#Mé¼éƘs2©SËÀÝ~ß;~ àcÆØŽ¸q\"zÀ{ýBÂcìÝ~DD -aëh _\“ïw"h'¤„À�v:’à;·Å9cŒÐDô€ÝêÞï1Æ~ x#¢÷¼ãݼàÛŒ± ˜Á1ˆHZ§“¡¡%h™Œ  H‘[3u½’à�ÛpIéKc|²x.iwÑêm~Çû5ónÞ÷.ÞeŒ}8hFR†BÈBè�Ž2âØ".·Ü^H×z"A:6pvRÞ†ÛààŽŽVÿöÁYI "À\AŠ£ŽÓI9 ½!“à' Ò¹ À&"@ƒ1ÖìWVŒ±‰HØã»Lêãn1Æ6úMh#@ýd‘Ó+²�ð“q\/Q¹XŒ9œ¾þsƘݧÜV<°Íˆˆ€1Öm”Pò5\Ö ™î‹÷JÐNû%¡“&ÈGA‚|­Ž!=kˆ�¿Þë|ÂJ 3~Rd­èÔ]i®ø¦.˜òB�áÀ‡LÿÃIäQQ ²&¡�xGQ—†·¥²7hDÔ€KHÇÑ–}k„O  ©€r<ˆ '»¯˜pÀw{-|�؃«þÿB‹”N$µ~ÿu÷…FÔ¥ëõnÚq,ÿ~ˆðHH %lA„�‘‰šp ®¡º·Å |·Uï¨xŒö9†ßFøç€×àjÀkf¼ë»þ ‚Þì€,d<(ø‰8¾~šíè› ²àƒH‘»¬ ø8€ßÀ%  à ¸­ö€œ´�l†ßh'gÑM«¾`À_ü�…Z˯ÄR\&£í~'2ú² rã'!è¨u ¢qÑœ*wxhD¬¯¯OU*•ïÑضýÊøš–––vt]¦ÒâÙ®®ëÏ–——ܺuk+¬´ã€b±øX¥;<" ÃЄC¬X,>#͸!ŸÏ7…;œ16Õí÷ý""²Ùl DZÎó3ên " šÍæXØi_Lèú€X`&ì`˜¸ "&…ˆ—/_6@Ó4¥+^e„B„x,JDcª—�D •u ­krÇ€ÙÙÙÉn¿=¯¸}ûvhÕ5L„FD­Vا_U­°,ë*0ÆBwu„FÄêêêsÆØ!c,9??¯Ìäõ¼*|N¡Žš,ËÚfŒrÎÇs¹ÜL÷œ …Í@³Ù|®bcè› ÃÐç‰h,nÛyû…iš ÆØ´mÛ—×}£ª>Jv•š¦™pgŽˆÆˆ¨–Éd¾Tµ3L¬¯¯O¥R©A÷ˆèéÊÊŠ2÷�²í½†ahóóósb ¦€®ëÏŠÅâ㸹B ÃÐ^ýõ[þëõz}/•J=U¹m PH„@¹\žxñâÅe±épw---}¥:ï~ vŽFµ\92J¥Ò´mÛ×8çv©T*ÆE+LÓÌ4›Í ¢/WVV†¾Ëi¨¾&y¿A.—»2̼;AÕëõ½(H†L„ìÓwçJÔs Ã04ñúÆØá矾UY†î}�‹Vˆa¶Ø¬øèÑ£­(»Ê¡­XXX˜"¢1ι]©TÊQÛ«HžGÈZ±¸¸8?l2 ÃÐ4M›Ü ‹qØT òÞ4"»yóæ�aæ¿°°0í8ާ}àC¾úŰ1CÕ Dú¨4›Íèºþ4MSþæ0Ã041TuÇŠ @ žYËö"“É,•J¥iùÈ£$ι=22²­"ŸA9ù|¾Y*•Šâ©—mÛ×Toy”´¿¿¿·Íø‘Ú?Ä['5MÛ ÛÉ&Ü+qôs1Ј�ˆºAˆ%byN˜«ôâº] VD躞Ô¼µÀ4Í*0Æ’a§bC„÷TOWõÊ6Ù…¡òå&ƒ"6DŒjÖ ˆ=p¶m‡¾võ¬ˆ Édr *•в—mI;b·.Dˆ5CŽãX*p–eLÓŒÕè)r" ÃÐlÛ¾###OTæµ³³³'¶«Ølrp"ºç}“9är¹ÆX’ˆ”¯”ÈçóÍf³ù�F,ˆòçp?{7ŠBlllÌØ¶}™1v¸¹¹9”ÙîæææWbi¨*¿VŸ¸ «ô,�Wt0Æ Ó÷cšf‚ˆÇÑ£vyùÝF†¡•J¥YAB¸l6[O¥RÛ€ëd,•J³Q/dªF”Ëå‰jµzC¸¢÷÷÷·¢|L)/±ôž]?^]]ê»júVé (—Ë–e]Ë/c‡–emÇáY±išÇq®‹ ŠŒ±CÇq¬£££êÎÎŽò7 +'¢P(¤Òéô”¦iSb¶·a|7nnhÃ0´\.wŶíkþ{DT±’ÉäÞƒÂ&&t" …BJÓ´±ñññL£Ñ—�k^ež‹ÅX¿+Ü0 íöíÛ™Z­6Öl6'ýÛx9ç¶mÛÕD"aQ(û$B!B^~t_×õg–e »ß ¦iflÛžô>“ÖVÏ0ºØÐ4¢X,®ãkÛv•1v¨ëúžêÉY�µ^l^Y^^~p–4�¿ŒIÎR¸¨‡~QÀ0 -ŒU'Çò§&Â(àzMás´¾ëy'º"}mqÇ;Þçp?q¸ü¾Àp!dþD4+uOoGZ¬¯ˆèmIî³ââ»ÒÅ{Ç7.:¼†O’÷»þ¼Oƒ#²çQÃ'Ô~ñ~§Dß$¢�HðÅ�ëÑÈë#"zSNçÿ6 ÛÏäèIEND®B`‚ukui-biometric-auth/images/Face/02.png0000664000175000017500000000572415167732630016443 0ustar fengfeng‰PNG  IHDRbb«¥ ›IDATxœí]MoÛÈ~fHIÖWìÀ‹œ:� ;–„8@n}Ùz졇B×ÍOØ{Úí/Øþƒ´={Øý ) ð!@„ØXem$ÈbqLÉú"çíAœd–¡×_’Îú3$¥ùxgæ�ygÑ€?úàdøÀ_d|—õ}óg™@ØñM\ñ¹Ÿ`ŠûI1'x¾/¸þµê«nì߇8À($ü8¡œ+òú†1¶#¼+}àËF„à÷˜Z \ gðS’ÌÀ=é$ ¦ïŒ€*NJ‚*tI‚…„GÊïdø_æÎ(·/c…,}àsÿác°Íû/q¼fVq™#ü G‘r’š¢:• I„$CB­ G‘pÜ›t£€vOõG!×ò¿ð+ñþkó7ÆØŸ}Š÷Uæ!cìJÁ@DGpÔu˜°OCPÐI"‚Ÿ«°Zq ÁÏOØ›œ ƒÏÃvý“{Œ1×—ëg˜¼ððÀôÙ€ø7å•‚šr¦Ê\N Où‚RïI ~\m8ªFH'‰€B„§¸°š$(¬F冊“׃_º> ü<üÀŸ0i_2"úÀ-¿ð, )ø’ïç}7¥ø9?œ ‘SŸ;Føa‚WqÁÆZýDkˆl3TrÔOV°áVI�µE [%¡¯!Ç~x ç‡å½€®×ÿ°ÍˆH¾AF pòÍ öbÂQÕ7B®9>nð¾*dãˆ0Çd¨íD˜àƒ$�‡v/p?̹G\�Þ#“÷äs™/¾°Œ1�À¶í,€l·ÛÍ•Ëå,€ìh4Ê�ôÿ®ëz…Báp<{¦iîW«Õ‘¾Üž²¼«Œ±`706lllÌNMM剨À9/G7 3™Ìí¥‘”wòOŠ˲Œååå93Œ±wo{öl«^¯{‘"$J„O c,Ç9wƒA÷êÕ«»ƒÁ ¯ã­m6›óŒ±ëD4ìõz�õõõ~Ôiœ‰aY–±²²²DD…Ñh´ÿüùóí8ÞRIçÜ=88ØJ ‰ñí·ß®ømAìÙØØ˜Íçó·ÒD†”?�3Ñf³9Ÿ °¶¶¶×ï÷·…æ•+W–,Ë2âLÿç¶m—c× ×ë½Lêm\[[Û#¢Bsee%5dÄFÄx<¾£Ñhmmm/®tðººúšˆ†DT¨Õj×’Ì‹D,Dض]’ÝÈ|>ÿ"Ž4�C&“Ù!ĵF£‘O:?À6€}�‰ôûýë`šænZU•Jå!„#„0‹Åâb‚Ÿ¨mûœ1ökÆØU�)e³ÙØßß­3�Óbkk«Ã9wc¹ååå•f³9ßn·çâ¬!RþÚ»¬�F#_*•*œs·V«5u§wZ4�ü•+W–„æq¿-‹ß-..¾Õ‘ímD±X,À`0èêNë,X__ï·ÛíV±XüÎ4ÍWDô#cì0ì·Ýn÷¦®|ûœãñ¸œÍf‘ÉdN­3Š þÈþ­ï>€•ë,ƒö155U€^¯—Z"Žƒa³@DÚºÝZ‰h6›×„&cì0 ꄳB¶ÕjUÛçU�F#Ï» œóŽ®ttcccc˜¨Ñu¦£�ˆB¡pLÓ|•–±ÃiaY–Q,çÀ0 ­c--DÈ‘4çÜmµZ©;œ·oß¾%„0‰h¨»Zˆ�z%Îùë´Íˆ�²£`_w9"'¶í¬Ô+éìeÄÎùk`ÒkÒ­‰œ×ug€‰–õ¢¶ ­Vë5çÜB˜KKK‹:ÓŠœ"š�êÜIQ¯×½ƒƒƒ-ιË9/Û¶]:þ_gCäDÈÏÒEÀ©X__ïËO”Ô"뀶îëEÀ!Û:¥ñޱÎY_Tȶî$ڳ⒈”à’ˆ”à’ˆ”à’ˆ”à’ˆ”à’ˆ”@Ç€Î&óQÇ�:�Î40±µÐ•FäDÈErÑÀÇ€áp8ãµÍIDN„Ô1�Çã�†YÓ4/�Ngšs> èUÄ ùr‘¶�‘±±±1Ûëõ~CDp]÷£Ñ5U*•Ó4wuªÃ##BÎ횦¹{÷îÝ'÷îÝÛŠ*î4 Õj½Ô©�„˲ ©kµZ/£ˆ3m¨×ëžT‡3Æf£Ž?"ªÕj„ÎEž£>ÒÂÕó¼BÔq_èN¹ÀL¶ƒQâ’ˆ” "Þ¾}ë€a©°G»ˆˆ„9-JD…´ê€Î²EöiB8°°°0sÜo/*îß¿_Þ—5JDFÄp8”ìsk­pç:0Æ"WuDFÄÚÚÚcì�1–[ZZJÒ8P Ôõ¼:tN‘öšÇÙfŒrÎ˵Zm>ʸ“D£ÑÈÑ"xž§e»¡È�ÕMOLÓÜ­T*;Çÿ+�°m;Ë›s]÷`¢¾ÑU-V¥¶mg…‹DT ¢a©Tz¡Ë3JÈMSžÑ�«««ÚÔ7ÚÌ{-Ë2–––ƒ;’™¦¹Ûjµ^¦MbY–qçÎ�{Áû£Ñh?ŸÏÿ¨Ól ÐH„D§Ó™~óæÍ'Òè˜XU*•t§}¨û9%aëöqív{ÎuÝœs·Ýn·ÒR+lÛ.yž· Dôbuu5v+§XuMª½AZv…Q{D£Ñh? €˜‰PuúBˆkI�5,Ë2äöŒ±ÃçÏŸo'•—ص¯i©²›-�“Þ3v"ÒR+–——gå¶v½^¯“t{•È|„Z+’ØÎͲ,Ã0Œ9`b°˜£šDˆPmÓˆ¨pûöí[q¦¿¼¼<'„0ÓdžØ6Ô@2ÝÆ4tUÃ�èTiµZ횦ù Ãоs˜eY†ìª !œ´�¤`ÎZm/J¥R¥ÝnŸõ¼žŸ…ÚK✻™Lf[G:gEâDÔëu¯Ýn·ä¬—ëº7t4Þj/éàà`+mÆø‰¶A<}út‰s^6 c3j%›T¯¤QϤ F$€lÒC*‰�Ës¢„\¥—Vs�Tašfгk�mÛ}P IRC„?«gêÚ²MUaèÜÜä¬H Ýn· èY3$!mà\×�|íêy‘"r¹Ü,ôz=m›m)–?©[— "äš!!„£Sç8N˜leä³–$N„eY†ëº· “ɼҙÖÎÎξ4?Öalrp"zDD�’Ê@­V›gŒåˆHûJ‰z½îyž·ãñ8DHùsL�}˜D&šÍæ¼ëºŸ0Æ777cínnnþ —†êÒk�á›È�€êŠÆØ³8u?¶mg‰hEa&­òHäÔ-`Ò&´ÛíIB ¸jµ:ÊçóÛÀDÉØn·’^Èk�èt:Óý~ÿ–TE'}œºÄÒŸ»~÷AT±Øét¦ǹ®žê8ÎvæŠmÛ. !nJEÆØ¡Â ý��í; k'¢Ñhä‹Åâ¬a³ÒÛ7�65´eYF­V»æºî�à3ÿô_'—Ëí?yò¤51‘Ñh4ò†aÊåri<—Uåš<ʸÕj¥z¯p˲Œû÷ï—†ÃaÁó¼™ /çÜu]·ŸÍf�¨ŽeŽ„uù}ØsÓ4wÇé&}ày`ÛvÉuÝÎy9XÎ(>±‘ÕˆV«µ*_×uûŒ±CÿdõTît¨µ^¯Ü½{÷Éyâ”òù8Oæ’îú%˲Œ(V�¼“?½Çt¼ÄÉADÓRøÀcÿþƒä²ô‹ÅßÌ<õ/>O&/¿hH™?-(Ÿ§ÏÍÖ/Dô™"÷yó 忣w.9üÿ‘"ï/‚?øŠÎŽÄæ3’F@¨§ÅWGEú)}}†ßÄ\þÔ€ˆ¾?ƒ¼¾&¢OÕxþoïµf‡ÀIEND®B`‚ukui-biometric-auth/images/Face/01.png0000664000175000017500000000501415167732630016432 0ustar fengfeng‰PNG  IHDRbb«¥ ÓIDATxœí�ÍNÉÇOU·müDD‰ˆˆÈ…+;ØŽÄ›ÌSx›¼ÁÜ7È#ä²ïMafeÉ‹H±ÒÝhL@‰�âÐþvu�»À•iq™K U]Eà'¡·©¯×ש:UqGÄ?¦??Ë+¸¡ â«ÊI”ëúO¾˜!À³|‹9ÿÆ€ˆ®Pn/Îö2òðD|†ˆO5åí—ŸNËö�Hy¿Œ><ÓœÖÃTÁÓhwcÛy] âëei㪺vÓ@Äê´ì?DDBÑ�°›ˆ([wBÎây^’Ýn7•Ïç“��Ç©Ÿý{ÆX˜Édú“É$´m»S.—ÇêR+#jD³Ù\š››K#b†Rš—6"މÄ1"›(Ê�ò×%„ã8V±X\€EBÈ�7žÒÃ0$„ô‰DˆˆÁ¬aBòãñ8/„%„ôß¿¿[¯×Ci™�€V!¦"lBR”R6»wîÜ9‡om«ÕZ!„ÜGÄQ¯×kooodÇqY´ á8޵±±Q@ÄÌx<îìíííÇñ– 1(¥ìääd×1´ ñîÝ»�i_{�4›Í¥t:ýÈ$1DùÓ8#mµZ+ºD¨ÕjǃÁ`ŸsnÏÏÏDZâŒÿÿ›žçå!÷z½Þ']oc­V;FÄ�œs{ccÃ1bb2™<�Ç�Z­vW¼çQ­Vq„ˆ™J¥rOgZ±áy^N #ÓéôÇ8⼈D"q À9¿×h4ÒºÓC`:*# ÷lÛ>2eRU*•¾pÎι�Íf×56QûС„�B)™L.t:�C•ñÌÊîîn›RÊ!©b±¸ÑjµV|ß_޳†ˆòW>dm4é\.W¢”²J¥ÒR߬4�ôüü|�s~¡Ý-›Íþµ¾¾þ]E:”÷Ùl60»ªãº ÛÛÛß÷Ýl6û—mÛŸñ+!¤Þw»ÝîCUéPn}�L&ùd2 ‰Dbf›Q\Lgöß§?ÿƒ˜•«Ìƒò177—èõzÆ q–e- ¢²a·R!Z­Ö=ιMé›`N¸,¢ÿ(—ËÊšWeB4�4!ä!¥´­*Õ4›Í%€S3ºÊx” ‘ÉdضýÙ”¹Ã¬8Žce³Ù˲”ε”!fÒ”R溮Qs‡YX[[{Ä9·q¤:J„v%Jé¡i+b³ ÐQ�éBxž—v%•£Œ8 ”œŽšT›@¤ Á[8µ²^×¾Aàºî!¥”qÎíB¡°®2.éB â"=�ûYêõzxrr²K)e”Ò¼çy¹‹ÿêrHB4K×ye{{{ š(aEV�²áëužÀ�Eôu‘Î[:±®Y_WD_÷3ÚËr+„!Ü a·B­†p+„!Ü a*&t àt=Bvغh·Û §¾ªâ�.„Ø$ 6 ü ŒF£Åé¯ÊÖ$¤ !lL“Éä—BäŶíë!D»Ý^ ”.¨5Ä�x¹QÙŽ@iB4›Í¥^¯÷oDÌ0Æ~[S©T:°mûH¥9\šbm×¶í£ÍÍÍ7Ož<Ù•¶ ¸®ûI¥9\ŠŽãX æºî'ašF½^…9œ²$;|)B”Ëå4ç<¸ÎkÔ!<\Ã0ÌÈûvB7bƒ™èer+„!Hâû÷ï!€eYFø£]G¤!–E1cŠs  TæMZÓÄ9VWW/úîuekk+ðw^e"MˆÑh$Ø—ÕZÁ}BˆtS‡4!jµÚ1!¤OI �Î�JˆîçUas’:j ‚`ŸÒ§”æ+•ʊ̰uÒh4Òˆ¸†¡’ㆤ;3F=±mû¨T*ÈŽ#.<ÏKB–cwNÍ7ªò£Ä«Ôó¼$ç|3ˆ8ÊårUycÊDšrÞ3DüZ­V•™o”¹÷:Žc …õ³'’Ù¶}äºî'ÓL!ŽãX�?~röóñxÜI§Ó_Uºm(BÐn·¾}ûvW8½œz•J¥/ªãž…èyN:üÁc=>Î÷ýeÆØJ)ó}ß5¥Vxž— ð€ˆ«Õjì^N±Úš¢þ¦œ �ÇãŽb"jÓçœßÓ=×pÇÇ?Bú{{{ûºÒ»õÕ”Z!†ÙÂYQ÷ ˜± aJ­(‹KâX»^¯×ÖÝ_iY�ˆÖ ǹ9ŽcY–µ pê°h‚S�!¢¾iˆ˜Y[[{güÅbq™sn›ä®õ`vÃF†ªç¡u©´\.wmÛþ `Y–ò“ÃDZÄP•s˜"€kÖÑþ"—Ë•|ß_VOt”D)e‰Db_E<—E»õz=ô}ß«^Œ±*:ïè(éääd×4g|£.ïxûöm�Rš·,kG¶‘M˜WL´sP#4�Ô�€ó0R±=G&b—ž©îF aÛv@Í©žç ¢—†˜„1BLWõlUG¶EM*7¹,ÆÑívójö „cLúÞÕ«bŒ©Tj  ×ë);l+âùcÜ&8#„{†8ç�J\]€Ó£Œ¦×¬ƒv!DZc�‰Äg•qt„û± g“«@§w•j»§´R©¬BRˆ¨|§D½^Ã0<˜L&F!ÊŸÀóéOì´Z­ÆØ]BHgg'–ÙîÎÎα5T•]kFžÀsmFwtBÞÇiûñ|ùðÕ�·Hgú⿊”÷‹³_x‰—GÛz†nÎꬼü§@Ÿ"âëKø-æü"~¸Dy½FħÑpþ CIÙ$uÄ�ßIEND®B`‚ukui-biometric-auth/images/Face/13.png0000664000175000017500000001002615167732630016434 0ustar fengfeng‰PNG  IHDRbb«¥ÝIDATxœí�_lI^Ç?Õ3c¯{“UV·$w'û²Ç†Äa”=-,â“'!‡ßB Häžè¼Ç#BJx�YÝÃ!�@ÙB ݃½ˆµXqQð8—Üæl³«]âx’8Éôô�‡ú•»¦Ýãé±g¦'É~¥RõtWWUÿ¾õûÕ¯~]3DdLD΋Ȝ¦¬¸Äs ¹Ô†œœ\Ï‹ÈX³ gÛ¨0‰»=~þ¾�ˆ¬ìAn³ÉÊ.xçD䬈œÎéÙžYˆÈi•íœ'ï þE‡³9÷õ¹�âpÚ·qÏ­�Ï "ryKöž�›Ì»cÏDdRe¿bDDŒ1&ïŽ=�pò/æÝ‘$ĺuã))+Ö�EÍß5Ƭu²ÝB_h„: '5Mu¸úUàà�~$eKþy!"û�·�34Žx7š]>¿‹ê§¼Ü/SƘ{»¨¯kpòÇùO=n|¿ç$ÜUïaZš­6÷Þž['­ô›S²%ÿ^¡$\Õf/«fô¢]GÆÝ~"#O"®îF ª1;’¦î`Ó2Þ"ªoÈÈ…ˆ½ŒJ½gǰ‹ØÅéŽÑ�=ÑÆýé-²‡PŠ»7C¹óâb7­Ë‰jg®däAÄœ›vq﬈Ìe(w:K9-»¢ý™m]º{è) mhÛ3R“Ör¤kÙLÏ"qØ?×ùÂ'bEºü>AüàÖök©ÁF±ÞÕiØŠ¦9iÿŸó´î‚dp‡½ò+’“‰ê…üýÆ&ç§EdÅû<©Btž“x‚ŸVbR…«×N+ésšßÕtID¦ížW²ïzd\Pâû£ê($Ž0nc]ü²æw=aL'Êe6�*ÈYïó˜ Ý_»œ‘«^ÿ­0ݼå>‡ÄÊåÄyu}¹Ù(”6&àVå•GºˆºÃÚ—i%ñ‚GZ+iõ>�x~8ï�›Õsw¥µÏä’zå÷K ›«eæ´-]i‰ÍãÓûòÌ}“Þ¹IÑw·6]L‘έ9´lƒ=uðÌÒÕ&ײ,¾æÚ@–{t0d]sHr÷‚ [«\Ô�gRŠœÄ†¦[aûN¡¬Òâe’1æšöaGx¦+K_w�®ALÂÛM^ÈŒ“MÀã»x¡³J¶·zóÍœØzgâžãÝ6û�?$^I7 ¬e´ã“if-Ã}Ó’!”¢óOÓÉÚs4Vš=G§Ð-�x[ó‹ioÄtfQõØ·tíb]ïm…Ev6OSš¿ÛooöZB¬¯îÐlÜΈÝUP.£Æ�%'lä'Üì§N#ÜļµƒBâ­†ûÕ›ù&]žü²@û7¥ýrîôº7€.k×Ó5GH¼Pòp§={ë#KPnW¾{«{U¦Õþß»š>ŸùÒyzÖž�›…,.yêî&ÂËj¶"¦JÞÕݘ&gr´­ý^}çµ­¯Ý«þ iRŸ3Qm¿KÉŠŽo¡i½=GËŒcÖTð'iœFÔ™ˆ¬8Il"�i™ÇšÃy`Ñ3›³ÚßoïÐß1íϺ1æ¥6ú‘=ßé§š²%Í×€ï%ÊÍa‰XÇ !‹ä°êŸ1Ƽ·ûÛ>êøj§m!�-—™\RcÌWEDv;UpëH˜ÇºÛM5¢èæÊºÆi?d±¬ÒÅÜi<ËD´Z¬õò ¢ß°J{»Í»‚gY#2A�…ñ¼ûÑ·DHöxÔ3�n±[‚Ü vðë8$Þ4°Ú­6ºAļæS]¨;/lÅϺÕ@OˆÐ�C_îÒ~ÍkLiZìF�d¤uJó§ƒUásúqÊ»4¼#vwÅIàL?£ŸÇöoNüæï¦�Ô_�Æ/p‹¤¼˜×Q7çE îs¼ üµ¶³ 5àWµÎ†E$jƘ=kJ§Ü×"ð],Œ%å1Éü6ð%ì„ìLRàç�뤓á�FÄkÀ¿`‰hFB8ŒÕà}úÙO5b2Bà÷´îïcç–(y„„íI.ÆžˆPJZÏßœ¾ü>°é]÷Ó¿¿¼Oã<‘$£ ÏI2 ‘ñòQ=¡9 ƒzý¾æ¾øšP^ÇŠ ì@ö®Õ€Â^4dWD¨ËYˆ]þø3íð,ö…¼ÝiÅïG€ÏBl¶’d°#/9O8³•Ô ˆçwï‹l'Á™ž/±�_jXçÂ}—ã°.±ó¶B¯ïŽ�–�ÌÞVÛD$´À1 Ÿ |ø`Z¯ý)ÛÉxE«›À® ü7ÛÉø/-ó¿4º¸þš"�ˆKr•˜Ÿ„"ðKÀX/n„Xè>°sž›þø à¯¯Žˆä:¨ "O²jG[D( Ä‚wD¸4<þKÀ×€SÀ_W¼û¾ ü&p ;WœÁš±eà–GÜKÀË*œfdøˆ€ƒØÝ1àC¬P_ÄûSÀU½kfBíëo5yüïI# N ü5Pƒ U2ZΙƒ~ |Á§‘2€M߯ÚVï|KÚ?ê=¯b1¦{ +4°ä¼Gã¨K›´ÁjÄo`Gy•Øþ£u~„�o=ÄšÒ?ÇjEøVÊ£_Ñ>þ'ð+øÐ;®yÇO¼k ×[‘‘I#<|“$!ù9ÄÎoaMohu¿ˆÐ�_ÃÚÚÖü|_�‡�Ÿóºðyàw±¶¹F:ûõ^´ X®cɸGl÷KX’7´ì°ö¬f~‹X¨NÀƒ4ŽvH÷Ü Ñ{ݼ“™jI„71;ÛíF}±Éç$!ÿ�z;o| 8�µµ‡�ÏÑè]¹üº>Ü«X¿=š©Ab�ðçˆb…&XÓó%àÀ#½îæþ;^Á®'ÀjžkÃ'=ÍKÛ&®Dòç$GFê"0Ë:Mz7~òçŠf½�úVCnÇõÁ±&É¥!¬ÉpšèV¾NÝ}?"vs_ÔºÜê~Ÿ¦aMCšÆ°óÈ!à×õY?ĆÍ}œœ“ÏÕL.ÉÐŽ¯IÛP„­Qïöýz' _PÞçÍK‰sþƒøÇ?‹�+Ø…×cÒÉ+ªðƽÏɾú#Ö�ÄaÍ�$ ½ãM_Ñ~=ÁÎÄd;³Ô,=ö’ûü(%wiSD±}áX7JDr$»Ü ~„x”yÇŽ !Gµ#jÀ;vD¼ $�ÿÃÚöI]좂õÊN&Ã_i'ÍD¤×ˆÍFë>»‰Ø'ÁM¾NØ> ›îø¡?ÂF6½s°ó•««æŽiµfï ’çÒܶ¤ oÈëõúWjµÚ"R/‹ß)•JQJûN §°š³î�K >‰)¶ÿL©¿ê~) Ã_ÃðEcL888øOX3�árEž–ï”ê)Ǿ)ݪËuì�u;(—Ë…ãÇ�Ÿˆ¢¨hŒyxýúõ›333] 1ïÔ~±XüäøñãŸöªífÈeòÌÌL}ccãf¡ˆ 9rd¼—í=zôPEŠ¥¥¥Û½l»rчJ¥2R¯×�ˆÈG“““]JmfA®Ûò'&&î‹ÅO …¡………¡n¶W.— "ò*@EÕ~!úàûKKK·ƒ £(*ŽŒŒ_^^>Ô�vÊåráØ±c¯9“T*•V»ÑÎn‘;333õååå¥(Šªa.—Ë…V÷µ‹£G�‘á Â���›O:ÝÆ^�ë‘ÄâââkAŒ …÷;Y÷òòò¡0 ÷‹—”Dî‘òî@ú’ˆ{÷îu|M!"U€Z­6Úªlè+"ŠÅâÀ[o½µÙéº+•Ê&€1f°UÙ<Ð7DT*•·ÒîFýþʽR©ŒìT6ô ÷ïßëßw« y †áp·ÚØ-ú†ˆÁÁÁƒ<¸Ó­6J¥R@Dúî ú‚ˆJ¥2ÁhEÕnÌÕjõ>@£•J¥¯¼§Ü‰(—Ë…0 ÇJ¥Ò'Ýlkmmm=‚Às°›mµ‹@¿–ÛO-Ÿ8qâ Æ˜AùŸN/â’˜™™©×ëõ;µZ­/ˆpò°_C:—G'®]»ö…0 _6Æ<¼qãFOV»7nÜøÔóÐ3Ø­¸V›8œËí]È!‚Ðs½—±ŸJ¥2 "ÇúáÅ�“Ïçˆr¹\X^^s$䀛˜˜x244´ 6ȸ¼¼<Ö�@c;è©Fܺukÿæææ¸ EollÜì¦—Ô |ðÁÁ¡¡¡q€ Â|üæ›ovÍ}NÖü{AÄ­[·öW«ÕW‚ Õ¶V«ÕÕ†ááä5y\*•ªƒƒƒëW®\¹ßib:NÄÂÂÂP¡P©Õj£~pMæÎÒÒÒí^îÖhår¹pêÔ©‘Ç�×ëõNK‚ Ã0ܨŠÈ�NÌm!Bu¯&;ìP,R­Vï÷Úîv•Je$ ÃAŒ&Ÿ³&¶c±´´4é&ß0 7�1‹Åâz·gyÀ×ú0 _xýõׯì¥N'ÿ=ÿmËÂÂÂPÞ®_(—Ë…Nì:Ù’¿Äèïß!z!öWúEtø¼žŸÊ¯KÏ-¦4ŸˆI2óÏû|†ŽÁÉ|1ù(-ÿï3tÒø‹ocîä¬wò’ì⯎?C6èÀ¿äÉ{6Yà‚ì¹½ÏÈ ¡¶‹ô?D”æAÓ ½ù?æ>„4ÿí�Ðð£�ÿ– RAPf|WIEND®B`‚ukui-biometric-auth/images/Face/17.png0000664000175000017500000000723115167732630016444 0ustar fengfeng‰PNG  IHDRbb«¥`IDATxœí]ÑoGÿíÝÙNœ¤Nš‚PAµ¥ uZ¢$|­@<ðàð@y@àòÀOFâ� ïHÎà UB²„œ¾ !Ù•*ƒ ‘]É–@@} ª…`§I�;ß�‡ùæö»¹ÝÛÙ½=ß�ÝŸ´šÝ½ÙÙÙï7ß7ß|;³(�œ$¹@rU6_,á„‚äR 9Y¹.�œŒ+°’¢@»Güü’;]ȭⶨ~\%9Or¶OÏvlArVd»ªä½¨´˜ïs]O „‹YmãN¬�ïH®4e¯lÜL¿+vÒ@rFd¿�$Aô»b'Vþ¥~WÄ�[7±ùbÀ¦¤·ƒ x7Ïúõ ¡â$\–­œsñU·ÜDRšòï$'Üp­-Þ¶f›®e(¾¬R»¿  Á½ åõ Vþ°þÓß|B9 »â=Ì1n´Ùýýì8igМ’¦ü�š!aCn»"šq÷µdìý$b#‹@Dc:’&î`l5ˆ2úBD7­R®év¡œvŒ8d‰6&Ôçh‰`¡{­G¾ÚØMr>Švö•Œ~±jû… ×VH®zä›õÉ'yw¤>•äܽÑáhCjÏHLZbK—¼^ÏÂ0ìß×þB±Ã¿O nµÿl¤ñ®fE`;²­2>þ¿ª´n‘î°Ê¿Ã>™¨£�¿¾™ÅŒs~ŽäŽ:ž!Za¯2ìà焘HáÊo³Búª¤»²-‘œsî» dï*2…ø�ð¨rÃcëòà+’î*aÌ9ù¼M§²¢Ž'Eèzì2OrCÕÏ’‘„¹ø;8z(+Îy=º^‰k…LÑ'åR,餸ÃR—9!qQ‘æb'ªÜ¡ÃþaA�«È¹]&Ûq/—TåŸ`‚Í•<«R‡DWš¡yÞ—gªõͨs3”w·×W˜ÒÅ$ósHÞ :(³´ó›Ïàk5­|®‘Æà;根ݠЫ‚EnÊáõˆ,—aBÓI˜‚y§�U$¼L ‚àm©CG(ÓåS×ÌèI¸óBf ~žÊðB§ ¿·zkqNÐ|gbŸãvÊ:ô GÒ±�5O;>eÖ<®›£G(EúŸØÎZ9;qÏ‘z¥7$½õFLZ¡�ªŸ‡yK—{rm6ÑÙ<•%½=hoöAã«[Ä�‚Ó´ØLA9O�›t;lÝò7{è4ÂvÌÍ §Nˆ7óô¸óó�Ô¯,õ²îôžj@7j×põ Jz7«ì­†OP.“ïžt­hÜØÿ]šÑô‚ÛòÙžq„r\ÈbI©»íWÄ 4#¦BÞFÓdMŽÜkB•· ÷ÚQ÷ÝÐ�&¦{A\HQoùL?Ñ”¦ $}ÀkN¾U"ö`„àãYTÕþõ ÞÈ^cSGi_iê� ý˜réå’Að"Ifm�"¸=Ö`ÜíX�8 ôrd‡)¤YdA=lÁyã8‘4X(ôƒˆACéf›÷ÇY#¼ ÎÂT¿ë1°DÐ?u,Ð "ö€¦ »AÖ€_î`8i Ú«{ô‚ˆ5IË=(»_hÆÏzuƒ#!BB9WHêµ&1¥9š‰n¤µ,ép!*üŠ–ÕOe·hfW\p}ˆ�¯ÁÔo&*…5IoG�4X`ën2âż´ºUñ$ÃoS¸³çuÐ.C}æ$¨7«Îͨrõ: 2aÎÃ`¥÷«4È-è'­ý<Ì¢ÁvÈ× ²©€_Y¥U˜Ö©íòM·ÜFØáo"lõ:ð÷¶òÎ:¾—Q•2ËÝÆ¯\äk’JÚpBœz·!*à'‚™BHÄÂW¯¾¨ªýM˜ ‘‚2�4A!‚{$oJ]^�+¹€ádŸ cóô˜1Çp¾jVÓ4/×'½|šL2K*¯}ÎÔ’Ð�]~#ÙM˜èiÖ—öU¹>i*Î<ÇJ«r�a 2Ýb`„>È‹ûÀ‰agߨ޴¾ruò�IXF¶Eõ¹""dú"\ö´éÕ$Û=ˆèå"OÓ´&iÔ2fÃÐtXXÁn0ü€»is§çÕÎ2bÌÂöÅövåèñÿª3�e½ºEÆäo üј—Ù˜M¯k˜:•½HÑ4¶~+¤ã„äc¶~r¡B£)±Î‘Qçºy&˜3!jž­QÏf{­¨$=<™~Y­´ö$‚)©%!sÈ}(áhÅR’MfÖY+Ó¥=»“C‚S¬M£Ççá"®éX®˜£U‡¾Odè ­èh˜rPçÓ¯¸}Ušº;øv’LÿušÄ«lýÈãÉ3I.èá6ú´p'¤‘-ké:ÞóDÂé/f¤OX%yƒäK$Kòû(ÉS$OË6³½Aò›$Ÿ!ù#’¯1 ¡\TZØ“ùIYÑ÷¿* yÀ;_³¾ àM_ð€§äüëþ)Û?bŠ»à§²?` ÀoäZ;mç9÷\“s ‡’6‚ häôh©pÔfaÞƒ”$-¸CÀW%ëÜ—ß'üÀgüÀ§e? û>à0dÙ1Ìø ß° ‡ç¸n�ƒ èùçX{¾˜‘dFØv+¡�Œ€ïø€«^ðÂW¯ø1€%˜Æc7 ›ï»ø€Ç`°Û'$Ï«0Zu�Ihî“<´çz¥1=!‚¤²z\ªÉ°ç`FPÙþàŸð>Ú‰°ûOø#ÚI €1É3…�"x$ ²ßL…”r&%W"H–ŒÀÔ¦%t&Å5S€yèÇ`\�tQR{>Šë¶FñgùíŠü® ð!¡¦Žë0¤ÔÔ‚ 8Ì"/�¼æ¾Zlê’ENŸ•"?pVýÀ´ô":¡m¹&áÀ¿åü§¤ì8ôÖ&|µÕ$Q„ÔS N¡+"bÐçÜ}­š”BUÑj–4µo…¯ aDjM�6#/ÀtÖQ$Äi‚NkR}®Ø�†d"Bõ£ˆ'Â%EkE”¹º"Åÿ À„¹dXÏ h× Ô‚FÄþ]aúëºF‘ 5¡Ùò%µÏR“ý:BGÄRƒ!ÄÛÛJM„£–ˆQUA½EJÑæ«,·Ø@¨�ÈÐýGKÑJ‚=>„þE_ð´“ÕúÝ–_’Ô ß¡ëX€!䑯v¤"BHE(lK„ÝâÑĹ&k¡GôŒŸ¯5‡ �8Þ“xöÙgßKºþ(±¼¼\¼téÒ'ëõú“îo$FFFöÇÆÆöîܹsÿå—_î:Àç”oäŸëëë§‹Åâø¹sçÎÖjµsAذ³}˜»[[[äý ybyy¹xåÊ•³㇇‡çIŽëß …B½^¯?Ý'ywzzúQ·÷Ì…ˆíííÑF£ñ´[a‹R©ôŸýýýûW¯^½Û]uû‡ííí³õzý|¡P8ç>gö÷÷«×®]{˜µüÜ4bkkk¦Ñh”lk ‚àA©TÚ›žž¾Ÿµrƒ ­õõzý xþùçïtSf³�¶óJº©Üòòr19çñÂòòrq}}ýt·å4坿ø|<ÑêˆAµ8¦€ãùé·aAYÒµµÈÞŸ÷ù¹ÁÊ|S¯ SκþÙÁÖ…““ödE�\â~'cXÀö%Ã7Ã"³c¸ÖçG¨i½d˜ñA“„ã¿3ŒÿíNh[2üWC¬ŸYæIEND®B`‚ukui-biometric-auth/images/Face/11.png0000664000175000017500000000766615167732630016452 0ustar fengfeng‰PNG  IHDRbb«¥}IDATxœí]KlIþªºgìq=Nšmµ dKþÍ&‚I¸ÉÕ^eÍhF½šŒ…V"#I"nÖ#Ö˜Iãp04�1ˆj2!b7½’ïÙqÚ…ÔàtÇÙ�MÑÆ*íi.´‹©}o„|—HÏÝTÏG¬�‰’‘Ú/Ôqï8MDÈw>J>Î;Ëí¯ž;>4•ˆ€6Ô±I«ÚÓ9o¤g!Ú?Qa1K1¿O srkûµŠ“�¤¢«ó,°YÞ&(|þÂкË!6òÏRB&ªò7+Ó œ%¢Yãx„…¨…=A¾ƒeb* —¯�gÒ'8]àí �ê½Äd/d\fâ["¢j(ÈŸaÜÆ:?øUN aŒòE6�,Èq㸇…nŽ]^"¢›Fû4Õ0^s‹ƒüåjà¼9º¾Ö ©\-?“¢I'âp˜Û2Ê$^6H b¶R¹OÈ÷—Œsã|n�ªÛñH!©‘¿‹ªØ\Î3Ám¨J“oŸÞ—gFï1Î�¿»�pÿ8Õb5nÌÁyË4詃a–n†\‹2øš¨UQîáÎuÌAQÈÝ d\³¼Æ‡/TÈrjjºz¡Þ)Ô‚9Ty™$„˜æ6ìÃtEik݈�ø$¼òB¦ÑÜ[Ç �9D{«7$[ïLôs\«± Ƀü‘tèÄZD;>RɬE¸o”"L¥°ÿ uÖF 1ö�B\ñ §¯Uz#ƽ0Šª€zKW+ùÞj¸…�ÍÓN¯µÚ›½ª «k„�‚ké±uMÊEÔ¸ž Ã6{~ Ì~ê4B;æ­ä/5ìâhæeÄìü¢€Ûw�Û¥ÃéE£½_»ž.Aþ@ÉÀ�7ì­‰(“ruÅîÕîemeû¿@j4})Øó©| äéGB›²¸b¨»v„WÙ l͘2y7ë1MÚäp]]Fy—¸®Y£Þ›f§ )O›¨šß¥DE×ÐU_žÃyz…ó,øÓ�­å!¨6Qq¾‰Ô¦eÊN¸e˜Íqnï«;´·‡Û³(„x¦†vDFÓWú±¦l ‚ÓyoòM@±%„(Q�Æœ±ÿ‚â­ú[¬ÚÈý«–6Ô„$–\F I…_!"ª·²à#�0 n‡jD3çÈ: ½¨}Ê¢Ì!ÆÜh$¡½ˆ@ Nm(_& :Žö=ÕüÛmß!¢v26OÑÔÕ�Õ�øjp"’P–,c_kë~øDã|5"öqyYHPÕR‰�ÿ — ÷„^cž¬64•îåŸð6uÀ¾&@ œ @ R_3µ¡šYÍ@=ß~ðV2Î}¥¥Yäp9-5C{b'‚ˆ´ õÖà�P=ÖÆv2,(Aø¶k„¹ihRÌÞ¦& %㞬qìšûLN¬ˆƒˆEˆès P°i~O·©&ã0€Ul׈JDè}³çv \#*‘ Ï@'*�Àûßà<ó¬É›PšÒ03ÖP"ØÎ¾ à[P�Ÿã:ô¦{~;Ôƒk-¨DFü­ÏÕB„ÖM„I‚>Ö„€ë©D‚ àÛœçMn— ¥).€M!Ä®5¦!D0).ï¯PD|Àï¡„Ñ   À=(�fà›¦02L¯}B� �j± =¦œpˆÓßx îù>ÏeNÂ'b“Ó”Aˆ[›ä|슈)(¾Ç—ÏA 3à‹|þ_û”@æQî'L2‚Q‰  œ2R­�'¡ À/8ïo¼à]®[“° à&€çüÀס|*�ÇÚ�†ÔE‡œ6€4|"^„ÿZîÀ'âOÞÐà'¾à›PÈø;çÿ7|2ŽAù›OØ@9×Ô À÷Ïð}§¡„KžpÀg¡û)(?ÿðsøÚ³~Ïÿ%×ÿ<€_ø!Ÿ·9�6¹š�M(B"G[5Oú´@‘†êMû¡æŒ^E¹¦˜û/r£¯A9äãNø4Q¸`˜«,øʵA·=,„õ|Ê=�|Àe¿ Eú¿ Èù)€Ÿq>ÝÃuªÉhð;( û1€ë�뼿aœßˆª5i“�æÍ$âP$Àe(•×yL"t~íV¡4á]#ïsºáÑ eÂüB%,×B í(wÂ%(¡êÅhkðµ@ W›Ýó¯ø>€Q(¿¢µÀ•™P"Úˆâ;" A WŸâl7à÷ž ðõþcðÍ–&Àât‰…2EÆP ޾+9mÀ7M�¸ž?s™fTd¦û Èú›Smv\¨i@in£¹²6ª‘‰ƒSp¦fèr¤q>¨5z+BÙýöÀy“ ›ó¹|¿éÈ+‘QÖ\”�*“ …þ,×¥£4mó+ 4ÿÉuôq»Â44èˆg’CÍTU" Ǭ…ašÓ_èÆI/A™²0­Ñå·³Ì0׌°‚>C @oY#5IÐf'm¤’ë3M�äý0ÍKWW`óx³á“QqE#t¯ÊÌ�ÚçÍ¢²“6IY†"b'­Ñ&ê0üñ€Ö˜ ¦�ÌôAë(·ûš³ç÷@9éJ¦ÆD°—ÛðCb-pË8¯�-øÚ)Q> SVX(X‚3¢•Žïñ-}PN[;ºJ£êTXzÊYWÒ Mà›Œ ±A2´°ô8!Íé>n�ÞÌPÓ …ÓF0öÍ1H{@vÕž“J)¶‡µ6 <bê´þtD; %cì·Cõ¤ üwÌ?0?rJó¾ö+)ÀW¡4)H˜IœA9ña#ì°‘öa”÷Zs²Ïåg[†U›Z IסÆ&ðjÚc�ϯû«¼ÿÀ ïës+–‰h~˜»`Ck„9ç¢�ƒ#Ñ'\˜°NS¼ÿ&€8 5ͱŠrbÍýüð·±Ýܘò P¡íÊ_ Ç•BÙÓfᇧA3¢·ç¡æÇ6à“ô)šœ‹\Ö_¸íA¢6YNúXï¯qªe¸i”ë †®âxç�wˆ¨Ãó¼âÝ»wgÆÆÆbŸ>nòù|g©T:!¥t…·‡††6Y~CßY‹Å9!Ī”2;<<|¬‘e'‰©©© õ@©TzÔh€Ö59Žc ôQ‡mÛ[î?’¢"ŸÏ§…G\×=q>O,ÿÑ”ÏçÓžçõQ­wvv¾××××ò«©¯_¿Þ�Édz+]#¢GFFÞ�«îØþ,Ëq«¿¿¿OJ™5ÏÛ¶ý0—˽ßjþÃqëäɓۖèoll,f2™‡††–ã¬?6"4fffº¦Óé­5F¶mßü îºkÁôôô1!Äa)¥;<<<Ýìúc'ÂD¡P8âºîQ)¥[(r­¢:""zoddäA³ÛÐÔ•~¹\î�”Òõ<Ï>Ô̺Ã`FD‹I�4™ˆ±±±’”òxžwÈq«Ú=qÂqkÿþýýžçÙBˆÕ{÷îÍ%Õ–¦¯}m­Ða¶çy6­ß¾}ûn’¦²éD´ŠVœ8q¢›ˆ:¤”îÊÊJâ³I¬/ÓŠ���þf“á8ŽeYÖ�R>8wîÜZµ{âF"DŒ��•–––îJ)]"ê8~üxo3ë?qâÄÏól)¥›ËåqÎA45| "‰°±BÕJHD#4†††–mÛ¾–e™ššÊÄYŸã8–U=Ï+¶ @ÂDåþ¢³³s°P(©~Wí0£$)¥›J¥æâ¨§^$NÄØØX©P(ä<Ï+€ëºGãpÞf”´´´t7Ž©ìÝ QÄ­[·ú¥”Y˲î4z’MO¯´â<Б*-ƒI-IÄãÇ�>¸"¢"lnnf«åM-E„mÛˆc€•Ïç×@ÑÖè²�–!‚ßêÙBˆÕê¹k‡9…‘Ïç;ã¨c7h"–——³€Šï㪃×ÁuÝŽ¸ê¨-CD[[[7¬¬¬<Š«ŽT*U"j¹$h "òù|§”2ëy^1Î ¸b±¸ RÊl>Ÿo©è)q"DZ\×í€T*u?κæç祔.!ºã¬«VHþs©Äþjyxxø˜¢�ˆb_)166V*•J�`ss³%ˆÐò—Pë9/&шéééc®ëB¬Þ¹s§)£Ý;wî| „XB´Å5¯U#.¸˜ØÍq¬%Ý ù|>MDžçÙIOyhù7ÝG8Žc …MBpCCC™LfP“Œ…B¡'é… MÕˆ™™™®µµµ^=½´´t7É×”æK~wýþÙ³gc Ÿ+aKþÍ bff¦«X,ÖË/…«Åbq®ÞçóùNÏó>Åv!ĪçyÅ'Ož¬ÍÏÏ/ƽ¨ v"¦¦¦2ûöíë¶,«Ûó<P½NJù Õ¦¡DZ†‡‡¹®{4x�ˆÖS©T±­­mñÆ�Ë�&¦áDLMMe,ËêÈf³�›››Ysr�æQ.—{�ô²•�à8ŽuæÌ™ÎõõõŽR©t@k‰†”Òu]w-�N‰¨!¿“hæòûJ×mÛ~X,—›mw‰|>ßéºî)e6øœ�0± Óˆ\.7¢�¯ëºkBˆUÛ¶ãœ%Sëõ�WN�:uc7ejùïú³-SSS™¤C¿$à8ŽÕˆU'[ò'‰Év¯�Ô¿ôñÚ'ùü…äš´gq�ÓI ÿ;/'Ó–= -ó[Á/ Tý8ÞÇh ÈÿÀ9‘þŽùßG ž–Ýñ£~pÇ¿bÈ{<˜á2Õ�§÷Ó‘»D@¨µ¢ò)ü4ÕМï1· (üûÚ;á*>“ó?Vd§E7ðôÏIEND®B`‚ukui-biometric-auth/images/Face/15.png0000664000175000017500000000776715167732630016460 0ustar fengfeng‰PNG  IHDRbb«¥¾IDATxœí�h\ÙuÇ?÷ÍŒdÙÒÊo²±³Y R±¼+§qº¤”4¥PÐö�˜Ò?jÚþÑÜ”ÒB[ª MKé?ö_ý rú+E¥Ø…B )•BŠèþáZ^1PB&|÷ÄÚùnAD®ïÉÞ³qãÝnØ“WÙ/cŒévÞD8ù»Ý�8ĺu£ [V¬‹šÞ0Ƭ¶³}y¡'4B�„³ºM¶¹øàp­IÙ“·ˆ‘aààeö÷x×›]:ßBñ“^êö�IcÌû-”—œüqþS‡+öœ„5õ¦$m¶yðúÜGF#L¥×Üã�ÈC¹;ïÏ®¯§õBibn”_Iq¤‹¨;¬m™R¯x¤Å±œTî¡€DãÃeïÜ´ž[“Æv<“Kêå–6WóÌiºÒ™ÇÃûòÌë}ãÞ¹qÑw·&]L‘öÍ94ï> :tðÌÒ­”kY&_sÍ Ë=Ú²Î9$ ¹A�WÁªWõðå„,g±¡éFžSh+4x™dŒ¹­m¨ ÏteikËÈ�"^Iy!3J6�¶ðBg…loõæÓœØ{gâžãF“mè>$šI§Ö2Úññ$³–á¾)ÉJÑñ'u°ö�å´çhòÒˆW4½šôFL{aU?Ž}K×,ÖõÞFX¤¾yšÔôF¯½Ùk±¾ºCÚ,¸™ÛRP.£Æ�Äl¿çÇÜìC§n`Þ[A!ÑRÃaõf~�œ¿,ÐöMj»œ;½îu «DÚu¸Æ‰&Jþn³·>²åZòÝÝ«Ú0¥öMìlúr¼çËþÈá™GxBN YÌxêîÂëjö"¦JÞ­VL“39Z×°WÞe­kÙ«÷–ßiRÊs&ªéw)YÑö%4"�—çhžQc̪ þlle¿ êLDVœ%2‘δÌcÍá<°è™Íimï—ë´wDÛ³nŒyº‰vdFÇWú©¦ì BÓUà_bùæ°D¬c…�Å rXñö_6Æ|³õÛ6jÿj¦ M¡K.3¹¤Æ˜ÏŠˆ´ÚUpëH˜ÇºÛ©Ñ ä9³NÃ(͇,ZÁ 9öàvãq&¢Ñd­§Ð "z +4·Ú<<Α ê,Œv»=K„d�G=ȃˆuØäAÐjÀ¯í�hÑÀJ^uäA煉9”Ý-ìÅÏòª #DhÈ¡'× i»æ5¦4%v¡@<Ò:©éá BUø’Nz—&�kbWWœ^îbTàóØö-b£ÂI˜×ôFI½Ùÿ·H‹yíus^ÄS$úmŠø*À‹~Ю…öLiPoÂ;7î•ë§!Ò`Í’DÁÊÌk¬šAÛ‚~ÚÛ�c?üb�|{A6/à7é¥+ØÞéÛå«ñr2àÑ€¿HÔëýÀßmÏ;«ûn\;ÄŠ–9yÐøUm‰5i#]8!M½k�ðSÁŒ1Jôê5+V¼ýEì†DÁ)4Z `Œy_D®j[.m%¢-�h±@–c%Ê9‰Ö«¶jš.êý�^>�42K^^÷œM/hh„nLèVÈ6“]ÄFO[}i¿¢÷7ZŠ3JÆù�§Um�aõ2EÏL³ ]D¸nvÎÛÑÞ7y€6e]I8IkÕ·m!B—/œÍhÓWÙî^Džsˆvš¦yM“ֹƱBD<“d׈IM³æÏŒvqMÓW2ôœ²¯Mmu K‹œ�kÞöPGÛˆ0Æ|�Ñ8pƒüƒ‚ k7ÿɲÈY;Ĥ–ÙÛ‹Í4„àB©s/OÝy‡ä¸ÀLóLdœûø‹Ì2½ÔUÈþ=Iût×ÿx°&Îäå›–Ö×¾Ö[‰>,ÑgéDèdoÆkëáútKÀ‘±,µ_‰^”è³ÛÙÿE©ûÀЈȗE䚈<#"}"rDDt;Zg;/"ß‘/è=}"rND¾äw’xÛ¤6péãphB²ÿƒA3zmFˆHQD>'"#"+JÌß{÷üƒ’ñAyV·×Ù¾£÷­ŠÈjº*"&"?/"ϋȠæù¸u"…€}ܼ�Û3 M|V¢wέ½¼|ø]`(`úÛºø%¯¸Ï?–€JJ•ŸžÒýûšÀŸj}o¢Û.ð=÷Ú†?Ð{Ö��!Pv�1¹ÿVIî?'"¬p Àüpø4ð–^45ºÿ Xx|+lk»^'"àg€_Æ’ù&Ž~~ ø1àõÞßþ\óU±„ìºÔSmƒXj�‹FˆH e±‚uéW�_†±Bþ0ü�æ ØOÆ«ÀEÝ ø>ð6ÉD¸<ÀkÀ†ž‹“P~ø à“À_ê}ÿ| KP @("»Àm&¥­DˆH(aéÒ¢·í üðEìCÿ8ö}„#Ï'c8‰5‘À“ˆ+d€ÓÀwI'áCÀ)à.ð×ZþëÀWH'aÇ;±¤„ÀŽ1f·u©Y´ëÅ�#À¥q2üôŸ°½ü)àyl�>†íñþøP%"¡ ü4p؈HHêýñž_ÔÔµÕxi€%äQVíhŠ%¡�HØŽ·¥âçLÔ°^Ëo? üVØq2 2_Idøø(Ö=vD8JXÁŸÂšD€ÿÐ2Ž’<¤õ|ÛñÚä»Þö—¦e;2#Á|)¾ÉJÛ/a=›o`]ÉÏcÐOc'tßÃjÃ[Xsã<§$2|<��žžÅsKè×€ šï;šïû…_¯çûND@형Ø&±«Dê’‘iBç‘'À'!鸑֔°þpD«[ ÿ9བ´MÝi‚ÿ ÃØIZöºÞ÷VK>�Õ®mìn�h ؉í?JØäå{KÝ~Zžºfª¡Fx³3¾©I:nDP\k;>ü,Vø§�[Xm(b'gŸN`{ëÓz.Ékr‚üo¬7䯄PËý€ åßôüµ=ß™š@÷ã½¼^ç•Øæê/¢_>§M³˜&ßfŽã„$ Ò�øWì,û$ða¬ûéî;7pä$™(€ê~«IŽ„;ü/V£Ž�<ÈÆËt�ؾï�9�;¹øÇ¢q*ÐýÔ%Bµ!ÞȤãBì8iþàòÅ ó q_ú‰4g+ا‰zXœ ˆ<¡!jç%Í3„%!©·C}�»ý$�'?X¥¨uk� <Íï?¢Û ¦ºñÒ~Ýï×íˆ ¯ß²/Ô$Íqd}DïWÚ'¹O(i€„ýÂôgÚþæ³Éþ0F|öìÛx76l�îxKSS÷bÍã–wn¼teí¸}§NuðŽ“&A[ž€]ê÷Þ$¯©Þ,;îªþœÖÿ-ök�|7÷9 {òï÷îÝ®T*ÏA0¤umV*••n’àP.—«ÕêGEä¨k[µZ­<|øpkuuuýÂ… ^*S¹±°°0pìØ±…BáDµZ-‚íuA¼ÓM›œ„ÙÙÙ™3g>†á©ø5Ù.•J•þþþõ›7o>h71m'baaa P(ÜÙÙ2Æô{•m—J¥÷îܹóNÞ=ì ˜��-œ;wnp{{ûèîîîq§%A„anõõõUDä½vŒmm!¢\.÷U«Õ�ÅìP,ß­T*:mwÛ‰r¹<†áñ †âÏÙÛ6�¸sçθ|Ã0Ü2Æl‹Åõ^‹n¶¾Ö‡aø À‹/¾xó e:ùøo[ºíúu³³³…………�ƒ–³'Þþ¢Çb?ØÑwÒóz~²{Mzb1©é|@ô-ræŸ÷ù!Ú'óÅø? ¤þßÎÑ^Èþ'GÜÉiïäŒÂßÉ8,�ÚO†§ã®Hë8\ß·1¡6‹äO†%ý/h¡3ÿÇ܃�ôÿ×®‡šO†ÿ'ï�ʼnG�]IEND®B`‚ukui-biometric-auth/images/Face/18.png0000664000175000017500000000671115167732630016447 0ustar fengfeng‰PNG  IHDRbb«¥ �IDATxœí�Ûo$GÆíõn6âå"�È"áò€ ˆ(BÄEB\¼ˆ¤ðŠó0‹xà�¯xà�/ l.BHHÌ .7Ù�<€€x°²H²»¶÷ðP§¦O×tOW·g<3ö~R©º{ª»«ÏWçÔ©ÓU=` "ó"²*"mM±Xç”BDÖ+ÈÉËuUDæ‹.تpÁ»ÇüüÙ9‚ÜZáÅÖÌ�mY‘¥1=Û‰…ˆ,©lÛFÞköG�•1×õÔ@ ñX²6îÔÚùqAD6z²76naÜ;m‘•ýN""�$I2îŠ�FxùÏŽ»"!Ĺu�œ‹=`[óÍ$IžfýF…‰Ðu55‡|ù.p¸2‰¤ôä?."Dd¸\$Ûâ}köy§Æå›&÷ÛÛ@3I’k5®72xùãý§c¾ùœqvÕ{X–¢ÑæÑïçÇI;“æ”ôäÜD( [zÛ ÕŒã¸¯'cw’È'[u¢3�4u ˘AÔÄ�1"ŽÒ*õœ�aqƒÓ�Ñ�€ŒcÑÆ’ú/r„PŠ?7¢ÜªøØMy9Qí+ã ¢íû…ç¶D¤Qn)¦œ–ÝÑú´ÊK�ÇJD  •=#5i¥-]ËF=‹¤aÿ±ö–ˆñû±Á­þßrƒ�⼫%ØŽ¦¶ÇÿÛFëÖ$Â6åwdL&ê8äooæ±_‘³¿ BôÂnKÚÁ/+1¹ÂÕß–”ô¶æ»šÖEd9¸ïª’½kÈXSâ'£*$�0ö±®¾¡ù®ÆrP.Útª [f^…nÇ.+"²eêçÉ(Ãrñ�'’z(Áq;ºÞ(j…R¡.+¯¤xÒEÔÖº,+‰k†´;y×� HÚ?¬šc-=¶+åv<Ê%5åç¤Äæj™¶Ö¡Ô•–Ô…F¤|zŽ–i$Iò´ ~1H ².¨7±X$5‘Þ´tpæ°l³ÙÒú~v@}çµ>{I’¼¸B=¢qì3ýTSz‚Ðüià[A¹6Žˆ=œb¼ �®Ù¾˜$É�êרÕQÛW•:TÂ8¦\F¹¤I’¼KD¤n TÁíE�ÐÁ¹Û…qåȺ ª‡,ê Ë[ð°q’‰(¬MÆAĤ¡KµÙæ#ÁIÖˆ(¨³Ðw=&–‰�G�Œ‚ˆ=è ò(¨ð:$�4ÐÕ=FADGóæ®=.ôâg£ºÁ±¡!‡‰œ+¤õêhLiYÜD�0ÒÚÔ|:ˆP~Tw›æ§&pEÜìŠEàâ$£ïàê·�‹ ç¡£ùfI“É.àÉy1¯­®m"ž"é·)ÂY€+6hW£>ËÔ[2ÇÌuí: ‘’9K’+£çXUÁЂ~ÚÚ/à ~r@¹^�Íüš&ïâZ§µË—ÃëD`“´Ãß&mõ6ð÷„ñξ×ÑÕk6�¿ 1”X“VÒ‡ŠÔ»y?Lƒ”ˆé«×XtÍö6nC®à” Ê&($IrMD.k]†JÄP éd�˜ c+1cNÒùªuMÓŠž_öòi¾Ì,™²þ9+Oh(Ã8t]âF²Û¸èiÝ—ö]=¿l*NƒÈñ�Ѫ¡Ç°&™ˆ£bb„1þ�KÃα±m}Í#Ô)v&a“z‹ê‡Š¡¡Ó#mz·ÌvO"F9†¦iêhž7Ï5D— ˆx*šÄkDSóØòÑ&W4¿ÑrºÄÏM­;…e“œ½k>ôPÇЈH’ä+èÀˆòPÀ&£ –vÖ~ü3ÉYDS¯9Ù“Í4„àC…cSfà¸CF8ÁLË,EŽ}ì$³èÕKc…d?zR´t×.ì‹3™r-©?÷uÐLô9I— ¡ƒ½uS×éZº¥àÉØ‘þU¢+’.»]—ìŠR¤kI�ÀŸ¤ÁÅåà˜]]ºÖMú—Ó¡ !$»`Ðb][·'ÎLxáx’jµDIW«îHíõD÷¾r£eüϹ2Ü©…¤áh‹–Ï�ÙHj:<¼`·$ýÂ@˜¬¹³ój—$gÌ"ý‹íýÊÑ“ÿUg –õÚYP>øg^– ’]×°¢$ ºöš¨¦Iö[!'$ŸHö“ -qšRøàR!2œ·"%æL‰Z‘¬G4²ÙÞ‡@+Ze/R}Y­¶ö2‚EsOBí�ûT"Њõ2›,#XgmL—õìN RamšD|.çœ�×Us´aê0ö‰ cA M‚TÔÅô+a_U¥î'±�¤Tÿ:MéŠUÉ~äñô™¤á6Æ´ð |®‰dÖÒ ¼ç©DÐ_,hŸÐÖãþ{JU>œÕVaÏk§¼!iÅš¤‘ÌOª‹±ÿU�dç �{¯Ñ!�ëÔÐã›ZΧ<,’N½¹€ Ëošs;ZfXœ¤�¶��è‘aßQ\ð³7ô·+è{ÿ�Á:Q-²š!¿:µi^ïÞFIƒ„KÁñ¸TPnUŠCïÞN¤—4-K·:¸‰ eb>ÕÐF…†�‰ûGÅžˆ$¸†’Ï�×EäN-“gV¿ "w¾ƒàðÝoŠH’$ɱþUCÆÞGˆÈ Nà3À³¸V}/) >OÌ>”×Ýà·_<¥û€CSæPó[I’Üb 8V�ÐV~'ÌYÍÏhšÇ èIœÐ<9!�%¤·è× �÷?# ¸%"~ÿÀÿ~Ú3r"DÄ Ú§YòÉx·žòk²D„a“‡'Å [rÒ3À«�·¿% ÁìØm%çGÊH4f$D¨¹™%zQnÉø¨žþ}œiò­~~Û¶Ü<"¶qD¼ø†óÏ%A·{¹’²Ï�I*"2 œÅ Ùç³ &exx;°ü¸G+#Ã#†ˆCàwÀ€·ê½‰#aßìàH9ö“$9¬)²†µPÅàó�Œá›´¯ùYCÈAUÙyÌúРåVE( À ·­fxR CÜMj®ÊÈ€,!’“[ïH€ŸâLÓ{p+•BŠ4ÁæûZ{ìL éÉßÔªü�éÎQLDHŠÕ OÈcÀqË·>Ü %¡ˆ ïyA¿f@ª·r¶�;€O÷ß6è'Áj‚où¡&ìçlgRŒ·Õ“U"-ðDœ#¶ÝÎ#Å“ñ1à#¸ÁÚç€kd=«22¬[›©"YúÆ 8ó÷8p'ð=໤ [x¨ï¨LD@‚|)ÖdÙíG€OwáHøðOwê1ddªJ9 >#ð!=ú9Å-ÿfÎö¾Ù¶dd~/"£†„�KBÞ¾ß~x?ð½ä3À×�‘Õ¨° =¬"22Õ%ŽonîÃ…ß_¡çÿ øðgœ;ýò[ûÍ ÷ÛEerÍT4Ú1Û¾à\°æ>½JXÂyBà´àÇÀ)ÖkÊòÆ –ˆ°�]Ö<òlþ ðfà9"¸ üø.ür�~2ÏÙ·š‘V!¢ˆ€pÿMÀë�·èC½Ü\æßÀ/p®ãùt¶ Y78� «E$„^OQ';¼xð�n[<�óðž~ü•Áô MT¤#YÛ žQ!Ýar¿}x îë�‘�'�?âZ“%0O›BBò‡yfÊj…õ˜¼i 5!$¤¬Ó½×—<€s4,ž¾ üAËÞÐt3È}º®¹­ãdGÖçÍÃûü¼¦{4¿SÓy“? ç_Çu¼W�¿hîÿp ô¢ÁŸ5C6Í䤰³.iÛ>£(¸ŽžCR®âúŽó8Gã%¸FøZàUÀKq�ý œÖ¼ òxN·ý±ç€ÿ’ö{6q.xPß ½&œ%Õ+ÔÎí;¤Ø´ ý ùÂ÷grò0Lno[\a(#Q‡Ûy& %æY²&è†!Ñj…ÿí:Ùp²q×ÔýG”CÌä¶Næ§ß¦MÍ;3¤k‘£?ïsCƒ—ù¶]+ RqÖõmÔ‡dNÎûƒ-sp=bÚÊmÔ„ô/n…Ö¤>¦kýñµ*ò— Kñ_Дáä¯Ä,€ÿ¿ö ô-þ?8õX?2²ŒIEND®B`‚ukui-biometric-auth/images/Face/05.png0000664000175000017500000000665315167732630016450 0ustar fengfeng‰PNG  IHDRbb«¥ rIDATxœí�_lI^Ç?ÕÝ3öØ3›p^’KHpÎgc{ãœr‚ì÷âîᄱ+�ÄBwoðÊ <ð´‚7ÄÃÂ#�ÐH¤]@Xò‰@¼š™È9ÍnBBVëK.ŽÇÿ§§ŠÂAñ¯)Däƒç�“‘ë·Ed¼_†×Ÿ#Ã8øùsùìäv=žÙûÖ‡‰È»"r-£g{e!"×"Ù~dÉû}ûCƒw3®ëkƒˆƒk¶Ž{mõ|V‘�안|œ.)¥–2®ÛSˆˆ@YÁ\cÅ}³°â0ŠM•RÒ‚ˆÌ7�;JD@)µßƒ¥U-`p­´z/2à`D„VZè&¥m]·£8TJ…{³JFþÞ€ Ut„íѾ¹§€ñ(ü(p6 g¢,ÒXšÀ-à ð/Àÿ±·Wô$EÄ\æóAôžÔ{„ˆA›à±—Œ_f¢p%á*<þø{4)}I°®ƒéMJ¢=æ©üÓ "R7¡÷Š�ß¾üˆõóe`ø^ߤ[5õ#LÚ´ÜKQúRˆòût�1B7½ã@$Xq‹„HI…ñ€ZØ&öØKÊqàoÑ4�ÿþ ø X¡£²Ì˜`�qB`/&mÂoß¾® º 8 -ëÚ-¥TûpK˜‹ÇɰãcÀ_SÀlÑQS&¶o›�ÃÑ~ø`øàSz“`‡~¢Ïℇ�Ý‹чû^<íü8Zíüð¿t„þ,2¾ŠV/;ôWQ§�›¦Št� ?ü&šŒ?B÷À8 ýz‚ì{»¢‡¼ÖP¤?qR ÀïßB“ð‡À=ºÇŽg‘ñÇÀ_¢…çFU‰÷Œo¡[ú º­$ÛdýIà×Ñdý>Z5ÆI°{ž–oÅñtW8ˆµuhó5Ö E:¶Ó6)_�ºW¬#t�%ýȘJÀCà zOð£MßÛì�;TG[Qß@÷È?E7Œx 7q!víE±©k@§×Úó WDvÚ;ž‹ˆˆ„"a"LèGH­£þ ø.Z°öàn§ãdœG÷ž ý'x úš¬^$5tøY´±ðuàŸé=<:�‡–U§¸�¡"2ö;LDŒ[ð½H±UV˜f£¬þMB\}õÜ `(Ó=€ÇUS-\CD/ŒÊ©_Cò=à>û·ügyúYtˆû‘áwÐæd_X$Ø‚‹“ÐëÚ¤)Êj=PÓ!â—�¤›­¶N ;ýþ$0…8Z鯡Ußн¤—9ú?h5vø5àÏé¨([ÕØi»µCoË º­·H„"}ÔÔว”úJ�íŒz°ÕGÜ*²¯{òQvÿN÷¸2 |…1_¦ÑNÈ Úî‚î ßE tm¡Ø­tc2êèKÑïM¹Ÿ£gØ÷Ђþ2šè~mRÿ6z2¹ T£ï¶xöDr�¸Ø;6…‘, ]“@#ÿƒ¨&[gÇT;Øc…}mˆÞ¾Owoš@·äŸ. |ÝZW¬¼¦Ð­Õ”[d¯Š2–Q Mֽ螋&føi4)÷Ð&ô2º7þ"šŒŸŠêúNYüºAÄ­1#pS?ûÚ¥£":ŽÈ.(xêêå†( [k)ŠMzȺ6éb�tíbø9´þO:=¢ f­Û¿¬±w> é1ûëf¢ûEô$Ñva„Q¹#Q¾ ­¶£ß|‰ŽYlž3Ž'À_Óé•ÛQÚ[Ñ};6a3 q£ ez„=¡²[´vÙª\‰nr†,râD�ɨŒ5àM:½äl$$cjzÀÑÝëÜ(oEÇbê7ÃŽëë2½ÕD l­×"álÇ…Cg’v& kÀG÷�ÐwbéÍ(=ŒmµmÆ3)%’Aúk+++óžç/ W©TVàé‚û-FI´ÛA)u÷ eŠÈ5¥Ô¿%•¯y†‘‘‘�‡‡‡o´σT‰XZZ:¡”:«”Ú|ûí·o¥YVšøä“O.\¼xñFZe8ûåpXXX()¥Î8ŽÓH«œ´±¸¸8 ”ÚÜï»/‚Ôˆ9 àyÞƒ™™™Ý´ÊI¾ï»£££g\×]M³¬Tˆ¨ÕjeÇq*ŽãÕju%�2�‰‰‰saz"²“ös¤BD«Õ: à8ÎÊüüü¡M²Æððp9J®¦ý‰Q«ÕŠŽãTDäQÒùŽã¬¸®;æû¾»ß÷_¨¬¤3 ‚à8ÀîîîêË:6T«ÕÇq‚0 ½©©©Éýqx$N„ˆ( ͤó4æççÛkkk·Ç Ç©Ôjµòþ¿:'¨¥���—ž€«W¯nµµµu2­rR3_¯^½º•VÞƒ†ë¬Á;q¤FÄ«3Ö…a˜ÚÎÈ#"r‚#"r‚#"r‚#"r‚#"r‚#"r‚4&tèõˆ¤óÎ �F〈ì¤UFâDloo¯ŒŽŽV’Î;+ììì˜}_©­I$N„ñ1µZ­W†ó,žç½D4�cŽãŒAºî€AÃ4.™LËž‹‹‹c?&"#A¼2¾¦éé點ç=LÓžfm×ó¼‡/^¼qéÒ¥T¶�d…jµz?Mwx"Dø¾ï‡XµZ½ŸDžyÃüü|۸ÕRcIçŸ333%€0 ›/óõ~‘&@»ÝI:ï£ Ýs`fffÀŒƒI∈œ "ž>þÌc`/3._¾\†Î³&‰ÄˆØÙÙ1 ì§^Õ^Ñl6O(¥wu$FÄ•+W)¥6•RCSSS©¹²‚½Ÿ7 ŸS¢VS³Ù¼£”Út§2;;{fÿ_¼XXX(‰È$@»Ý~”ÆÆÄªø¾ï^¸paJDF<Ï{8==}à“>yC­V+*¥NAð&h÷MZϓʉ¡Z­V ÃpRDFDd§\.ß›œœ|’FYIbqqq¬T*�ëõ™ˆ|177—šû&µ£[¾ï»SSS“f ¦�çy«Õêý¼¹B|ßwßzë­Kñû»»»«¥Ré 3«N ©fl4Ç?~üf±X|jÖzž÷`zzúó´Ë~,--�QJ�t'˜��øÛ>úfËz½~*‚ÓŽãõz½š—^Q«ÕÊívû<€ˆÜ›››ø)§�úšìó³³³'Yv?ØÑîîîj$À€‰°}úažÈz®áû¾ûÆoL…aè)¥6?ýôÓ;YÕeàÞ×¼ô cf›ÃŠ·nݺ�¥ª8yéçÏŸ‘Çq‚���FÖãU&ëv¯¸páÂÔ Éð}ßu]÷è‹y8T“ öÙ4™˜˜87ÈòÏŸ?* C/OçÀ3y1»AfcLÕ^Èt©tfffÝó¼®ëžJ{¿¬ïû®1UÃ0læ…ÈÁšµ=^”Ëåéz½~*�rl+Éqœ P(ÜI£œÃ"s"æççÛõz½jV½‚ 8�Æàm[Ikkk·óv?Ó1"Ž›7oN9ŽSq]w9i'›q¯äÑÏ9è ˜uz!—D˜í9IÂìÒËëq�\áy^ ÒykA­VÛPJ %�wÈ Ѫž—Ö+ÛlFš/79,rCÄúúzÒÙ3d`ÎÀA�øÞÕEnˆØØØHíe[ÖÉŸÜm‚ËfÏP†Í4pÍfsô«ŒjµZ®¬§Ì‰ð}ß ‚à@¡Px�fYwïÞ]5Ç�Ó8lò"p¢ÿ*ÍìJgggÏ(¥†D$õ�óóóív»ý Õjå‚#x/ ÇÒÒÒ™ ÞTJm.//d¶»¼¼ü¹Ùš–_ë9ñð^fÿUjïèPJݤï§V«EäB†^Ö.#ÿ��¾ï»õz}Ü��…nfff·T*Ýíd¬×ëãYodh�h4Ƕ¶¶ÎWôÚÚÚí,—)í-–ÑÚõý+W® ô]µ©þWi�FãX³Ùnn^·n~ðôƒ#$ލá`Éûzü ïËá‘ÙzFÖˆ õyñ~¿L¯‰È‡‡Èðñ€Ÿ?7‘Ï!¯Eäš�ÏÿþóÖŠÝT»-IEND®B`‚ukui-biometric-auth/images/Face/08.png0000664000175000017500000000756115167732630016452 0ustar fengfeng‰PNG  IHDRbb«¥8IDATxœí�]lYVÇõѶÛIv“I&CX‡ñÈ™Ø&ΖÀ°�€FZíh¥,ìÈO,3/Ì OBH™7àiF�T/YÐ"�”̆ ²I–nGxœ0ÙùÈ$±ãöW»«ëðpïMß®tÛm»ª«f2éêvUݾçϹçÞºUDdXD΋Èe:Å;<£‘w¶!'#×ó"2Ü.à ÛÈ0Ž….·?7‘ù]ÈíB<³‹ÖÅË"ò†ˆœÉ¨mŸ[ˆÈ-ÛË–¼/Ú Þȸ®Ï 4!gl÷ÌÚù¬ "—žÈÞ²q“YWìYƒˆLjÙÏ;""Žã8YWìY„‘¿ŸuEâåÖm:Å"pCÇßsçn’õK ¹Ðí$œÔálÂÙßÞÞÍ#)OäŸ"²øàÛ4÷xÓ›M|eÙŸµbóûpÖqœÇ;È/5ùcü§.¾×r´÷pNÚÍ6w_ž™'ÍçÍ)y"ÿn¡I¸®‹½¤5£å2òDF–D\߉@´ÆlJšvÛ¦±&Q¹!#"vÓ+õ6]v59Ýtu FFW´q‹út—ÙÅRŠùoé΋Y»Ù:�híÌ”Œ,ˆ¸lÆ…ü÷‚ˆ\î Ý™NÒé´óº>¶N�ºJDL¶íi“¶eO×i;j‹4–ý3/l"æ%åû b/n=}­åb£(ïêŒؼ—¥ýúÿeKë.Jî°•~^22QÝ�¿]˜Ádìü9™·Ž'µ�°/Kc€?§‰i)\}íŒ&ý²ŽtxGDÎÅÊ=¯É^°È¸¨‰Ï…G•(¤±Âøëºá—t¼` ã\,]ǦS ò‚u<¬…nÏ]Þ‘ëVý [á\û’six(—bçíÙõ¥x/GD<ùU¹""="Ò'"EúÛ„oˆÈ{Vº>ýß‚ˆŒˆÈÛ–àÏXu9§I¼h‘Ç<ŸUHc|8o�» Ï-ˆÈO‰ˆ¯…U‘ÒÂÙ'"¿/"!"Dä99¤Ãóm¨ˆ,ê4Ïép@Dö‹È—už_‘è:ü–.Û·MŒyLíæY7–ÁÏêøŠˆ8€üð!ð]à°psݵÂA ªÓ˜…IG_k‡½À`Lš‘Ž¨ÿ ܾ§ÓF@$"uý;ÔqxSçóîvß)R%BkÁ>à&pÐeÎßþD ßàÑ´ ü"ð—(a9±``H‰t| øà¿hß&At�^Ã"A_3$Ø¿÷é|ÿe—"i‹TˆÐ*þ3ÀÛúÔoÒ ÁÓñW�ÿD ÂÕçŒðm2ŽK44¢æ·Ñ€O�Qä·"!îc4ˆhGÂwtžÿ h�©uÇq ñ»F¢DˆˆP‚4°?G™Óó _þ‘AíÈ8 ¬°="�aýŸV$˜ã›¨1Kkú�?Òyþ“®kh‚ˆ„@ÍqœúNäe#",L|ø:ª'ÿ ª ’|àkÀïò´FØdŒ î° Yç:!âcà—hÑŠ„ø?`5^ìð§:�‹"ÆQÓqÁ"$Ü‘Ù%-0¿O'ùkTƒûõyF�9šµÁãi2ë4´!N4bÏ7†ôÿÚ‘PGpø7­øgu^?ÐçPÔt[kú| ðv£!;"B�>ÐÃÓD ?¯“~(Z×�VÐÐc®âdœ@ ìF# žÎ?® „ý ŠìAZ“`LÏ”Ö Ò~/ðXÿ=ðÀ·PÓ¢Õ–šþZu7„ÔP„t<Ý61-0DôX|M'}OW¼œ^@y1#À¯¡<¦~šÍUœŒ^” Íø7M温Š4¼§=Öqœ„¥m/Ï¡LÔ/èãßF‘ù}Ô=õ!àÏ€óºn5«®†—f×Û‘�Nµc[DhzhÞaBðªNþ# Ï:ÿuÔ˜`0ü5ŽáRÌñK(³a4¢6Lᅦ2;ð4 u�çA”#ñÇ:þwீ5T �?Dmr˜~å{4k�=j2¡šŒ-ÇŽŽ‰ˆ‘` >NÊ)ý—2ªG÷ÿ‹re{€·PsƒUàO´>FõÀOuXE™¸~K4{SímP$˜1éÊãZž¾„ÒÌ:íÇÀðÀ¿¢„êÐ0§5šñ:ðë@‰æž¯ËSu¶"£#",ìñ N‚ ?¦A„­5‡"âm`e~% ¯‡P&¥‚êµÏé8¤µIjEÄ^”àŸGÚƒú#à}”àPšñ5]ž~ÜÔx:ýëÀOë6-lå¹™:ÄD(²™™Ú’k`¶Í‡!¤Õ±�·M�9Fy+k(Óµ†r#?Šå÷M¨ži°Yï3¨Yç~ܧ1Ód< e²úh65. ©è¼hîlO‰+Œ9ôi�Ñr؉FØ6;> ÚÁÐ N�!dµv´ÙXS@™Š×Q){ü°Ýݸ+kOÞŒgS¥y"÷v>Ei¢!:žgšm ÜÔÏ>öh8 . G¢ ›¡µ!n[Ûçì ÛD™tPî¡íyÅMœMªíþÚyÆÉ€fUP½ÜöýmoÇôö‚Ž{¬<°~Û^4wÄ­ˆŸs•R<íÖúZàv#í¸O‡Auè³â^ý»WƒW-ÁöÒW^ÒÂ{5V^+Ò@ þn‹7MífÚhîµñu%5¸‹f­©¡Ìb¨cƒoëã*ʬVc¿Wõïu”£°f�[–E¤JÃäV� £¦rXÇñIкÎÌ Àö@lm›¦Ù‚. Hu�ë4÷[»LO?‡2QFðñؽ•Ù‡�®[mŠbzúk(×Õ�cÏ®Møe�¶Lƒ$›¨ª>¿n›ßk:62¬Yùšz%‹G�½õèÑ£·Ú]uë²£�²‹çøô�¥Žî=wRÎVíÚ-_¿wï޵ͮogk¼ã8ïí´z×÷ͤÊÙª]»Åfw¹v–¡ë†ÓÓÓŤóÎ sss{´mO‰±¾¾¾ 0000”tÞY¡Z­š;t‹i•‘8…B¡P«Õ>7D˜¶ø¾ÿÙ bnnn¯ëºûúúú“Ì;K˜Î%"#Ax[¥ß #âêÕ«ûWVV^‘~€0 ×’Ê;kŒ��Ýõ}ÿAEþèèèHe$FÄÀÀÀß÷œ8qâÚÉ“'o'•wP*•î¹®º®;T.—×öDˆ‚À‹¢ÈUá$ò̦¦¦ê®ëÞpgÒù'BÄøøx Š¢ÊÔÔÔ®w4ä"R¨×ëýIç�¸×ôyÆøøø2€“ÄDä‰ñøñã:€çy©¸vÏ!â•W^Y¥²iùÙy@šmKÌ4EQTÞ·UÚÏ*N�:5�¶&‰Äˆ¨V«úúú^µ¢R©p'ñ¥ŽÄˆ8}úôCÇqVÇéMm) +”ËåA×u‡\× ÓXsJÔkªT*wÇYu]whbbâH’yg‰éé颈ŒÔëõ‡ããã[ýg»HüÕ@AxÇ�‘~ß÷Œ��åîI�¢\.÷8Žs8 à–oÒjO*ïh*—Ë=Q�ˆz¸°:88øÁÈÈH®Þ“Ô W¯^Ý_,�¶º&"ŸLNN¦¶|“Ú˲‚ ðFGGG\×mº/áûþƒR©t/oK!Ax/¿üòÉøù���Åb±ø‰™U§…ÔßZ677·waaá@OOÏ·Ö÷ýÇÆÆ>J»ìíàæÍ›GÇ9äºn811Ñѽî$ÑÕ×ÇÍÌÌÃð×uÙ™™R^´¢\.Öëõc"òÁäääýnס«kM¥Ré¾ëºaEþÄÄÄÁn–ݶG´±±±˜ Ðe"ì5ý(Šf=ׂÀÛ³gÏhE¾ã8«ï¿ÿþ�¬êÒõÕ×¼h…q³£(òE¤zëÖ­ÛYšÊ®‘­8vìØ~éw]7\YY™Ëz¼Êä~„­Ç�í6Axžçp]÷¾Y=Ι155U_ZZºíºn("ý/¾øâÑn–ìØ±ÃQù®ë†¥R)“Á9ŽL_Ìž…Û˜Wµ2½U:>>¾ìûþ‡žçN{¿lžqU£(ªä…ÈÁ=k{¼›™™9œF9¶—äºnX(î¤QÎN‘9SSSõ™™™’¹ë†á i Þ¶—´´´t;�¥ìÝ Wï¸qãÆ¨ëºCžçÍ&½Èf–Wò¸Î9Ј °Ùã¹™!—D˜í9IÂìÒËëã¹"Â÷ý"4¶ç$‰r¹¼à8NïVi³@nˆÐwõ|ÇqVÓÈß^ÂHc7÷n‘"–——‡ �=Cæ¸0 ß»º[䆈ÞÞÞý+++Ó*Ãzò'w›àrA„Ù3EQ%͸J¥²  6É•÷”9Axa( ¦YÖÝ»wÍãÇi6»*=³8«ã+.pCüN6uy¦ad~ü‡Õ`[ß™þ;‡4>p.OÞƒ+�/%Š^–Ýö§Ž¿@gÐÿKÞâ .ÊΑÙýŒ¬êvÑúÝÒø ñvÑ�ï1çÒþûÚ›á’Ä^ƒýÿÞ‰�K®IEND®B`‚ukui-biometric-auth/images/Face/09.png0000664000175000017500000000750015167732630016444 0ustar fengfeng‰PNG  IHDRbb«¥IDATxœí�_lI^Ç?ÕÝ{œqHð*!GÂúp6±7ä!°‡H¡{B¹C' ñ²ûΟO�Ⱦó� !A–'PK(Ëi¹²´:¢$ÒÌ,É�ãD»d/Q‚½ÇŽ==ý㡪25í±gÆîžžMö+•ú_uuÕï[¿_UýªºˆÈq¹,"s&t‹k¼¦‘k=ÈÉÊõ²ˆß.Á+=$˜ÄRŸË?0‘Å=ÈíJ2±«ÎÅ9yWD.äT¶W"rÁÈvΑ÷U÷¢Å»9çõµ�!Äâ‚kã^[;ŸDäúKÙ;6n&n‘#ûE%" ”Rygìu„•�wF’Ý­;Ñ&t‹eà¶Ù~¨”z˜fþ²Â@h„é$œ5ábÊÉ?>>DR^Ê?/"Däð>ð-Zk¼­Ív{cÉ_t¶vÿ6pQ)õÅ.ÒË VþØþSŸ~Àé$,™ÞÃ%Ùn´¹÷çÙqÒâ uJ^Ê¿ßDn™Ç^7šÑ�çZ2–‰Œ<‰¸µ��Ù‘4ÓÜ6Ž3ˆ2r!b/µÒܳ£ÛEôàtGï@‚Œ¾hc‡üô—Ùƒ+ÅÞÛE¼Ëb}7�ã‰ÑÎ\Éȃˆ9Û.ìâÞ+"2×E¼ ÝÄ3qM~®tŽ�úJDBzî“Ö±¦›¸]•Ešnÿ\Û —ˆEÉx>A\çÖÖkm��¢{WŒÀM˜“íýÿsŽÖ]•.ºÃNüEÉÉDõCþîÃ,fç/‰È¢sðëÀÏ?@7� Ì£`5Áwö­ ‡ÍþM"Ü`aIqk3h"$, 1zNüÀQවᅵC·3üpøWù�„Ƥ†,‰øOE vÄœÿ;'Þ7€£Ðj¢ðËÀ?Ъ툰ûn»sø5àíI&�GÀ™íuà÷Ñ�¡µâ;À¿€oŠÈ M_#MRR%BDšfé‡À¨yÆmt}à/�o+è�€?F›ŠûÀà�h2îÓ4]Ý1nžõÛÀOÐíÌiàMàm`ÂÄû1ð�F ^h’Ð@kÆ5à»h3öCs-‘¨+¥= +�T–ІÐB_1§ÖœóÛlo¿t»ñ(£ Œôÿ�9vCÝlÇ�7e{MDÝlm¨+¥¢ŽÂÚ{ÒˆC&XŒ:ç'¼…®‰«h=î dÍSü9Zkhì£{"ÜFõo�»4ë†Ù/™ýáÄq”ØÖ�ôö›rÕM¹êN/²+"L—3 lOD‘V"¬6Öiå;[»ï ü ð§´öªlÏ ¶š(h¶󜟠M�KBŒtŒÖŽKÀ÷i¾%ÃÖ|·\–„À\³y·„ÔÑ„tí陈„X" 4…ífØ%Èîž¡k¸k®Ú‘­=«d;a�[²ˆðº�ÙoŽÛ‘™|ú&?n ·[+t·\u'¯–ˆä8È‘Ínµ£'" š‚·DØPp¢�°•ˆºíX¢•(?±o�¡IÄNd¸°&È6Ðcl%ÁmFLº£$l>­5ß-—O«¸c ›'½¤u³›¶£k"$¸‚O’b1ÌVóe÷=š*î�Ü‚®©É®m’Œ–¬š`»Î%¶’àn_?MÓö[Mh­ùn¹’€�ºÖˆ�È芇WpIlp3ÜNkÆÑÝÑ‘Äy—Û°ƒ¤k®Ú‘Ñ’]Z‰°£æv�°ÝþM Mš»ï–«�›ÅÝO¶ ""²“™êH„Ó0»æÃVòØMÛ%ÈF÷’Fت)nz?ƒ6aV#\2Ü™€ V°î˜À5;ZÍŽ59u'í:[Év+Ûq%‚ÕÄ€&m�Ýh„k³“ ª¬WѵøëÀçÎuKˆJ·Óš!š¶Ýí·#Ô;‚¶±�­¶?Yó¡YÓÛiÚ³}jòÑâ@¤)p›?÷اÙYðØê†sÆ”ìJÚÂ� k׈³?ìÛý‚Ùÿ_à$ðM Jk»R@÷bN_£•À¤Y*!¾í¨“mvá™ôfÁl7`í©;Á’¶ L›8ÏL¼ sþ…Ùwú9ïnmX‘5¶VŒºÕ[Ã’ý~+ì’CB‘Vr†r†Ñ#Ö“è‘òc#üƒ&ΆIwâ9Ií²þ©ÝõÚ„$Û¹<¬ã/¦•Ûn`„zÄÜW0ù¶ÂŽÐ£€ÿC›ÌMGè‰ý5³?‚¬ºå³Ú·á䱤û–ÐÂÂÂ�ñññß ‚ଈ,�ŽŽþ è‰"´jÙD½a¦*·…u§+¥þq7yéö~Ñ«K&N·Ì£lnnþA£Ñx[D–?úè£?›��ݳo)‰Ôˆøøã�‹Åö8ŽãÚÙ³g凌~Þ¨V«Ç£(:œU¹R›³Þ·oß1€ žž9sææ«D@¹\þÌó¼Èó¼±J¥Rê|GoH…ˆ0 ý8ŽÐN#ÍAÃììlÃó¼'J©Ci§Ÿ SSSEÐæ( û9(‘@£ÑM;í,—Ó¼r˜ššZ03�©â+"©ñÅ_4|ß÷;Åý í‘ ï¼óÎ:h• Ãð•%#˲¥fšâ8®?~<98zepîܹ4Ëš&R#bccãÀÈÈÈ‘WU+jµÚJ©åNq{EjDœ?þ™RjM)5<999ñª‘Q©TJžç�yžA0¸DÔjµJ©5Ï󯦧§�¥™vž˜ŸŸ/ŠÈ@£Ñx655µ™ö3Rÿ4P†þ©S§&Ed4‚§§OŸ¸o$u‹J¥RPJ‰¢è0h÷MVåÉäM•J¥Çñ„Y"¿Q*•>�˜˜¨ï$µCÒqéBDÏÌÌdæ¾ÉìcYaú“““žç�¹çƒ xZ.—?4WH†þ[o½µå ¢ÍÍÍåb±øØŽª³Bæ_-[XX8°´´t¸P(¼ìÖAðèôéÓŸgýì^pçÎ�cJ©7<Ï‹¦§§wœ+É}ý|\µZ=EÑQÏó¢jµZ­¨T*¥F£q@D>�™™yÒï<ôÕ×T.—ŸxžÅqLOO�w¾#{¸=¢ÍÍÍåáúôã8Ï{¬†¡¿ÿþÉ8Ž¥ÔÚýû÷ä•—¾{_E+l7;Žã@D6>ùä“{yšÊ¾1(ZqòäÉC"2êy^ôüùó…¼Û«\æ#\­8uêÔd¿ÉÃÐ÷}ÿ€çyO¬÷8OäBÄììlceeåžçy‘ˆŒ¾ùæ›'úùü“'O‰ã8ð|¸ìy^Ù¼l²x¢¿$ŸÛ§–§§§�)¥†E$ó•³³³�F£ñ  ^¯Vþðž }Ç�;wŽEQtX)µv÷îݾŒvïÞ½û¹]š•_«G¼¼—ÛÝJ©Oúéû©T*9Çq�·ËÃÊ¿ïmD†¾yUöh^¸©©©Íb±ø´“±Z­Ï{!C_5baaáÀúúú ëŠ^YY¹—ç4¥»ÄÒÌ]vþüù̺ÏíðRþý baaá@­V{Ã.¿TJ­Õjµƒ0W\©TJq; ¨”Z‹ã¸öâÅ‹õ‡.g½¨ s"æçç‹ûöí;äûþ!û¶yaüÉ ¹¡Ã0ô§§§Ç£(:š¼&"CCCµáááå›7o®¦MLêDÌÏÏ}ß+Õëõ1×¹f ó¬\.?É{ÙÊNÃÐ?wî\iccc´ÑhL¾Æëy^EÑz¡P¨‰H*ïI¤B„»ü¾Ýõ žÖjµÕ~ÛÝ4Q©TJQôk^Ôx!åº>2`B4NšcÜ#;Χ":¿){cŒO»b�ˆhœe?'ˆˆ@!Үأ-;íŠAʬ Q±à2ǯ !â¬_RÈ„F°‘pŒÃ©˜³Ÿð*€W³HʦüÓ"‚ˆöxÀóhìñº7ëøÂ6²?eÄúø2€SBˆ;ÛÈ/1hùCÛO.|�a$,²õ0AÍV›;/O¯“æ²f”lÊ¿ÓD0 —¸Øó¬�(W“±˜%2Ò$âÒv³%il6Mc,¢2CF*Dì¤Wò=[º]H-N·ôÈèˆ6¶¨Og‰ ¸Rô½Ò�&í»i�ŽX;S%# "¦ô¼°�{ÏÑT„t'£¤ã´s\Ÿ3­S'‡ŽІ¶-#ÒZötN©-ä»ýS�/L"æ(áç d:·î¿êl$e]�d�Íq˜¢æþÿ)CëÎRsØH?G) Q��¿Y˜ÆxàüÍ¿ÇYˆZØSäOðLL¨pùÚI&}ŠãEçˆh"Pîi&{Ñ ã,Ÿ ‹*V�ïa¼�unøyŽ aLÒE:Y�gŒßý,tsíò]2ê§Éh…‰æ%gä[(ççÍÕõùf½�Ú˜€[¥gR4éDls]&˜Ä³iAÌ…åû@€üùá´qî Ÿ[¤Öãx$“ÔH¿‡ZŒ¹œfŠëÐÒ”&x|pž½oÜ87Nüì6Âýg¨M“(¾5§mРưt©Éµ(‹¯©våî Q×…Ü�@&•1kÀ+üóù�$Ç \Ó­0õL¡Ì£ÅÃ$!Ä ×aKCW”ºn‰Ÿ„—›<�@4lã�Î<¢=Õ»ÐÌH6Ÿ™èv¼ÞfÒù+馎µˆãøxذá¾ ŠàJáù§édmsÍÚ’Òˆ—9~%ì‰÷Â(ª¾ê)]»Xâ{[á2¶žNqüzÖžìµ)[]£Ù*¸�»-§\D�ëNØfϘٜFè‰ysù[ ÷°5óžü¢€ëwŠë¥Íé%£½_»¬9‚ü…’¹€;iŒ·&¢8å¶e»·º—µa‚ÇÿER«éÓÁžO�.�ga¹™Ë✡îz"<ÏÃÀ¦Ç”ˆN±p~JD9"ÊÑ."*pèÞ"&¢?ѯ‰h?ßûu"ú!½N¾7÷¼& E›ôÕö³”¨ˆ} Qëí9œf@±@DOø<ü}MGôxÀ“|Ë/,s}£ÔyÀs||Àð_åxøÀÏxB/¤¾ýP&ñ’â±å·�Žîô#"à3> ¢"€� ö.ýJÈÔÜõ;("–| �$lEÈ-ãø{þ %lâPçü<y>×À#¢:Ÿw9®s‡¢YbÛBâD‘%\> `Àn._×ô±ð_�¯ Á ¡�³7çT9�4’@œ¶à€øÿÖ$l39‰"1"ˆ(Ïù[�ø³nB GÂ'CÇ&0ÒmE„>6MÖ� HïEs@7—WD |ìíêPƒÒ”û†±í"V"ˆÈÌo7|áë`ð>Tõ4#ð‰#C#Œˆ›NÂ'Â$Aÿö¸¬4'ÁÔˆn>ç‘  &„رÆÄB� äWàsV ÎA UM[‘øsCaDts^½hNBj:Èõ©B �€OD�ãœAˆ™®-숈ZÈÝÆyS+ž„š¬µF˜óD�  qh ’4BF¬5²ˆæ$Ô¬A aE4j€Ž5f»jÜ®š‘ÆÚ‰†l‹"ÒÂÊ£94¡µâSP’&ÊœCL2úÜ@㦠ÐÃV˜9«ç=ähëÈ$Á´Št/.â~á›=ßl—&Áækºîš�!‘Ÿa´MD@ 4zbÎA©z/Ôz`>AúºÐ¿Çj‚‚d|À|�’!Œß U„°94i #A÷ÞÝhìá:Îø§yŠˆšQWM„YG EÈFTíh‹&!_ðšòþåµ<5ašDäáajŒ8¶à[3ædÝŒ º÷ï6î’œc†¯ ºç•ÓüÀ.£ŽZ t�´µ·9„2-çŽÈDH0$eŠˆg¼ÁçBõÌ›\YMDpØ2cÝ`s½ÑŒŒ†ª"Ü, ³„\}Pš;EÚSþ¥ÙºçŽóþ7×Ýìù­LkZ‘‰ƒSpAò¾à|Û8W:ÏÇÏØÇ׎se?@£FYFšˆà¤FFCuÑHDÂIÐB~�Ëú>!ïr½µÀ-W<àǾ å6Â-7]‡€‰¶¦ZaLÌæðaZBú÷7üĸu>Aÿ‚²žðm¨ö%(­X0 ¥-KF~}PÍ^nXÐÂ2{£)ôjºÊåQ‡Ò®^¨ñ—±Î÷ÞðAEN�óÿ §ù f;ÄZmød„.£h„9�'T3¼Äéÿå.0'q­5@õº·¡œpû€z¾|j[�"äç×ÍéÃHÐóCpQ0Ä÷ôA¹:ƒö¨I÷\Ÿ"€oø=”4Ó´ßB ·£P~þ|¤®åbþ¶à �n˜MØÀf¯6PgÚÕ;t¼‹…ÚeïåÀ”ô¨Ìã}œÿüáè=²p‡êÍûàiak‡0矂‰ëð‡¥ÔÚ¡¾iú$T§¨†ʾ5ün@i“ú÷½�X‡5"º‡ûŽu­æØlÆZðEŽ vq€Îçmûá•7Ž5ÝP½³(/è Yáüƒ„-ê8Ö$§íEã¤mº1ôúb�“&Á5„¬Iû ”¯DèãU>¾Çu_3ÎÝåviâj|ìi"tO š…ZµLó>G^½^¿ADÇ„×,Ëz-pÝ äÕàËþ8ÔÆýÆü- ü æ¦4·Xò³ë'NœHÌ|æü;AÄìììžjµº_o¿B¬V«Õù,<+.—ËEÏó>Ío&ƒbÕó¼ê½{÷Ö–’ÞT�8ÓÓÓ…Ý»w÷Y–Õçyêß«RJWJy+knhÇq¬±±±'\×=¼FDë¹\®ÚÕÕµtñâÅ•¸‰‰�ˆééé‚eYÝ===ÅZ­Öc:׸1·K¥Ò­´·­lÇq¬ãÇ�×××»ëõú^­%RJ×uݵ|>_%¢Xþ' æöû°ë¶mX­VW:=îÆ‰r¹\t]w¯”²'ØÎ8†ØØ4¢T*�ëÉ×uÝ5!ĪmÛKI/ÎÒ€©õúÏ+;ý¿µ–ÿŽ?Û2==]HÛôKŽãXqì:Ù”?ùHýK¶�H½¥ŸˆßJs�ÏŸJ¯J�,Nq|AÂÿŽÃKái?F‚Ð2¿üJË�ã}Œx@þΉôw4Èÿ>±[¶íOŒhàŽÎ�÷™`‚³´}<¸ŸŽÜ!BmáD¤æŸ i…Î|�9ƒ æß×Þ ç)ð™œÿŒž²/·Í‡IEND®B`‚ukui-biometric-auth/images/Face/14.png0000664000175000017500000001003515167732630016435 0ustar fengfeng‰PNG  IHDRbb«¥äIDATxœí�_lI^Ç?Õ3cDZ½Ù#{»w{·²�YXçÖ¹Û‡…åÁs‡8à8Ž#Y‘ƒ'$„¼¼ñ‚’'$þ) ��$N­ sáqNßfQd[@rÿ‚�؉OOÿx¨_¹Ë�wÏLÏ'÷•JUÝS]]ýûÖïW¿úuÍ x‘ 9+"óš²âO)DäB rrr=+"Íœk¡Á$Ö{üüYé@nsÉÆÎy΋Èi™éÓ³=±‘•í¼'ïsþ‡§ûÜ×§JˆÃŒoãžZ;ß/ˆÈÅ]Ù{6nºß{Ú "Ó*û#"`Œ1ýîØÓ'ÿb¿;’„X·n²AÊŠ `IóKƘµ<û×- „F¨“pBS9çæW�w€w‘”]ù÷‹9¼ œdïˆw£Ùå m4_örW^ÊÆ˜»m´×58ùãü§ßüˆç$¬«÷0+ÍV›�ßÏ­“VÍ)Ù•¯‰P®êm/ªfô⾎ŒõA"£ŸD\mG ª1û’¦î`Ó:Þ"j`Èè �ŒJ½fß°‹ØÅé¾Ñ�=ÑÆ”þô–é ”â®ÍPטּØMz=Qíì+ý bÞÍ m\;'"óêÍd©§uW´?séµ»‡ž‘І–=#5i©#]ëfz‰Ãþ}�/|"V¤ËïÄn=þYÃ`£XïjF¶¢i^šÇÿç=­;'Üa¯þŠôÉDõBþþͦçgEdÅ;žV!:aÏK<ÁÏ*1 …«ŸÍ(éóš¯kº "³‰ûžU²×=2Î)ñáQå ‰#Œ�±®~QóuO³‰z™M§ rÎ;žP¡ûk—Ó"rÕëŸ## ³Íï<à�ØC¹˜8ﯮ/6…ÒœV_Iq¤‹¨;¬}™UÏy¤%±Ò¨Ý‰ç‡³Þ¹9=·.év<“KêÕ?")6WëÌkR]i‰ÍãÁ}yæ�¾iïÜ´è»Û ×ÏI‹.¦H~k­»Gƒ<³tµÉgY_ó­ Ë5:²®9$ ¹� èVêçõðdƒ*'°¡é4Lbß)´‚UR^&c®iö…gº²ôµmt�bÞnòBf’lžlã…Î*ÙÞê-4s`÷�‰{ŽK-ö¡ÿ�x%Ý4°–ÑŽO72k®›• ¡�šNÖž£±Òì9òB·4âmÍÏ7z#¦£0‹ª?‹}K×*6ôÚ4,±¿y*k~iÐÞì¥B¬¯îÐlÜʈm+(—Qã&’¶?ònö�Ó71ïî �x«áõf¾@—'¿,Ðþ•µ_Î�ÞðÐybí:Xs„Ä %7ãÙ[Y‚rmùîiת6̪ý_»š>›ù²7rpÖž�›…,.xêî&‹jv#¦JÞÕvL“39z¯#^{gõ^+Þ}¯úƒ¦I{ÎDµü.%+rßB#’¾=GëLcÖTð'i’½.¨3Yq‚ØD:Ó²€5‡ À’g6ç´¿¿³O'´?Ƙ´Ð�ÌèùN?Õ”]Ah¾üM¢Þ<–ˆ ¬²xA«^ù¤1æŸÚï±í£Ž¯VúÐú±å2“KjŒù”ˆH»#P·‘�„¬»ÝT#z�n®¬›a’ÖCí`•.Žà¼ñ$‘¶X(ôƒˆAÃ*­í6ï žd�Èu&ûÝ��%B²Ç£žtƒˆ Ød'h7à—;$Þ4°Ú­{tƒˆÍË]h»_Ø�Ÿuë=!BC¹WHûµ 1¥Y±’‘Ö²æƒUá3zXö>*ïˆÝ]q89ĨÀ°ý[ÂF…aAóK H,ÈÞ/p‹4x1¯£nÞ‹xŠÄ¿M‘ÜxÚڵџY êÍx禽výïiˆ¤ìY’8X™y�U+È-è§£ýYì—ßÚ§Þn�Í ø•½|;:}»|>ÙN\"žð—ˆG½ø»æygû¾×±ªm–;�_%‘K¬I;é ÍÔû14 ø©`&‰‰˜$~õš«^y »�¡¡à” Ò6(cîŠÈyíË W"r�Ä›²l;-vÌI¼_µ]ÓtZ¯O{ù4‘f–¼ºî9[ÞÐ�†~,èVɶ’]ÂFOÛ}i¿ª×§mÅ™$ãúÀÓªÜcXƒLD§˜aäE„{àÔ°sÖØŽŽ¾r}ʺ“°L{_ªÏ¹¡ÛNd´é«i¶{ÑÍ5Dž¦iAóFû\“X%E+DÄh^‘’ˆ ‰È!Ñtx¿”€’^3¤mE¤àÚV”É®åijæ†<‰xGó·3ŒœU” T@C*àQžþø -?Œ{å´ôIàý׌ψȘˆŒniÒäá\óÜC¹½³6Æü©ˆ|k›/‰Èɤǣ#±ü6ÌñE=.`…ñÊ�–chˆ †ôAô=@¨× i.@]ó1ì¼öX‚"©kÝPóº1Ft…^F~¨Eñ¤"ïÍg°šQÆ®†ß'h—ŠÀðqà{�Sì%£@,è"–ˆqb"üäàH‰¼sïZáq"àuàëZ'ÒÏ »e™"~W~n(W"t•ZÆÚÐ3"R~YïSðr7Q¿ ü ðUà&{5Á×€þ‹ý‰pe¿ë÷·‰5Â'á0ðóÀO·°D4"áCÀ¯k]€¿~KDJXMñ‰ï¹¡‚ß>üð À 6,ð.1¿ ü&–°ãÀ¯[Ø9á_�¯iÝa¬0>l“�ˆ�+À_ÑóX-üQàeàËXÒ¿ˆ5Qðã4§ü1ðÛXC¬¦„@ÍSÏ*£fÈ%è§”°B.iúpøÁDõ¿Åš­ß¿�È'�ϯ£À¿ŸÖk€? žGÒˆø=àƒÀ·5}P?û*pKô6Æuø–ô/5x¼w�?þ %@S-ylŒ ÷“Ó~èH#šàÊ!ðV¸'�Oée?ÜÁ åóØÑ`MÓiù¬·äpøK࿱š�¢�`G+X‚Ѷþø–gž XMý¶¶7Jüe øbUÓü°w\Óg¬yç �hH[D¨›W†hN„+ø=~ ;«/cMÆ:{'sü#Ö\¼�Õš¬°Gˆ'g_3n±Âþð#Àb=¢K®³ý0�uoG�ï~ZÛùkb¡û#ß .÷|5-‡^ß!5,!™¿Ù2 -pD yôËIR¾Œ%a ø1à v2ž'žÈNK>­ÇÃØÑzŸ˜gªÐûa‰8„Õž:–ß#rò'´?¯¿¦mü§öÅýÉ‘_ÔÜõÕ�p½Ed'«v´D„’àØ'Â¥f„8""}øŸÅšžw�)à²W×'£†�kÆêÏÉõD¼Ü¥9 cØuÆ-à,VËþkþÜdì“�ù~ª±w äú`¼r'ËÜ‘™ˆ ¾à‘⛬dyKÂaày¬YÕ‡(%ò¢ èì„ÚŒŒ=]ÅzYß`¯[껦¯`‰ú<–„uàOôúÃ4ù¾{xi?×}ñ´/™ˆðHðÍM’„FÇ�´F€ƺŠÇzP#ì%¡Hlª¶�£X“”D3"Žb…èÜRŸ„kâî`”�‹ÚÎ�›šF MŽ¢A997ˆˆÈ~f*•obv#Ô75�ŽÓ*a]Á}ð_*Xa5jïÖŒÜ!ž;ü™À0V˜ÃÚN’gv>¢×| ¸‡�W|Sh99Ê÷sù%‘Ü (“Ñp˜E#|›�œPýä�ú4‚"àÏ�_^> üC¢ —îaMÉmï¾Í´B€#X-ra‹�ÇýÿW±DíïaIhdj|H¢ìǯœÀ]ÿüãñ<°7 ³‹"ìã’É=ì�vÚ宜<_jðyiŸr„5QŸÁº±ëØÉ3Iæ(Ön?Ç^ÍL Î h\Ë/èÃ'5a8¦uÖ°Ú6N¼>ØÑº;Þq£TÃjëŽæîØ?·ã�{<‘Gì%PŒ1‘‹ù'Þå‡4�i>¢é�—kÙ‘p(A’OTr¾(/b'í:ðMìˆö]F7Êý9¢Ñd�{B3¤Ÿ‡XmK’åK’â»ão{BvåZ~¨}ÞöÎÝÇÎO®­]2�<ßü$×~9éåøy³ä߯$"Ÿ«×ëEcÌíB¡p«%“ž0ÝDç¶à4"à�¿®]Ö£( Dä³" …Ðó%b�Êú^V�ǃ�Iâ‘è“éˆtç%Ú©õÜ6˜u‚J¥R8vìØËAŒ¼÷Þ{K§N�ê8�æãÚµkÏc^ ‚ ¼wïÞûo¾ùævúU½Ã@á°´´t,‚ñB¡pcjjj+϶———?†á‹ÅbñÖ«¯¾z;϶óÀÓøÕ­¡~w ’ˆ»wïæj–Dd V«�§Õ튈b±8Ð û]­V·Œ1Ãy·�†ˆjµ:EQÑó ½vëð'ÿjµ:Ö�{t‚�!bkkk Š¢ÍnÝCS„ax8­n¯10D ¸ÿþ�nÝ£T*mˆÈÀý"Á@Q­VÇ‚ �¢h³›þýæææ@ãÕju ¼§¾Q©T aN”J¥[ݼ×ÚÚÚF!€1æh7ïÕ*ýnXß~jùøñã5Æ ‹È7ó^Ä%qêÔ©z½^¿P«Õ‚'ÿ»{áL?:qíÚµ�†aøœ1æÁ�7z²Ú½qãÆmcÌcÌðòòò‡{qÏœÎôí]È!‚Ðóõ©©©�^Ý»Z­‰ÈDQTìwÈÃÉ¿çsD¥R),//O8îÝ»÷~/I˜ššÚYÃðÅååå‰J¥Rèe’è©FܼyóÈööödEÅAˆ‚^¾|ùèÈÈÈ$@áýû÷ÿç�7ÞèšûÜ»òï7oÞ<²¹¹ù‚ sclnn®B(ºZ­ŽEQô’~¹c̃(Š6>|¸½¶¶¶‘w8>‰®±¸¸82::z´P(�¢¨vÔAð­A CW*•ÂñãÇŸÃðÅäg"ò¨T*mo\¹re+obr'bqqq¤P(«Õjã~pMæÎõë׿ÕíÖ *•Jáõ×_{ôèÑáz½þ¬Ó‡ Â0 ·‡††6EäNs[.Dh îåd‡ŠÅâw677·zmwóDµZ ÃðÙ Ɠϙ‡‰ÍM#®_¿>í&ß0 ·�1ŠÅâF·gý€¯õa>ðÚk¯]é¤M'ÿŽÿ¶eqqq¤ß®_?P©T ‹‹‹#�¶³+‰1Ø¿CôBì¯ô‹è6š=_î_—žZ”5_ˆ&!óÏû|¹ÁÉ|)ù(©Ž÷]äÙû‹oîäœwò‚ÀßÉ8(Ð�Á“÷\²Â9i÷¯#;DB¨­¢ñ"Jó¿ ICoþ�y!Íÿ_{?ìùÑG€ÿÉo.ƦAùÌIEND®B`‚ukui-biometric-auth/images/Iris/0000775000175000017500000000000015167732630015554 5ustar fengfengukui-biometric-auth/images/Iris/16.png0000664000175000017500000000640215167732630016512 0ustar fengfeng‰PNG  IHDRbb«¥ ÉIDATxœí]K�GþzÆqB€ØKH$a D;  ¤±!cH‘@ŒK@ãhœ ‰ âV×Q �¸� 0F ^ds^›×&ÆÁ3“ùXÔ©éSÕÕÝUÝ}»ïØs¤Rwßé®:u¾óªG÷‡tH‡´Dr�äÉÙÀ|L…� ’džä¥7"¹BrDrF—NÈ�O#’+Cð3w’_ð:¼%V1¨’<&|L€¬É[§Dró hœ(̦g±ãEå7ŠH®‰ÿµtá tH¬d#ÀÿÁ‰!҉ѭ QÒm!Óá®H®8¦#Hkëš§RòbÁÁ2ãHòmk¡,ÝÓ–ɵ¡yš'ú;¼Õ S[JCn9+(# æ–Ö‡dDƒ0Œ‘ÉsUýƒ! Ìng,‘<©d±ÑgÃ+Ìóëþ^`0¦½Y†çŽ7…€DAûqSÌçcnkwTFž›šO6Å|Òn<—nR`ÌØõ¬2Íìäm—¢6%-¯.+�·0)K³ˆ ·œp6˲´e° ‰¿=.|Ø#äüªœ_‘rÀ%W³,ûS¯Œ*Ïq ÀƒÎdYöT›Ê6ûÎ�Ä×D£l†Ö†¶¤®µ¾Ýªô…4©m³¶iF�—4׈�Ftçÿ«;‘2Vç1ÏZ¡Œú†¹‹j–i2OUç’† У��i¬r�‘3�4c�Uš¹  ,.�jš±‡%Q¥$ií0¸M:f(´òåkêz¬ÐÛ^PÇ,n^°íoαm6–gWL1ß½ÒÈ  ÀG% Œ»æ‰¹ûì?ýgx÷…©á¦Ž=¢q}ã>;Dd1›�Ž�h2‰ÕA˜*!ÒË÷]¼uwwo8a>@œvmþ-øµ‚_“ßVXÜV3ãAØ Hˆ}7ä˜6Ýu rÜó@j…íóÚ7¸I´Ü|mîÓ÷ ‚%ºËž…ù!dâõo±Öbèš6Yâr<ÍZ¸µ ºÁº Dr�ß× ÁUyšTÕ�UÍ|ß|Æ‹n3œYÜã4+»·¢›•n£Ƨ Át ‰Æ[ªœ’%œ©~õ7<73c…¿÷[˜¸PFtcA¥péîâè·,Ž�KçOVÌË7ht*õt¨}�jKQ}£°[Ǻ'ýü™Ç¶#SKIÙ†0º¢®W^KnK)î©Q_*êÓ‹SŠ×Y’¿_„Ù¾çúÞª(ŸÀlQ¼b¹„ÙByfMžª¿e>$[/ÏÊ僞€%šüö´üáb–eßî™7ËÐéš{º¤ãõ·Ì�dñE¹(*­f‡é«Wﺪw äÁú,rË8Ïö©š}g!ÊðÃ3‘÷uKh2Rëy®"Üû7t¶çˆùÈ:zj€í§/R(v±ih* ¯><æ#pc#0Ø`j€Ý�œë(zÉ–¹rt±°µÂ”}]týbýá:’g_Ù~š;–¢û£žiõ:3[Lüù©š€‘Ü ¶[ü‰¡è¹/º#à6nz¥•,Ù æ™XÊ$›Ït—T>Ñæe¤žm:ùy’î�f€ÒÕŠ¤Šè¦hÑ«SÞs]RôÚ5ÝÄ¥ÑÄ%;Š·ºBß2¢Æm:30’öyí7qËúùÊ x©7c¤žIZX ´Ù„ �j‹hƒg7¼ö»}Q’Ålª6ÓÍ„šì¤XaóñEÒfÕæºª#ußߊ:Ÿý°,ú½0ôôI#í%ˆ]—µhG»Óèõmߟ˜Ä>Û˜`T6J×*Zí~“ºÖ™ïwÕ¥µ  »9,*¸³8PÍÕ¸F¥€éšl'+]]]×5úfq»Lÿ}£ûI9 FÕËñÃûž‰Åy¶Zëb« s§€€K³ºÓó d ˆ®¯Ôj]ÑÖBô…ÅW™J;Ãbj7øûgžfWº$'&ïkn,¾àÔæc‹Á_hdñµ² b°øÖ쌋öV©&ƒ×L:æÝ·0Ÿ­fþîGHiVXœˆœp�ßÜ'_j±€,T€®"æßÑJ5]$Š&ß-³îjaä+CVÝ î1S_ébþéƒÖÁˆÅoZXíjݹ®ˆå_§uá†Øæ«—ÌƒSksdñ?“ø�íýÓÿÌ¿ VÆSWߪ² A³”�]|0ÌÔÃ_0›qŽßÚc>=R&ü)çð�˜[Zó,‘yJÚù'¨Yî,MH>Nò$O�!ìoQ ¨ãJ@¡Ù²s‰J „4b‘>ŸeÙã�¿pŒ íñªAi†ß�* 4>1 ì¨k]v²,{Eúo•5Ùs¤¡?<¾ÿÑv€=ú`„À‰ÃÃïG) èR&ü]ù›¾þ.€uÈ[N©«“€öƒ÷E0>à'pРøçÚ24(KÞy,~8¦‚Pf úhAØðjßð^˜„æ}Y–ý1^¢ÅNDÉGü&+ø*€ï¡„жŠ2w†Í¼€¢e¹ìÎupÞE9Ú|Í× ÜàÇÞà/> `Kþ¶“’m5±+ÔGüÀ1|G~?Š"!0ÊÜU,™ºvX„ B(C*!¤ýþï¶<à›0ÙÜeŸðoÛê¹m?ê(5F�´ö ˜<ýcaìe±@ØßB–¢ÏSÁÐBLÐ øçŸðI¯ð,€/ø—ܳ °í,Ëvëd›’¾j¬p�x=€x+LÞþ3ÕÂ�—YJ(~Ô�á°ŠzôѾ¯ùˆã¾à�ÒÖÏ|¹ð·‘ƒ¡©#v@§…hЖñ:_ð€ëž„q[þs!KÑÅ�!~†U†Ã.â@¹}¾í� Àa‚óuçüžÀ×û¿W¹©˜)Ž%äÂÔÜ8~ÆL_㲞„™^°Â÷Á¬³”PP×@ø1ÂOYC Ôi¾_V`‚ð iãY˜wà®Á´¿֖™ÇQ@Ùõý¾Ìþ à)¿�kA¾EùV£‹Ž)!0´U”�ໟ�æûš|Ìùa©ûŸ0Ùás(xèÚ·Š ‹ª"ÂB¿Ý)ÇÇ|ÀÝnÀŒ=.UÔŠAeA?P'h7*!�~€wx“Ôù2Œ"=]#ðJ¤ÜDIZ[IJn•ðõõ�êúa˜oiدÌ`^­½QO(1ð-EOî@Mk~È�Û²+õ=àáßÒfºü?5 ¼ìžP¬ØB¦¨ýâÏŠ†fJcÎßàkÒYø€_Ád[×´:ê‘¶Ö8=äOa<`À½êþ0ë?•s}ÿnI=¡²WóŒ3ØÔ@”�†�JgC."æïú¾7x?Ìôˆ¥a¬ä¥„zRø¹)e®¦Úß‘û^„Ypú»÷wÿß•…êLyfÀM „Ÿ�hMÔ :ˉ÷Ï—ˆUäoÝ$âù¦üTiåžv¹«Óä*�oòŒ-ÃÍf‚á7ðÒ!Ò‚Ñÿ1­ƒS¥«HIEND®B`‚ukui-biometric-auth/images/Iris/03.png0000664000175000017500000000753515167732630016516 0ustar fengfeng‰PNG  IHDRbb«¥$IDATxœí�[ˆ]WÇkf2icâTÒv$55ÅšöI”ú >ŸÄ§Vë•¢­‚ >˜‚*(i}ÐÑ´,¾˜Š|kUD1• ÑÐБÔĆÄL�0éLNòù°¾uöwÖY{Ÿµ/gÎ$Î6ûröÙëòÿnë¶7l`X‘E丈\œp>^Ñ|<*"s“ÌËšADn‘£"rQqp‚ù‰qTDnŸD~Æ-ð‘¨ÀÇU+&*…"2§ùx>AÈ}“Ì[§‘Ã׋ĩÀŽ4öØzÍoD䵿GêHDœˆL‹ÈŒˆl‘Y¹IDnÖmˈ-Üw“þw“>kZD܈´çÄûŒ8ÿcÓÞÊ 5�fö à!½ôð˜sîŸ%÷Oa›6ÇSš¿°wæ<'ï\3Çb® pÕœ_Õý5çܵþ|YÓí`xÈ9÷Ûi×F§D¨M}Ž’L«$†Êž¡¨üpÍþ^F R†Pá0H@) ÑyÏœ¿x 8¤Ï{Â9÷…¼ZÉCgDˆÈaàq=}xÜ9÷ºˆ„ŠÛ ÕdLST´%#µR®™kR²å’÷€÷?à ڋÀ¡2M¯‹ÖD¨ú>…—–E¼Iú¾’C¥—í-a_‡Œ¸b®å�®å�ö[�ïhyuaªZ¡$¼Üƒ—�ËøŠÜDQéU¤´!#.G–„˜€®˜óð)à[šÖCι§kU^„ÆDD$< |_‘›(H(Û×!Ãú‰˜Œ¸eDÔ!ÁnqåÛí ð༩zØ9÷£zµ8\€ZP4Ï�P0cöñ±Õ KÊTtœKF\Iìë’P¦ v…‚ŒwâýÆð%àˆsîj�ê*D´-ð0|øƒš�:ûi†‰±š‘CFˆ¬`X3`8LM‘`£¢ VB¥÷¢sKÈ;€·ŸÆûÌ+Î9«¡•¨EDd޾| _±³•m�S¤L“6_uɰaí@6$!!•‘�’þøz¼…ßw¿ÁkÆg€«¹ÚQ—ˆ€û€Ÿ�â+}“ÙÊ D„k)M±ÇuɰÈ!!Ǥ$?EDØV�ýÀ³x2îžÇ“ÑU·ÙDˆÈ“Àç�_£¨ìP¹–”p$ްÊÈÈ.y$¤Ì�=^M—U¾½¶Šoc|[ëëýáz•™š)û¡_*‘{�ïà/Ÿ.3lblå�"h”ÖÄÏ‹I‰û¤â¨É†¬)BåÎê~F÷Á$^1Ͼ°æU oHû9àð0ðMà˾*El_–ÅH"€£ø0õàï¤j±„·!(Þf€·7áû|f�7i…Ìà+¼Ô­à+ú¾/‘6?3zl»UR G‹TåšÙ_3õr ø.ð!¼ãþ=žœ)»aú¨$BDâ#¤Ÿj%Ä™žŽ®YÇK´�˜¬6XBvâ+|°C�Û`xøp¯ÑAòS~¦ªÂñ­ð²óe|(ûkàÀï€s^)†ÃÚR5ÓžÔð&é …I²Û¦ÄùæŒ{âçܼØ�—ö*¼¡âtÚÓæ¸ —ñ¤ü 8«çÁ¶[;¿’¸–º/u¾b®}ø$>Òü%¾¢O„ö’Z[üK¼£ùð'Ê͇•æ²Ð5uß>àÝÀ]%¶ üo^–µPR’^™ÆMã%´¬Ëü ðoRÎ4îê®ê¨» x¯>ßçt XÒ ¹ IµÎ§Ô Û~ ƒãÁÔ¼ï/§•”ªnúT?YüûTôû×ñæý‹øpÖWG ÞÞE»ˆÌâ%bGôS_éœs—Û¦S3OÛñ]Ú·0ì+�3]æIDžÇw Ýãœ{=þ½ó¡Ò(ñà|wE?-á+ÿÂ8ÓÏ…vÝìÀ“b±œî‚í£[L‘c$BDv{¢Ëçñ¦h¸Ü¤—rP�¹ožv3¬%‹xBVÇ•‡qM¸=ô ""7ãûd®§ÖÚ$ÅÐüÎã+þeÞ�ÅûÉ�„ôðþãÂ8¨Ë1ëi¼4Y34 ÚzÏ»( ·0ió$"[�;õ´œŒò—iŸïN¨"TÊç�-æòçÜÙè¾枉“ ";ñZ °ìœ;ý>�··™Ë§�sçºÊCW“æ)¤|…„É‘½’õšsîÕ¶iw ÙGᬇ„Hï‰Ëº„/kkSÕvò€•$(/€Uÿ%çÜÉ6éŽ ³ùRÊ9ë}ó¤õ€mù¨IZ¥Ð¨(�ÐÃ;º !ãá¾…¦iŽ*Õ æÒî²ûœs§ð�¿ž¸jž£jfBhÚ^-‹�ñ‘Gˆ ^gØZ†%=ÝQU¹êNQ�q—6¡6Ú0±QÄ©2§«Ú°SO—»pÎ:±x«nÛEd·n[Û>[qÚÇí 8ç.áÉ](ó*¤µ‘3ч’º)B½l7iœ®¸/'mëìËîiÝe✻,"çÑ–¶ˆÌVi±sî’ˆœÄGU[€]"²f;ñ,�ЩìuI€BVTzÚ GígðdÝ%"û´aÖVsG¦ëœ[Õ�wQ/ÝìW‹�…\Ó4OA >J¨$AMEð CN¼´Bki/¾2îÖÈ®Th–õ4Ûî«?£§[¨áÄG!"û)Bµ¼&ä8\[€ÅÒ»2 é�oø÷[ë,�1Z±¹ND¤‘ãBø/^3Fþ¿’mä„Öä2ù$`þ·ØQßL­ÚÑ€ +î$·Œ¾e<СØ|y7ëþԔƷ6æïlÔ©fi"¶@�È©shhÛï‘­S JG«Ž¹ Ô‚­ëmS Úñ[Ù@5ÛuaÃè¥) ±jÒEtÈ͵Åëb~S6ºê2ßNÑ¥¿èœ»Â׊ÊÛÓf¤I*6K¢&0·)·R;× YÃàQèx úãµYMñLRë´„;“¸ äöõ5ºƒñ”@Â~еß`î7è:&#Äßuº:éÌÀr ‘ÜJå]0!º�\×ÏÇ@‡þpÊ\jJ†•îܰt­ˆ¨ž‡¼·ÒVÕ„ÊÉuC�~ª‚/ÓB3"‰ËÔo9ø“‹¥Ü ÑøAc³¤š`ÍQr†c²\#©Ú™© áujgMš]£G1Œ™Û ÒH[>¡tšiéÀ�!# .!ó›G�N™4W�qMÅ<›ëpµýˆh4ÂhHýn•s}+‡J•ŒØLå¶3Íÿâ•BUi†aÆ.ñZÍ®»>¢¶6¨À†ŽÊ®GNH˜©=9d¨Ù†bvï¥fÚ @S„J¨«e¡|½º“âtÜdÞ¤_:Ï"k:�’a£©=™ƒñvÀ¿V‹]Ók7ƒï´/]hY¸® åo§9�÷­Ì�ˆ<ˆ;ò‹Î¹{S÷T½Jî8þ�LJœs?o™‘°º45‘¸q—DË`�’—=5ÈÔ4Å[_âI½=|oí"p©kM1Ý#e/ËZÑ´ÏuéˆÕ$bÄWXF½Á,|%å)çÜǺʜ>»Ì,é¶LbTâ·àg’l¡|ŽÕ"¾=йß‘Gñ_—)5I#�µˆ¼‚wº­MTÉóÃhØv|¥•Íúîᎄ·OƘÆWö,ÕSèƒæ]¢»õ}C0¼EIš¤€"Âõ��|S§"½9|…†^ÖVëðZu¯Y‹k1™M¿¯ñ˜sîÉQÿÉ}7xßëãΚ6ƤX³=K!õñ:½ðöûðjÒ¥®]¹0�Nç&ñ_T9Úéƒo0Hñ©Í㹓&š$r\9<–®sa šÐœŸ�|pl ]‡0$¼"kñ5b9¸AFÎ`Ž.® &ñƒR|áöÑ5Kx�AIæzm4!‘ KÆÿ�ψ,Ãx}BFfæ G'š™5„ ~óúùuQîu¡žkñþ@DäȤó4%ãˆqX7œßˆ´à¢ø�¬OˆÈƒ&³×÷'ê"rŸ ~éýغ0E£ ê{ÜHÎu©J€5C¯¬k-(CB•¯‹6G‚€‹r½G…âC¼c‘T­;BT‹­à¾.ÌP.TÊŽ›^ïÜ'êC"3j…åÆ" FBíE+bb!¯ L*�r401á¼¼¡¥?âÛ7lpØ@Sü+a.”\«IEND®B`‚ukui-biometric-auth/images/Iris/07.png0000664000175000017500000000745015167732630016516 0ustar fengfeng‰PNG  IHDRbb«¥ïIDATxœí�kŒ]UÇ{f:}ÐÚ‘–œJ,‚Å QC‰/£-D?è—¶âcÐhü  >M &è'�šã3ƒ &ê—£ÆiKÑB¥Î@k+´0C¦ ´½Ó函vϺ{ιwß{Ï}L™²s÷œ³×ÞÿµÖ^kŸsÏ�yÌc=Ù,"»Dd¢ËrŒ©wŠÈònÊÒ1ˆÈ°ˆŒˆÈ„Tc}å‰1""ÃÝ�§íÐo�¼K­¢«Z("ËUŽ�9„lè¦l¥BD¶Í�S…ÙYìh¯Ê›Ù¨þ7`û\i�ZÉ�9òÏ�1D1r6h”¶ÅZÈØœpW"²aÎ �%dÔZG·e*D4Ì-3ND¤h»zÊÒ#m™‘�Ý–©�Èio÷­^…Úe4䬳‚"è`°¹›‚XFº&H¹ªÎ“¡$L¼’I‘õ¦/îìdÅÃ’Å×�«¸‡¡dŒuÌ2"wÔ»!\  Ú7%Ù|Ì+Ú!rS퉦$›´mKg Rö¬²øÙÉW\ˆÚ,l•yÑö1|Ãx�¤±Ô%\pp °Å9÷£Vlêo‡TްD×'u}\Ë$°˜tÎí騠ê9vk€Mι_·r±m�Ž�Ô7ªF…­ìÒkmì´[Õ¶ˆøÐ¶¹ºÅg�¢.©­ ÐN‘êùÿZ»S˨YO97tÊH§ˆ‘ÌE5iJª¶% S¢Gêtبx«Ü(‰3�âs� âç‚¶Ëì[ Ò�[¢FI«G²ÄmgÉåÝùŠ5usj§7X÷%uTf?¼êßÖÆº¥éþ,K(ÉžÞÈÓÈíÒ…hL ) e´l™$sŸ�ÿ%ÿé Q¡º7uA¼ë-�³B´/ºB¶œ†�ˆ�$6ÔJDœˆô‹È€ˆ,‘AY$"‹µ,©SÂq‹ôÜz­~qQ]ÃJÆp�•̽ûî2ûé�ª†H– ŽézŸvРvÜ9"²Lüx2$"çŠÈ Y)"ç‰ÈùZ.¨SÎ×ãÏÓsW赆ôÚKµ®™Ž¿Ee–Ù�ÕLHŸ¬›Ð¥B¼¸Ëì~¸+$V"2Œá1€Û�Ÿý@ŸÊÖû̾° ò†}µp� žÙ`Æì{ ð ÷ð^`P–_ŠÚ´ŸÜ–š,–B„x?ºƒ,ã¸Ç9÷UéÇwn?ðà�úûÀ¯ð~ë¡£-y% �rÚŠUP, 3ºÜ |EÏ{ x»ù­,Å+Œ ?ïrÎÝŸÔA h™ñ ì ÓòqàVàŸÀ¾c€oŸÔc~|ß�Ѳ2âvˆÙ—BBØwؼCϽ_·+ú{XÞ|ß´õaüôÅ )}U -!þÝ}f××€oá;r o~¡Çü ØJFR+dÄí¨E„%Á0£e 0ŠwGï’‘pÊ÷]à}zÜ$p�sî©ú=VŒ¦‰‘mø1!ó à·x ðÚóà"` ø0p”Œ¤zdØq"&#nGõH.èzà^=ÿ!¼» —­Àç�åÚþw:çIí¿M!~0 `“Àñ¿ß‘a9|ø”{/ð{f[L_´žJFÜÉY¦’¶¿A6Ž}ØGµEœÒRÞ üOÀÇ�çÜL½>ŒÑ0â'¯¶˜]ïþJf f=XÃ2àIüaI²cH?id¬ÎѺÏ^­ëcZ‚œÎY:?&¡\|G¯ùgàËT[Â)³<…'ãÛzÀÀg�SÎ9k¡5Ñ “À&à `�Œ»þ <éñàq2k°î+…Œ›�·Öñe`/>ü|†j"RHZY„tð_ª­Á– ° ?ˆ¿AÏyoGS­#‰Íî##á< ûÉ:5&aøp�vÊíæwë¾,a=�Œ;€E)ò*PYcfL �oµ~-Þÿƒw¹?¡Ú òÊIà{À»õ¼½ø(ë¨s®ROØzIQÀ2žÆÇÙûñ»0g¹¸OÀ/uß"`±)KtyŽ®‡²T÷-Óåj#|gnÅ'lË̵µC�¶î ÓÓøˆ àF#ûBÓ¾…¦„vš,мŸ7]+"õ„­{€ø©Ûuói¼%<£• ÌÙ~�¹Ì>¶š¸W�§�ÿ—Ö“7×ç¢:'°ƒoÐö]ïþŽ÷ûç¯ÓúmÀù‘ÛÀ!ü8óàwÀM"ò�Znª¦EˆtæFÝ|Øü�êÎZmBBäñˆ68ÏjEëÖR‚¶->PKÖ:¸¸Á\o±Y.6õ[MßoοŽL‰ͺ]Úò ð9¼[\Žëo‘Âþ.üAæMºù(ðàÕ>Ü+Èeø `ÕÙ-ŒŠíKÈ­óx‘¼ .gv繚�çõÜ×3»³ãöÇý2 | OÆðsª£Í*äEG{ðYäqªCIZöGÛ—™ËŽ�“cÇ”äp°Wâ­+t|¨Ïjö€Y×ó.6¿Å^´ÜÛñdü@D¶ä 6‹ˆˆ„Ýx_H(êü˜ ×šK®!¨Ýk\ž+[’׈°?ˆ¹V;VõáÝ0x%XYÐÖ¼m;cü/¼g dŒHÎM±3ƒµÞ,ÙLFÂSø)áÍq!?E– Uð¡›mØEzü^mLìÂb³Îû=¸¯Ó}­âB|’™— Ù}§ðyÏÍzÞ`‚üäΞS!Ë_!�·àÇŽW÷‰È!|x}ÈîT‰È•À�uó4> !j?³£›/Ä¿ß�× §ð¡kÑqõ®~_\¥ÛESâEÅfØ¡Æ+X8¡%¬‡œàÞoÐsþüÛün�³ëy× ë—â3õ>²ù¹#À §$ô㣜A~¿^ ¸{Ã&ò~¿J÷=¯¥¯Æùv=L]Ttßb|.2ÈlÓÏ›�Í+vN)” •Ë&x6ãž1ëktyT‹½ÞLÁ93å4^©†uýeüí‚“Áå¬U¡+ÀAç\ˆš‚ˆ êêaçÜ‘Äã×�MA[ìmE–L:ç’Âa¹VW“Ú’xÍ)|{.tÎèÓé‹Ð“ιg˨¬A ’OB»PÆXÓ4œsÏ‘=³;$"Kû¨ŽDÎ>mm‚íëe}À´Ùq ó8;Û…Uf}ªOï·Z3¹°„J¹©qÃ7R:„Åf}ª¬‹ŠÈ üüøáàxHèÆÉ:oµØ BÇ&i”sî¥ëk©�ZºEˆÈb|¦>8ͬuVp¿þ°¦E2©‹kU�Ò4.“õŒE;çZ™çÎ�p9Y‚¼?ÌÈž™â(™Œ“º0¡l=¤vN«˜nÀC$w¢ÕJMˆH·rTÍ5é6¾n– «Ý©ai§ˆh$<²·d­j ëÈ,l\CØ3˜5é§&ø$-XF¤qKÏ9 k¤ž&0w@¢g\›vKj ÖÍ" ¦Á5’§574¼‘D툩³lTðsL©2ëMYkΘ�KÔ¸1dÈh”Œ üÂÔ'¨Õ*5PG#8’:àjþˆ˜læ9%CÂBÝUHÔ¹UªdÄn*5Ϙ4ç­L<'¤ÿã©Ç'â™§n†È´¸akP…½’ìxM á)Ž7µ:… Õ"›(¦FO� «Í"tB£VÚWISDdÙ„^8�r�¤Çi” M­–´ÐØÙʆ2v­sÍG,ÓÀ¾&:r™;ihTD.&›&ªàó„$wØè“~ñàs¬ÞSÐ"²–Ìß>ÑLb$"KñSCõŽÅG^Ï5YO¸—\Êc)マ·–êp÷@#cK3ϾÆdÔ¬T]ÒÕº9�É&›¨;L—ç¹¹©V³_u¹«uó`ʸ¢2­%ËŽ‡mc³OƒÇdÔì`5Ù0ÉUÚ –2¡Vw…nN;çö%ž³–¬šn[ê#—UЄmY꿸¼Æ€|„r'K…q-uï˨r]AudÔ´‚5Eœ‰ù÷Q=å½Nµ$>v†ê�ôbµª^A¬Õ….Nü¿_בYxð 1Êø]?>\³i®‰jhg£Š¤Á°�ˆÜfM—É Üû®‡2ÿÞk:ðšR5Ã¨Ç ã¼gšˆïK…*Ñ:|¸Z¨j½kÈä >S/íþ~iD@îàUÁÇâÏÚŠÈò2þ‰Y”Œ‹ñ2ÆJ3ˆÏìÌÀ^ÁNR"J%ªf…¯àCº–üh§ ¬V�)Õ |HÛ*�ˆµŽ5dY*xwõl¯¢.h³çÆYu×oÝ’Gf.æukœs·4[¹^ëB|ãìŸbNÏÑbãÊ‚¶w%³3÷cø± %7¤ïv;çÞ”wL¡EHöRÅÖ^ ÈwµŠÙ„@ S-Ê´ïzìL«•©e´žð’Å!àÆ¢wxÔ"b½^`ÿÏú–}£²OÈÂèç ~¶v8^¶¥˜é‘¥äwþ ­ûÙ2buI›€ûœswWsŒ0oØáœÛZ–pzí"w0¥eš&ˆQ�·P,zÆjŸ”>n™Wdº¤€”÷¾ŽQÆ»K‹¯ÀwZÑ,+ÀKxÍÍÓØ~|g‡?¶!XÞqš¼û–ãQÀ{”š¯J!"\°”—$Ô·ß¡a–µV§¦` ÿÀÛ4¾ãÛþ0›¶a¯`I¯JýÃû™Q?àt4S7þƵÄ,¦Éþƒ0�·˜©²“®T˜@§t—Ždo©œÿdA HöžÙö½Ð^²WDokKsFYÛûUñ/%ÓÊzæu¡½C˜tâ=¶Òéïéô8T9ƒ;ê짤[_šê1Hõ7—:c 9BX2^qcFäºû¥‰¾G×Ua:©~9ïΞhwO˜g‡ þ Éa<éµOÀ)áeìgã¸YAo|,¶â?„�{/6Ï�øʇ± ´«û®¨Ô|wÍ™“Ö¡X74ÖÓVP„Sž9G2×£Bñ!žý@ÆX/"ùŸ)Ý×ûn(ªeöSfá“6]C"7j•åì" FŽÙ‹vD×B^©.6vKŽ®@¢OŸuY–õgµö§@|þqÖ&€ó˜Ç<šÅÿsž AÆ$‡IEND®B`‚ukui-biometric-auth/images/Iris/06.png0000664000175000017500000000746115167732630016517 0ustar fengfeng‰PNG  IHDRbb«¥øIDATxœí�kŒ]×UÇ{^®S8¸�1ò¨®R\œ¢EU•òúÐ�S¾@% ©JB‚¤D´@*¨hAIˆò¨Ü $h ´´HU¥8 HE?8%!VCÜq7n»3É8S<žñâÃZ{Î:{ιwŸÇÜ;cû/�ûØgŸµ÷½öÞç×p ×° "wˆÈ Y³ó&Ç]"²{œ²Œ "r@DŽ‰È‚”qxŒò¤8&"Æ!ϦÃ|oÒàfcÕBÙmr1ÄqìJÐ(k‹·�ùmá®DäÖm'tŒ�û½uŒ[¦Z$±`{™q&E;±¥,=Ñ–92n™6í¿Õ›P'œ†\qVP æwŒSO±± 2F$®jôd W3 "rØõÅ]£<ñ)òëÑ�x ÃȘ™e$îhë¦pc€)èhÜ”ó1Wµ;ªCâ¦6'›’bÒîþM9ÁGÆ‚ô=«,:;yÕ¥¨máû«ÏJ7�á+΃dÅÒ�Qá ààÎÂÇ» ØæogMޏÇ>/ÚçÓ¶-‹!„/�TPósÀí!„îRÙÑQgHf�GL£b†Ö'¬®#£v«ÖMmÛ�[tÔ(æ’6µÖIǤ<ÿ_‡‡EäAÛ>í>ŸÎ$fÞÎ5b¤pQ3ÍZ×$"oÞBx°gù¢»¹Ó¶*< <|8\!\ÎoEDduQµ}YÙӔ㨟ý‘šÞüŠ æñ$ðŸÀCÀ�§ÑNnå�¿ Âe@â©�^²}j O ü kV­Žµ‚ЦtÇ�ãuý90X‹È�Â×: 1 ¼ømàg“¿Ÿþøð´s')::n¡f‹ˆ¤xm–šmÍöG€×?�Z‘Çç€?þ%d-îÛZŒy˜9à–ÂóéÿC³¦–'�¦P~ø¥¤ÈÑÎÿ'+7áöMÈHÛá5w —Ýç5àVà6àÇ9BèË82€K4$Eti±Š߀^ "SÀ4Ú‘¿¼')ò)Ôôg�'€eÊ$4%#mÇ "< ñ{$ä;�W'�w¢±Ñ[Éç�ß¾†’á·K!„µ¼ªG/D8¦P“ÿà»]‘/ ¦þê£ÿ¸¼˜g0>N¤d¤í¨#b ?ü*° UžQbÞ ü4p½Õ÷ðaàï�o¢V‘²šÝi :‘°ø à\‘ÿ>œ²2³¨UÄÆý1Äb§7%#mƒTì‘°|ð>+x7ð¿hçî~%$⤕ysQ¶_¡ƒ…´"ÂÅ€”ˆÃÀŸ¢)cÄŸEAÔ4ðר øàß(˜$�Œ`ßa£e@a—+>G.SdE«hlø;~¸›"&\^¼ø~wžue6lM²­ÆD$V0¼¸�"ü:p�5(–�Fö[­ÌgÑTq’"¦4%çµ%)“àƒs Ñ2Þ ¼Öêø$ê‚¢û‰šÿChÜ‹ý%k×7),bÅ·’k�ˆ0fl›2!~×ùªõӮ̴5ðVæ14^xK™L>7%Ã#‡„5·ÅNžF3¤ë¬ž{€oPhx$dø5à�Vîà')Æ+”-c%'vd‘�0�jÆ=N˜£ÀP�;úÛ�{�½À‹Àï¡ã‡i6’‘îsÉ(‰ÊpüÞo7QŒôB•Êáµý6àÔ:–ìó#®œ'd(Sƒþ\oYABì¸ßGM”„?BGÅ;(\V´ˆÛQ@ÍýEÔçNWl“îÑUù}%qÉ#ÁÚ¨í_µíÀ š^•NMÁß�’ñ�Ào¢Ô46ˆˆÈ 7•3 >AA ðgÀO¹"?�Ž@ãÿž„Y4ˆ¿x ø E§{býgo)~‹dìF ¨Ùir, ”SÖ*¼Ï¯ ²ßü¢ÕùðYÑ¥äó ðjÔ;ÜhÇ|µúøj•ƒÀ‹ð>Û“ðJÂW):2u7?Š’ª1‘ ”°ôø´®)k°›Ta8<‹¦¢‘„R¾oõ­RXVÜOP¬gÜÜ ¼ x†ê1Êet2ònÔ2nBÓÝ}¨Û>ouG뜠< ³Ž�gf “¨ŸOI¸Í·#QÞmD"ÞlåÏ£YTt=¾“}Ü™AµÝo;m‹7ShÇÝŒ7‹*B´œ—¸m‡;_j¡�¹:_ïÚ“fvñûsÀ;ÐÁ À�‡Z—?fBD*½Ð°Ìèƒ?¼Í~;ƒ¦¡OPž~˜L¾¿¸ÁŽù×DðªÆ¤–;iõÁYñÌa7:®ù.ÊÄúO]aüüu4c�LÛV÷ý×QW†µÿs&CHÊmÀzãl–4 �Ó¨K‰óùO£þótJÀ§©>]�A'Ò"£ì ìË'(|v œùD_ÿ ªíMq#Jäó>Ûûîà"eŸ¾‚Î+½õßgm÷åÒòqûtí]èzÈ'QþhSñ=óf‹!„ 1}=MÑyûêF ;6K£F��ß©½[„¥¬ûíëúÚ€�²†â™ˆ¤6 ÷¦qX^pmÓ�`$ÜD‘¡®˜×t=“óï&S¹�ÓË ,0fr»žÔ¥è~p]ŽÒ‡ýqÊýÔ– ¯Ý¹i騈h’žGÙ;Y«Y‚Ÿ9Þ0 »aÒÏLð :XF¢q»j –�YÎ59O ,åNƒ'wµvKf ÞUN…WNƒ[&ušnn*jx“�ÚYwξ±Š®²åÂOƒ´²ÖŠ˜Ðl=JdD4%# ¿#÷^5³Š3 ÎÑgs®�"‹m&? qÞmà¢ÔÀ‹ŒŒÔMåŽ3Ýq7 *˜œó¸õŸî6ZXksDJÆÀ“šKŠ—•´]÷u]Oõ"ÍR×ѯ¹Ü}öõ©œ¸b2¤#œÎ4mcÛ;†R2v°™lœäz:„p¶ªÜ8aV÷*ûºB8™yŒ_Tkݶ¬‘Âl')†þ×7 ÈgéwR±WT,]—1åzą̊µ‚µ"Ösþ“”§¼¥W'XÙ5Ê)éþ ø£@ªÕµ.ÎÖÑQXxô�.¢ë|{¯iÓå@Zi¢–Úù¬"+n&·9Ð%%òƒöNÕ•o‚ÞnxO¨¦”f­\¼€í™ù}¯0%:„¦«µŠaÖ;G�WÑ‘zoëû}?y ^«h.þ¬o ˆì®{¨adìGeL•fÿø™�%TÁü¥6�Ñû³8\üð«hJ×ËÅÈ› #`/zU`Tª‹hJ») ´)E�Ò•ƒþ ¹eTó¶$!æ‚ö²qnìi«nQw|:è�ÙO§±ÙÒ÷s!„·V•i À�hãü•z±{ÝÆ¬a½½7°qä~��Ü�èy?<BxmU™A÷Gć*v{0 ëîj/ �SeÚ…º?ÓêeêL€�'>dq}‚YåqØ*8MÍÞZ5‰6~//ê]Egk� }[Š›ÙEuç_´s?Ûg 6—t;p_á]uå†=Áì(ê¢>Bx{_ÂYÝuî bɶeZcï&½Žúk¬Ññ@ïqKô!ö÷1À%EäÜð ØÙEÕÔWÃö �VwÕ÷*zãÈEÊ—ËGL¢�ïF­C´¼ ´\}Ë�ó( eà3hsˆˆ.Z…�žñ—q¾Ýh‡ÆYÖN÷% Vµ†ZÖâ(.f³6œFì“•¾ú¨�œ‘ÆÌÍÄ{¤¯sûˆeЧÍ,£³Ô÷ +.ÑéÝ¥#Ż宽²`¤xµÃæ=Ð^ŠGDÝ”ls8eÝÜ· ˆ¾QeÞN6¾7MmA8æeo�Q¿Og‹Ã”3º£Ñ¾ÚAÆõ¦©-)¿si4–P!„'㪋‰gï›f$yÝX…!¤üFß¶D»·„yŽ¢¯8‹ñ@d«½ÎȈ/¬X¸ãFb[ãe±u}ÛTvÛ¾PÜCôÍ21Äv�ß ƒ™ï §9ÛÒ:Œï†æ·´ԡ”·Å˜£‚€ÙîY¡hŠç_Q?¿ 1+öŠqt[¸¡\˜–ùW™-ˆ÷±Æ�Ä�ze¹²HQaöb1¶”WÊÉÅ‘qÉ1!Ç"c–åð­ý9\±Àk¸†kh‹ÿy»ò´» ¤IEND®B`‚ukui-biometric-auth/images/Iris/12.png0000664000175000017500000000670415167732630016513 0ustar fengfeng‰PNG  IHDRbb«¥ ‹IDATxœí�kˆ$WÇ5³;›Ýd³›lb|fVAÑìƒ ³Ìg!*Ê$ ‘ˆšDA“((*²‰Šfƒb¢"“H@…È$âQ™�Jí5 ¢&ö$›l˜ÉLþ~¸çnݺ]Õ]Õ]]Ý3»Šê®¾uï¹ç^÷QÕp†ÎÐ’4'iYR{Ä|´Œ�ë$í%/�‘¤iI ’ÚÊÒ�òÓ‚¤éQð3t²‰:¼lV1R-”´ÇøXÊdf”¼ÕJ’æ7‹Æ™ÂÌG»8®ü–"I³æ=Ù,2+¹.‡ÿÍC¬ [A£¬/¡…´6…»’4³é˜.AÈbh£æ©�¢X°¹Ì¸$EжC„–­®Ù¦ÝªõEr©mmË�e.i¨0!-(;ÿßM°Kv,ŸËÜë…²Ð0J]T™¦ÒTu(i˜½ÐC`‹rV9«’3�rc�¹¹ #ê\ ©­–D%©ÖŽÒ�ÛRÍ å­|Åš:WVèÛž1PÕ¹yÁ·??Ķշ<ëbJéî�<�<¢dcøB(‹uó¤Ô}6Ÿþ+÷†Œ©ÑMG$çú ø¬“ÅH@˜Ï騂\&13¦ È„4«â}W›oÝ]�»72Q:@lÕmþðë?kצչ­¦­Í°P.Çn(cÚÊ®cHcàž”R/ì˜ß¼�q#W \2-�_ó9åÂ2#Á“²ËžóCÈRÔ¿ñZ‹QÖ´¥—iÖØ­e(¬;”ÈÊÄ}]Ò8¸ªH“ºu`&d¾i>Ë�:ÝfnpVç§vQÙFHÙ¬¨p�1Þ ¦{�i¼§®S¦„í _ÍÇ�ÈÍ´ÕÅßG€�M\("ecAWá*»‹£Ùþ©s„\8™{-‹$JÇ!3r£ãy;j™/R:c*•X�4>ZÁ=Ã�=ÍQÙ2� ”?B�©–)“¨Ÿ=]©Ü¸#Ì5Œ ®ÎÞ¥|b )­xÈ›êF}�†•M.r�‚û ^ÿ²rÔ@«¤–„�Èw*ÿ«²ÔW¾¯TÃ+)‘²1±¥º‚¸²Á«vßBpßÀš¡îk½¨ò¢Œ²nµ’0•n�êȨÔij¥M]©[ªeû�³ŠÊ`Dí•vOÁýsʦ·ýí’WV+ù;e3�ÚR: ¾†]‰¥ÊÔ× Tƒ¦·ƒ€`÷Ï÷×6ÐQ÷eÏ2Tiý=�CßÏ‚+»û¯<ƒ‚`uœJ5+sÞ½Þª™SUÉ‚Â8Ñ÷Œ@e0”ÕäV? X=KVGmóJêœ×ê—JgAÊf~ƒŽƒB0Ú…õ©Ë¼|�¶¬žºu¬QƒR©¾)°Žu9`ˆ Ä3�ƒŽL=UÊ6ŒÑéàû´ò×’¥*¾t©/œXlɼ΄ý~'nû"ÀõMoU4�/á¶(÷\â¶PB“{ÙÖË«ìë~à(À„\~{È~¸3I’[æÍ3t¨G™:ioï"Ã#ÛC|§}=,if‚¬v\ß<[§-…²>4�sžnn˜™±& w4â^ß`ÏõÚ*¤t\*kRv$Þ•J«UcúÕ;Ô»i°¾ŠÔ2nÔਗ਼f¡”/Ás ÷–,W{,‘ËH½çY! ܧ Ô¶çHéȺôÔ€Ÿ¾¨BeÇóþ†~eÕ�‡òùÈ)Øêcj@õ�œ{Ѳ¤žOJOKvO [Óª²¯KY¿Øû†ü:JϾJš�´MÒ‹ë—y.]+gýçH:[ÒNISÆÃDÄ›§�gÖñFª~Àè脤Ä:<%i— c�¤ó%] éöúä�K¿–t±¤çIz®¤gKºPÒ>Iç)h—¤+ƒûqÓÓ*!ˉ¼‹ÁèÏÝ£}0ã,‡ä¿88ØmŸwÛwíVàñŠí”¥Ç�oX[çmïŽ�·+ƒ{*i»"‹éEr1à^Ò _ø@haÅÑP*€a ßm_÷o'¡ŒÝ8a}©L}ÐQà!² øÏ1ÏÞl÷ýX÷¼›µô%a¿]êúTn×Ê ŒÃd-£pœ!çvv»€{€Çì§w“! ¾ø|7¾ú »põ‚?—bÎÞj¿,Ùµ]öû©³¤³$MÆ�™Â#}ü¸ç£Ñe³‡YœFy»1I’›‚ß·ÛÞL·o³boþk×·Eç ûž_ |È:Ý/= |§™ž±ó†}Þ>¯ß¿�³ŠÀëí·øx:þž$ɺܮ‘pœp8I’ûz1Z pÙÙ�ÐQà½t‚r1ð3+7ðYRá{°¼àÃÏþü,à=ÀKËòÐ?�¯ãÀ¯Â€�X ¸¸²�¼?{ÂkkÖ¿Ú½+À¡²ƒÕÒ@@nðùNkó€ðŸ�~zàÃÀvÝ¡eä�1¼Äêxy 6oÇ_q‚ÏÁ ?a ø*Î Ÿæpͳ„��À·€×÷á,Á»ôžT I¯ÂùƯ€÷'qŸ"k/î°²>iðZF70&�ópÁo¯ñòÿ0ð²‚�èÂ:ð&Òõ�£¸Øk~|\|x™Ýw;ðQàQ`-I’�b­lÛp‚¾çjüìäÀÕÀ*)! ×~_Ï�‘µžÉès70&HAHèL8Ê€°^Èû�Xã&Öü„K€/’ö›�/DeÖ’$Yï!ÚJ1ƒ0…Ø qB}¾ù3N Êø{ö7‘¦r·¿£Œ<+)F†Uzƒž×­þp.\’ñ Y�®ãâ€ÿ| i"røðƒ ÜÀ(›5y�zßïÙ‡‹>˜žÀiÒƒ¤áï{ði+÷i ÝN6ÓòàÄñ£v)BènÞ�K,À%?Á Ò[�ÿ¼†s‹³þü¸ç:Î]ÝT™×M� sЬULçŸ!»Ôù]œv„å·W�ŽXŸ¾L$ó}^P�ð`œb78Š@ˆ}þk? úoœ‚d\Kp¾7&òôKàQ™µœï¡e<“'ç2@¿†ìHü8.õûWTþ�ÀeÀopXlmñá�ÈKwc«(!Îz¼{x n0· |—-…‚|¸x.ñ7>¹çš»Ðq­ÈEu¢„5Ä×.>…‰‚ˤî~n÷e_´¢zâºÁ\f0 ¼ß:•ç"¼¦vûý .}�2mÃeWmœ–L–¬§l{ñï«v¬“ÕÔðÚºñ¶›¬K;‰sAm:5ýéœkEí\�Ë&Â�§âzVC ¼<Á™àA\p½‹ì*o@_ËN¸™pÂ2Oÿ³sÑýUÛ �p¤žÏÆe|;ìÁï�à2¨�‚{Ã9þŸÏ~�ù àOy÷Æ›W:†Ë~&IòXQÙ²d1gn2oGôó:n^gx¢ìÔ@…¶§H§¼÷â"¤Ukû?I’¬QÉm—9 Üœ$É EåzëyÜ`åh’$W×Ŝս¸€â-+'ì8IÀHòk~}dWAÑÜ«I­RIü”ø±$I^Ù­l™qD‹:Þ]Z\ÿ$Œ}8¡Åšêi7\%M;CšÄ ÛgyEä-ï µZž§À£€ó(]§ÃËá+\± ÿ>0—ÝÛÛƒènz µ � ¼+I’<5`}=Éúp§`×—ÙØ]v®i—vÃ-v /ª�¹™8`vgO'ISÁ“8‹9Q§¯¯BJß]»KŸ­h�ÏV'¥›Òêó@ЈߩVËÓ3[�eÖPøî¥±åO“€ÐRïnRÓÿ§3æ¤ìûþš}�–FõOScFÊþçR3–�ÃDÆi3"Ï0ܘP‚™ð™Š…‘2Ó )ûrÞ¥±è÷X˜gC${ Y)�×kS•}cp{+Æ�È Š_á0¤ì;Šú~•Û8‘:_ž8œ÷õÕMÊ>¢´i­ÃÝPk¬­ ˆrLySŒ9rhk³g…r)^übƱDùS »6þn¨,™–…OTú÷³Ž4†¨óIO¯,[ €˜rÌ^ñÿ1(›\ô÷ÄÍJŠþúlļØÒÚ_†äÆ[vx†ÎÐê—þhH†ôŒ|÷KIEND®B`‚ukui-biometric-auth/images/Iris/04.png0000664000175000017500000000742715167732630016517 0ustar fengfeng‰PNG  IHDRbb«¥ÞIDATxœí�Ë�]G�Ç?ÕÝiÛ�MllÒ`äàðp‰Ç,HFÃi$lRÂɰ`mlXþÑ 1#X ˜!!Ã0#3,w'Æ‘ÛiÓI·¯ócQ¿êó»u«Î©óè¾Ý¦¿ÒÑyܺ§ßß«çØÃö° "OŠÈE¹9år\Õrœ‘Åi–eÛ "‰Èy¹)ã83ÅòÄ8/"M£<[­ðÓQ…/ªVLU EdQËñ\‚�ǦY¶A!"çv‹Ä©Àœ‹4ö™�ZÞ"ˆÈjžÞ-R-9›(ÿîñ!Z‰ó÷‚Di]¬†\ÝæJDÛu….€òŒÕŽi—)‹Èì.5.D$hw”¦GÒrSDž˜v™¶‰úN_ëµP�„ ¦"âDdVDæDä>™‘ý"r@·…†-¤Û¯ÿ½Oï5+"n€ò�5àɾ÷ë\ mô À£À�s_ïxŸ l³æxFËöΜ—”]€·Ì±˜kÜ5çwuÿ–sî­É[eËþð,p?ð”sîG¥ÿ�щ%aY PL‚Jbhì9ªÆ×ìï92`œ�BƒÃ8Y¢óQ8wÎ ˆ¸€o‹o:ç~ÐÔ)´&BÔ`©$c ¶9êɘ¥jhKFj ¤Xi–ÌVJB|<“2¡1JƳÚ&�4£‘9ú¾sî[™t¡‘C£çö–Œ°oCF\+¹%$„kE$˜ý"RT@ÿHG3Õ–ˆç€Çɘ#™îÃ7dØÏQOJ2âzÔaIˆ (!áŽ9·ÛçÜ]­¿5S�;ç~ÕФh„vb¾ <ëœûRô[ ìc2Rä”’aýDLF\�mH°[®ñGú[LÈÈ�žŒ?54íXj¡áÙñª÷¸sî–^O`¯ÅÇV3,)3Ñq)q$±oKBNì>�`¯m˜k_ íåœûXI7‘bØø€yòDĤX­È™«2Bd“š“ajŠ¥H°š0!ùfÛí{x ’õ¥%D\Ä;ç§œs?Š´ 1OÕØö8EÊ,ióUGÆû�à°x·o?°®Ç·t{xÅìSRŽ„”ôÇ×ã-ü4bCÏßüI}Ñ9÷Óºv®%BDÎßAYUæ©;¶!–¸ØdY"îÞÆ7þCT�Þ^Ðíyàï”ù�RÉ[LÄàƒÀïð}®GƒIO!K„ö/+xVÿNE‚mø)ÖdåŽ-A>¼qÔá5­$Zé}zü6à`Ã^Ç“r¸ªõ²�_'ù‰ã;æØ’®}ø ß:"B¨ú8ðkÒXRçuZó0ðIà™"¬â}E·×�7Hû ‹Y`8À{4“Ç:ðÀWH›šœ´oDûpœJó'¼vgCÚ$¦ã¶üã¾`>:�÷u-ÿ|xg”íëÀÿ¯âÍÉ›¤�z<&GM6dµ>ášç"ž˜ù(ÿ[xBþÜ ¹Ásû�Äù§€ÿ.8çþ5Ñä�>â!àeÒäÎS&êðàÓQoÿƒ7·×kºb_’ÓŠ ±í¿<Ñ}0o~‰7a9IO5xê<\û)ð^2¾¢‰ˆÚ5þ¼V*\;|ø\tëe<!­A¹À““ýŽæì|@ð¼�²¸ŠCzžî„ãw×�©AÄ&"f©·®ñíy â+À—£[þø=Þ©ÞÔ†k":Ö.Kˆ,„ñŽZÊɦk¤÷{;Þ,~±í7åþ3ðc|8\BÂz]š0$b±I„J<m%2öq…ýg€¯ïŠ*ò3à6Þ<¥…ý¼J哺wœÎ†ÁÖLÙžõz¦±Âµ|?iï_À;ùSÀi*_²ü/L¯gî—jxKÊsn…æ®%"מW‚R&Âþ~?ðUàß —�ŸàUrb~›JÚ~¡iJòi[žðûºn£¨Qµympô·ßà�õ:žÔ1uzEëôb¢¡sùÄ}‚KDj˜95♚1[À‡gÌõkøðÓ¦}XIpZ‘Õ–yÙ ¡Òôvˆ#Þ‡ãCÀq=ÞÀ ‡M poRÃÿ^Ñ-5”Ò”ßĆ˜»]ÄwøæôÒ:pÅ9÷F”îð€ž¾êœ{©oÞCBDNRu&_vÎ]K¤‰ëºŠ¯ë„Ío‹^DˆÈQ¼ÍÈUà ^V�s—ûä»ÐÀäÃT�ügçÜF&Ýi#àR*m4Íûf!"ǨHÍ� Ò-wÍs+¡R½l.Ë¥sÎ]Á›Öž¸Ó"r Oþ�ˆP3s\OGÀK5ZG©:L/õ•œ­„ÖaUO�Ô5®sî:~X$�ñˆˆîšwk"´·ý€¹tÅ9÷Z&í,Õ8ÏZ.]ËüˆÈAÝ‹È1ÝJüJð¢9>žM8çnãÉCñK*¤­1ל¤‚’pDOGÀåØ)G8lòx±&]IÞÖÙçÒŒð‘Úk åÊÂ9÷†ˆÜÀ×ó~™¯ÓbçÜm¹ œÄG�ˆÈ>`¹�/Ò]×–¨´a]¥§JÔ~OÖ#"rRDâ�½RXÍmÌ×9·áœ»„wä§Ô"¡Ô4-Q‘°Ž�jIPS|ÄomÐVÚ‹oŒ�hd× *4kzZl÷Õ‰¿¬§ ´pâ�DˆÈ)ªPm¯ %×V`%›ªšß�ŽPº­ÚZ±¯MD¤‘ãrø/^3ÿ_K„vrééå$`þ·2D‡‡~Zu¤Vxšf Ç AÉ2UDuªi�v–-x(@+T‚Yê¥ š÷ZcÂ<Ž´ /5¿ ªK›ùÿkŒ‡·¨Ë?IDä˜ m¤zÁ÷i¼}5ëDJÕ§èÔYS_sOøð6IÆ�¦à]ÃȦûvÄùùëBÙçºF`ZÿF2ƈÐ6:êBT±Z›ª4úi9¥Ð¦÷kµ¹k(œ"ãDÜÝ$BXÒÓýFC¡‡pÒÁç$Ç~: Md}b<¯Ý sÀI[ŽØŠ8iþWÒY«C(t+ÿ Ãóæ|^#·GFŠ¢ (8鬿~oP…¶�ŒÙpž„Í¡ˆ�íz#´ñ—ÐèD$û€ÎPXhN²5pÎÝ‘e|}÷éþʌƷ6æ¿>…òÍÓ!Dì�6‘ÓàÐÐvs8DD†i΀^s{hÛÖ‡f·ã²‡M´ìs´… £Wgt2ĪÉÑI ·Ô]mlt5d(~˜jHÅ9w;„¯ËT�w¼ÏL“"4l‘Dmwp@y£®²†É£Í©ãØœ¯-êŠ"�Ú¦'<˜Ä tükS£˜O $œ¢ŠP7;Ì›º�Éñw›¡�A °ÖBC$·^›ª&D$,ÛrŒ qèWÌ¥®dXé. K·‹ˆ6áy({/mUM8M¥aËñüýÄ Ÿªà_é¡‘ÄMê÷œü)Åjé†hþ ³YRM°æh‚È ƒk$µL?3$¼MGíšÉshŒ¨¦1K`‡A:ikÂ'$I€š‰!CF@[2Bá÷5ÍN™<7€­ZŠy­Ôájÿ!Ñi†Ñ�ÆÝ²$@ÃT©’›©Ò~ÆŠùß‘º„QžašqH¼Úrèæ~*)n­ *°a rD P°x a¦Ž—�¡Rd;ŠÅ£—Zh+]¡­–…ú�Ú.ŠÓy“%“vžEÑr%ÃFSÇ 'ãí„«»æy‰îË~ÙOÛ†Øüþ`D@Òy�ð±øu[AY¬yÔk[¡dœÀ—1šð ;2°Š°AA”«˜-|xή÷£[Û%à(ãO<­ãCÚ- Á‰0+í ¹5¼äíHBÔerlìe"­îpïgôð©™uïkú°ä¢W‹v(À1|åìJ½uüƒ ½*7´¾G˜ì¹ßÀû‚^fHÌ[B]æ­—uo0 /Ul|1`AAÂÓ¥©…Ä�‡$z–é ÞôØ‘V[¦Þh>‹ToHξ¶Žˆ3zƒe^ Ø¢P³øÊÛg¯FT¯�»=´¦˜á‘ƒ¤]ó¾>¤#V“ôE^;Zú–ËΟ%¨¹wάê¶FbTâð+Iȯ±ZÁ÷÷["rø>/â-yïëU ß]Úf6ì0¾Ñr«¾GøGÂû—bÌâ;¼è+‡ y·îù¾ ‹Þ¢Ô¾šºôMÈÄþѦaï¾PMY eíõ\^«îâ5ke;³Éø÷5о)ÑëÝàÛ©žÙž§’úø9½ð6°5¼Æ¬Ýé*… t7éHõm¹óƒÞøƒTŸÚô›Kq&áÃNç¶$ƒ]#¬[G‚f´(Õg#{iê^‚!áªlÇ׈EäÌT8ƒ9º¹-$˜ÌÏHõ…³ۖñƒŒ‡o{4!QKÆ?�ψ,ÃÖú„‚Â,2ÎOµ0Ûÿ¢ïs;¢Þ;B=· â?<ü�ÈNûН’ñ´qX÷œßˆ´`g|,6yÒv×~PÜBü§“ƒ/õš¾)j‚ªïE#9»R;”k†®îh-È!¡Ê»¢Ï‘ à¦ìö¨P|ˆg?Qu'¢Zl'àÜ®0C¥P)»h*xS¼sŸª‰Ì¨–{‹€ µmˆ©…¼2\<1­rLJÈùÀÄ”Ëræž–þˆïܳÀ=ìa]ñtíó̓5Y{IEND®B`‚ukui-biometric-auth/images/Iris/02.png0000664000175000017500000000771715167732630016517 0ustar fengfeng‰PNG  IHDRbb«¥–IDATxœí�_ˆWÇ?gw³Û¤‰ &¦&¦v5’’Øš*øàS[|ZiDñVmQP«’ŠhkZ‹ H5©¨V´öIèK[Ôñ!«¡¡1Û&$6$fëÆMws7?ÎïÜù͹3sÏÌ�»w“æ ÃÌÜ93çÏ÷üþœ¿.cEÀ�:eŒáÓŽpýÓ.æ|AÏá¸àœ“²G�‘!"·wÓÀëð…<®çp”‘iD\0×Bž”%=ÿ˜ö;çÎ œ¹XV"Dd¸¸Ø`ÝüSÓÓ� ÈR†PàÐ+�„­À_£÷~|ø—¾³´Ò3t"Ddx3ðyàvóèYà!à àdŒ“´%£è¤\0¿IÉH¸ ×Wï>¼Ë¼ÿðKài ×Á“bãh C!BDÆ€ =¾|Õ<~x8�/À‰è\‡Œ8¶æ¦�~ ÷¯ÇKëà5ú�?_fP2€ó´LJ«DˆÈ° _�·ßÞ¨�Š×Ã/éó 2)hJFœ�*", 1á:ô•À{��oÐï=|ø�† ÇyçÜRݲŠÑ †€ `#p/ð!}üð]àßd$M�N†µ1q>ʈ¨C‚=¦€ÁKÈ1à‹ÀŸðRÒ©Yt=h„ˆ€Ux£»X¯‰¾ x†LM…cœ<)cÑu*q¤à\—„Nt>¬¾ܬßÝ|SŸ…0‹ !�ˆ06`’Œˆ/ãk xôcày¢ÆÍ½%%œSÈžôJôº©E$„Â/#á¼¹·5ÿmÀ}À:à ðià ÓsÔñ¶jIÁ$^=¼ø/¾æü‘<EdØë&dÄ ¼n)hÀ‘F‚­ááÿ>…w>nÒüÞü™L"Í{‹©ÒQ‹%aR� `ð[`¾†|’L BKDø-ViãÑu]2,RH°vÀÖþœÎ7çøú<ð~|ƒ¼ ~”<áXL±ÉDD$¬ÂKB á÷x� ݪ¬²ë2I)²ýÈÈ%•þ$Øs\ø�œøè©íÀuÀ=xUuðóÌÒ—Œ$" ¡ð6Á{�+)ñõ*ò$MD¿ÅªªÈ~T‘‘K.i$©{½Xp�+\=¿ø!žŒ{�Ÿ„Y¤�šš({ÐÍUf˜Ca¼ øž„{�_‘W9E„‘’")EF=½&벑 wRÏz*ñ¼ùöyz%/&þE¼�¸ø Þn±¶ºÝÜŒߢßðÝúß×ïîÁ÷*/˜ç ú~ŽdKD¬VÂù àƒø®áç€Ïé‡B¡Md‘Š Ò3EoáZc»¸±7µJ ¾Ì¨Ûçãä=�¸°—L-é¹c~³$Å~{E¯m!¿SËéðñèÝWL¸ð�KD‘®Þ<®ÌÝ<=�sEú¶èºéóÔøâçA*l·FQ÷Æ…(\Ù;öÝ8œ½¾øðs|°ì�%`©¯û*"€€=ι‡û…Dd-¾`ט3z\ÂPã–€y|7õ¹eNj"²ßÏ6 Üêœ{¼*|%"²?¢ö€sîΖÒX Y�WOëôXSýF_Ìszœm£Ë:"²OÆ pƒsîå²°¥DˆÈ�xÃ< LW}dPhíÙ€/ø©>Áçɤ`‰¬0Ø«~XÀ“2Ë2#"÷ã»Bö;ç>V®Šˆ'ñ[79çžB×â»I6•YÀ÷[ÍëqÎ9·˜ðÝq|·õ<9kð¡ƒ'ä´sîl­ Ô€ˆÁ«¨Ò²,$BkèSÀ¬sîæ¢0 4Ž/üÍôÖÞPSÏs)…^3îµdªn-½m¨à4ž”¶ãÚ婲òìg#®qνÐBB&�-ôÖþYæ—Õ°ŠÈFh÷Ť¹ŸTÏmíHC@’9'�%Â|ï™kÈ7àIèvEŒ`FÅ$^×éý°£tö`cèPì >¿Sz><¦þ­õù[uª�0År¹PÇsjêÚv»CDdíùÚ1PÇÜeÔ‚-ëucäõøÕ\F5ÛuaÝè¹1 ±bÒ†wÈMÕÅ+b~S¬wÕ¦+¾‘¬KÖ9w6¸¯3d…·u�‘&E(ؤ5‚¹M©…ÚºD¨Ë�ºCÇcЯMjŠ'"�Z§%ÜZ�K@jÿWW¢Û˜-n&×µÛ`î6èZ&#øßuºZéLÀ| žÜBe¨ÝN®ë¦#×Å¡›Ÿš’akwª[º\DÔqÏCÚ’V•„ÊÉu=�~*‚Ï3€dD5.iPÀÁŸTÌ¥N`ˆÆ«%•«Ž g8vƒ«'5Ã`j*Ôð: µ&ζÑ!ÆL�íi$­6¡tšiéÀ�!# .!ñSýF§Lœ‹ø�φ�©WÛ�ˆF#Œ†„ÐïV9×·r¨TɈÕTj;cÖ¼W¶N®(Î0ÌØ&^ªÙuc×GÔ–­°¡£²C„뾓 ÔÔÖ2´Ù†brï¥&ÚV€¦…PWÊBþ:u'Åé¸É´‰¿tžEÒt%ÃzS[ã퀭»Æy�æË<~ÚOÝ‚ÜH¦Nju€ê$8;øPª:¬»•\l|Nõ[ìMw®IÃH­®"má —ëF3Â;À³)ö¡`ýDíéúM6WŒÉ¨ŒTUÒõzÛt Ü~kŃ4sƒ¶~£uI Q4Maº%øŠp¬n›n7“QYÀѼÕÂ5£F´†£gÕPÅ;vP­qÞMË×ÛA²¦ÿü$ª2ƒ|‚v;[EÁPqßq­\×’÷ŒW°Æ UÔç?H¾Ë{gÑôø‚E Û]ØÑ2âZ]ªât}'™„m0Ð’ƒ6ÖÐÅK™ | —]ê•l ‡‰HmVª¤‚¥j³:ñx`´¹¼7^à^¸ ÖL`ù‚F­D;ñîjiÅ�ÞU³|K}å¬*µ(0^¼/~ÒfPDÖW,õZV(ÛðiŒ+MÑ"sø Öê´aì<2fÖÙ­ˆuÕý Ù"vÅÓÞ¥Jæ^aæ �!7�¯y+’UA›éí;N$Õ ¾ý˜^î)"³j¿¦»ñ;—½¯iäú­-ä÷´€lo¤�2פ|wšSx[0�ÿcû�gœso/ SµƒYØT±ïÆ€ «K‹&7î’0Maµ¢ýšZ!@ã ›,nÀï`ö·¢pUD$o X#QU;˜…m݆²×žé)Û,kAã>Ù¦!V•t+}6¨LÝå²rcÀ† ,SagÊy£5~ Ùþ~es¬fñí�Öí–ˆ|x€ •�²ïkØp`Uòý0¶_he³¾;ø…#a×a?Ø~»]É;K{ëûz`4 x�R¨’RˆœÕ¼Ç_ŸøÖ“íL™º…hæÈ6å�]ŽÉlš‡|»Ã9÷ƒ~ï¤þ‘G×êã β6Æ$[³¶ 瀰l(ðE†°Sf*Œ£ÓºJGDö‰Ç¾V?|‰ADžÔr:�:i¢I$4’½C‰à"‡©¬Ã#A#Z/"G4²Û†ÑECµ«C�p÷e22hå êè̲�`"ß­‘ŠúʯJ( A]/�$$Â’ñª³‘f®MHHÌzCƾ‘&f!"{M¾Ÿ\ù^â¹L‘kŒ=ñÿ ±r dÜo Ö%g7")8#þ¯V&Dä6“ØÇ¤Ù†U+ "r£±!_£WEý â{ÀÔœ‹R:”«†Ž¬h)(C�(_mŽÎÈÅîŠwñ‹jÕŠ#D¥ØVœ€½…J…Ö²&ƒgÄ÷‘Ú�H�ÚÊri£@ìE bd.¯ä�‹[F•Ž‘@ Ù˜qZv_Òµ?âÛ—lð2.ã2šâÿ5òkç³É¬äIEND®B`‚ukui-biometric-auth/images/Iris/01.png0000664000175000017500000000603215167732630016503 0ustar fengfeng‰PNG  IHDRbb«¥ áIDATxœí]jGþž$$,$l�°‘‘±À‹ƒÌgO�ì œ=A²'pöÊ ’=�²'0{{O /+"4‹ŒEŒŒ&Œ!1ÎÛ?ê½éššêîªîêéI £uO½ªïýªŸM(30—ó^ô¿Ø÷ª÷è Øzýî¼û¾+{w¿«ý[Dô{Q›ß⦂™¿aæ=f>kYŽ#‘ã%3ßmS–‰�™3ó.3Ÿñ(ž·(�‹]f~܆<�C*üƒSá=±ŠVµ�™ïН=„|Ù¦lIÁÌ;³¢q¢0;ŽÅ¾šVyƒÀÌ/Äÿ*~˜• ‰•¼ôÈ?;1D*±{4Jêb[ÈÑL¸+fþræ„€òÊ¶Ž¶eÊ… fËŒá(ÚÞTYº£-gÌü¢m™š„§¾í[½µgiȵ³‚•\Ÿ âAÞèø‚ˆ~Ë»6—‰úotlýH]ˆö܃iø¥’ËûȬàŒU†¼²{c9=˜z5NŒ¸¦ïüDDÍ»®ˆˆ×¾ðý«W¬XϹäÀLÃ÷\ÑUÀïθcI‹ò¾šsù†��DtU�0óŒ‹ÊmK/¢¡ot‰èÏ š‡iüû×^ÕÔs½�F�,{™«[°à)ÿ# )©ËVïò&¯=ËbÄc"ú_Al`\ûÈ*?ÑÀÊÌk0„ÜÃ8)]ïSÊ$f 9±¢4kªYø"Œö?pþÕƒiü�M– ñë0¤Øè8NA›I¤n^¬mŒfÞðÐùúÀ˜{1É ¦¢0w`bÒÆ­¤ CHR—e#9¢]�0†‘ôô)LÆsØf® åÝ‚iø_ˆè7!Fc™2pcÉÉ(ˆ70ê†FL[®ù#²ÊuÚvOÄ?“�޼n�ú0r'U $Dˆ–oa´óõžˆNœë¶­kZ'AÁÌ÷a¬úD´ïüÀŒ¦ÁÇDô!• µ‰pL0ià˜ËaæMdšõ+½«[vJ0ódÁzL‰ä·®=˜ºÖvUµˆp4 ȯ€mþ=":¨Snð¸Íÿø‚³\·…Œ´€ýº�|®ê�’) ˜@ç#A×ë:UËl¢Õë«�¼ëˆèÀ1L}l‹{®ŒJDˆ›ÑÔtà]ÁX”Ý‹~×d XR‡ž|\/j\‰‡ÈÈx&�ÄJˆ&B:&vq˜tÅîËÇ~ŠàÌÌw˜yE^k̼!¯•º¿-8¶þvûA#�ñ©C˜¸[¢¤Ñp»ö…t˜b$ÕËÁšUÆqÁu!eÛÁ>ïšÚC&DtÁ̧�ž63/Y1�3óLVµ à3/Ád…ÁA<È"˜y¾ @f — F7CÌ~†¬gÌüD:fU`[ni¹Dt%)oW¾ºà©x„ „º¦-d$\Âd …$ˆ«ÐØ0Äc e½0�ñ¹dvQ¥éËÇ`¿/Aü½|\FD/%‚™Ÿ"KÕ.a,!$àÚèæ^)ï´âí�¸ÚªmµŠ¥˜ŒH2ÇŽÞ c¥÷!�íMöN¬ûº‰ÆfêXÕz2låqGe !IIYFõ´lõK."¸ E‚h€º¥ZÖ �²û¥æc=&½”ò4Ê›á+ºÿ#FÓÛ?•ï% ÌJBŒVÛcNuÏE]ËÚŒ  Èú•:kk`ÈLzë%cŒˆ$–à‰G)kõ^a43&x«ì U30©)#DÈvvT… ³ˆ^áU�ì'6sò!¦÷k[sÕTØGƦÛ!ÿØ’�ÔUT¡“L HÌñŽýT@LdÇÄ�¥:¹pÈXðÄ–coW„tÖŠ BGžX´>/Jæö i¬A”9ÉIe‹°~ïYj«dÌëÀ�0ŠhaEÅ"Œ5®Ê禋¬»z°2d*¶Sß%y?œ“üÖÎù“Í:E@—XN 1™SrHj;aæ•9ŒjG­�¹[DÁnëÕ9ŒúñG¸Å‘}ŽXØitoN&Cl3I‘�(¹¡¾x*Ö7y`gW)Sñ5dCú]":×ôµƒ¬ñÖ™ihÃiT k›B5¹EHʪ“Géã9`8_Ô„’ÓN¦qÿZtŠÕâÖâ:ÍP‡æa‡.1šÇ $ @?Â5“»,¼*VŠn/®Ê12Ä!ÿ8´¾ªJ†­Ý¡i餈ˆIÏUöZÖ*–P¸¸nlÐOLðÔ° Gã‚&õkNþ„¢º€Á™?¨ì–Älwä]áè—LªƒznJ5<¦£vb•™dÓ˜!°‡A*Y«'&ä.3Í�²ÈPÄ’¡Â/•ÍNYe^hj)æIhÀ•þƒQi†Ñ"AÇÝ ×úN• ®› ígt­ûòöÉùÊÔiÆ”ø5rèÆÞm ¢°:P9@À‚ëÒÅ7õ0„ Ñ"»£㯤¼»ÈN¦ =B´=d‡òv'±˜MêÐ�Q°ïˆèïe÷¥¯vÔ‡ 8íŒq¶g[�Õw…ž« ~…NÊ …•è$wéàìÙr·�,(g�vhî@{Îâ±ÓH3KY›}ª›'ªIaí=ij a‘pÄ“xªOúy:SQNuG“}´·õ¤©)�>si2–àÂ&ãÆÅ Ç3´û¤vžGת0�>Ñ÷õTÔ{*ÌsB`óˆ3�ÌÓö8!CŸ©svã†cÓñ°Ø<°yÚ” ;³·Áæy¤ ´^í»¢2ˆùîYš3“Ö!Ønèhª­ Sž‰>‡‡€3žõ¬�MŠg?¢þh +¶G±3n(¢e{VÏØ÷VcˆãFme¹^¸ð˜=KC´–òòhrñ¢-9Z�²«L´,Ëók­ý!`Óÿ¸¶À[ÜâUñ‚ç‘pŽ%úwIEND®B`‚ukui-biometric-auth/images/Iris/13.png0000664000175000017500000000655615167732630016521 0ustar fengfeng‰PNG  IHDRbb«¥ 5IDATxœí�kŒ]UÇg¦hi)P0ø€© ‰ÀF�¨L5JÔh Áª“ÖDCˆ$ òÍÄŒ~­"A4ÆEIü2551:|0�(ØJ|ÄäBÀ1é B;íüý°×îÙgßsî=¯û˜é¬ää<îÙg¯½þëµç\Ø  Ú 1 Iû$’´4b>:ÆÇÍ’vŒ’—¡‘¤iIó’–”¥™òÓ¼¤éQð3p²ˆ|Ȭb¤Z(i‡ñ±˜Èì(yk•$Í­�3…™‹,va\ù-E’ö˜ÿõt`­4Ȭäæþ×N ±F̯�²¶„ÒYîJÒìšcº ¡uŒš§BŠbÁÚ2ã’)Ú¡±²ôH[–$í5Oƒ¤œöŽÞê�©C�†¬;+(" æžö�’‘„ù‘12BŠ\ÕðÁ0–Ng[Äd1ær6/—IÌŽ„©2!íQñº«µ7ï®îÕ™†(í vÚ6ÿüzÁï±kÓê^V³¤µ°P.Çn(cÚÊÎcHcàž”R/ì˜ß¼…q#W \2-�;_s9÷…÷ŒOÊN{v� ‹QûÆk.FYÓ– \N¤Yc7—¡l°îR"»'në¢ÆÁUEšÔ«³!óÃæ³ ©Ûmægu¯qZ*ºw(¤lVT¸ŒÆïŒÓ}È4ÞSÏ! SÂ¥ ]Ã�‘›YR66q¡ˆ”�=…«ì*Žá¶OÝ=äÂñ“ÈÜ[™$QÚ™•ëÏÙÖÊx‘ÒS©Äl¤ñÑ Ê >þE ô5GecH#A)¿‡S+C&Q;ûºR¹~G˜.hA\Ý+¼KùÄ@S:-ð�7&Ô‹j÷†•M.r�‚raoZ9ª SRKÂÆ4ò�ÊŪ,ÕÊ÷•jx%%R6&vÔVW6x•ÁÊÍåk†zÏ]ô£Ê“2ʺÕJÂTºx@j#£R·©•6u¥n©•å7jf•Áˆê+íž‚òû”Moë­’WV+ù;e3�ÖR:5ŸÃ®Ä‹ReªÕ UÓô¶ V~_P¾µŽŽzO{–¡Jóï�j¿ ®ìê¿ò`4Ážq*Õ¬ÌyïçVÍœò¨JƉÚ#•ÁPV“;u@°ç,Ú3ZWR÷¸V]*�)›ù5í…`,>O=ÆåkTڱ紨c�jJ¥Ú¦lÀnërÀ˜‰oˆG›öL=UÊ6ŒÑéà|ZùsÉM©Š{ªÕ–Ï ;2¯3a¿Ä-_¸eØKMà‹¸%ŠO{.qK(¯@•—÷¿e0dK/÷Ûé.à^€ ¹üv·ýp0I’ï™7ÏÐî>÷´Içô¿epdkˆÚé5’f'ÈjÇ-Ãgë´¥PÖ»'pîÀÓw†ÌÌX“; ñ°¯°ï|mRÚ.•5)Û•J«Õbú=w_ðÜHƒõ~R˸MÍS5ÿÎB)_<‚÷.y_ë±D.#õžg™4pŸº¡µ5GJ{Ö¥‡Ô|ø¢ •íGÌùue=/îåó‘sc-0Tch@íõœûQé)[¥ÊÑÆÄÖ´ª¬ëRÖ/ö/�ÿŒÊ£¯j>Ì]–J·'(Óèuf5ø‹RÕ£r#Ôlò§ •ûR¶ÜÄMO7’¥‚¡4«2È3Ý&´åó2”­;ø9£ì �z€*«•¤lŠVzv**×&•ž»V6q©5p©–âmøÀØ2Jõ3š4f`Ü)i³¤M’&%õ|­9ª¿Ž[Ë÷\€WõÁuÁ˜Ê­%�0MIÚ"é,IÛ%}NÒrC–%Ý$é|I;%�'é9%Ùfum±º7Iš0ž:^ˆ5df•ÜaÙ f£Fö ÂÊfBó’’@è[M;L@çKº@Ò…’^'é ’®”ôHMž’t•¤K%]"i—ñs±¤×[Z�;%�k¼Ü<ãvõ±ž¨½ñRÔÒÓ ¥+±Šfp½Rßã¼7I’/ô)sð1âcÀ£À$®W¿Éö“ÁµIãk"ØÞ|ø` 6”³�´ýª¯ÛYÀ#Ààà2à¨Ýw8™$ÉjNwàFSwÛ¥‡q_x¡¿@E ¬ÒŒ®JåL|“moŽØOG€Oÿ£ ¿/#^ \\˜Ãûd0Ë€à¯ùó�›¬üÀ @ö+(r.÷ é(ö½¸9�Ò �Ó˜R”Æaœ6¼ lÆ Òï7ß¾h÷Þ|ß®×#Üâv„C½@ˆ8‰äÝVö¯ÀuäßÎýö^à�nK’äö>âË¥Z@€óÿ80vÙ¥'€ë�Ñ ÆyÀO�·Ø½w¿¡€<0âvÑ„-ÀO€mVöË8×–'|¿}¸Áî_¾–$É�û ®€j i'ð;À¥pšÿ©kÚlû·?³û^nž!'ª‚·A9û~ ¬â„úv+s?pÝ–à÷ßÞf÷Á÷g+³’$ÉÉþÒËR]×ä…5ìÄ™ôǃ[îÂù׈ÍÀ^cœ»8FjeÀHìº-R+XÍ9ƒó Ûï®¶²Oã$´„R+¸øjP×o�/Ù=][’$¥GmëëP¸SvJÖ:ÂãÉœ}Y02¬Ò„pnÞ¶Wá²¢­öÜç� [àÇé#ó{?0J€‚Ÿ¿Èk‚G=‹Ó¼ÇÉZ’ß<>ÐOFû"02ìR„Øý¬à\Ô{€wFÏ<ü —å ?¼VÐÆ×þ¼>F.ÖS¼ —š^G6LEçñ>ä38ëØTqgâ2aøò±¥„[†"ŽqÊšB¨ù^`ãRë7G¢ø#έþ›bÇûã9ç{q1åp’$WäɼÐ"”~TñS¸œ? è<¶œÍ¸!ƒ«qC[¢ªŽàûóä[I˜ç�ZE±ûYÁõm¦q�øŒˆ§Ã¸´üyŠ5=Oàyçg¿Î>œ$ÉãyòîÄŒ1ô ð~àú ÊUÈÙ8ÓÝ+$ŽÏá:„~Ôӗͳ” èî'„nhçûwàÜ忍þ�à¬ô(Ya–x|î¯Ýƒówã\unZÛo\þv\gç縴³Høáù%î™Âuˆ..-¨þ(®ƒø éØTl)á`!d;jÞz¼r„®1¤çpÊö²Â ü'ú}ÊžçBªÜç¿ÈŽÏ$«ùá0ˆW’p½h …ú*μ֞°}x¼’ó{x-Îye6áF¶wâe²ñ}þøAœEÜ|½O¿•#¥Óž�Öø¬wRº(­ý/•ø•j­¼=³Þ(PÖÁ�`…ß^jíýéõ@�*sÕM*œÙ#%e¿÷7ÜhiTÿ45f¤ì. Çr˜Á8íbFäJ0®æ›)3C$e?λ8í óÉ^CVJãõÙTe¿¼´ãFdí/¥l“”ýFQíO¹�©û㉃ù^_Û¤ì+JkÖ: €Ð uÆÚ Š(Ç”×DŸ#€%­õ¬P.Å‹?Ì8v€(ÿo d×Æß •%Ó²ð�Ê%¹à>Ò¢î7=½²¬/bÊ1{iÄÿÇ lrQïˆk•ýõÙˆy™Y×Ú_†äú붸A´AuéÿÕŒ:Ù'eIEND®B`‚ukui-biometric-auth/images/Iris/17.png0000664000175000017500000000640515167732630016516 0ustar fengfeng‰PNG  IHDRbb«¥ ÌIDATxœí]Mˆ]Iþîëtgf3 8¸±ƒˆÂ & AtÓÙ+tºPÐŽ.w ¨¸Pìq§ ‰³r!ø2ˆ[_‚ˆ®æµ "¨Ð™… qñzAQ|=:£�îäsQ§ºNÕ­º¯îÿë$.÷Þ×÷V�:ßù«Ÿ[ <¥§ô”Ö€Hî‘<$¹™�…ðq“ä¥1yŒHn“œ’\Ò§+#òÒ”äöüôNÒàÛAƒÅ*FÕB’—„�y��1yë”HîŸ�…Ù,v¶®üfÉ]ñ¿–nŸ—‰•ÜŒð~bˆ4bú8h”´E[Èâ\¸+’;çŽé @fÚ:Ææ)IA,8_fœI�¢®•¥Ú²$¹;6O}R¤½ã[½0u¨4ä±³‚I0·´7&#„éhŒŒH�« aù$ƒ`‰ä%‹›CV¼M—_Wñ“€±Ì2w´¾)Ü$ :Œ›¢�y¢ÝQŠ7ÕO6E7h7륂DŽKv=ªL3:ùÄ¥¨MIË«ËBûCø1&åA²bi‘Qà!€«nEñj[›�øÛç…{†\Ëõ‘Çî8.Šâ�AU$žã>€Ë®Eq¯MaûCgHb�»¢Q6CkC‡RÖîÐnUÚBšÔ¶YÝ4½FŠKêµ"¤)ýñÿ*ÁÎ嘩ëœw­P¦CC碚ešt©j/i˜=]!°�Uî2s¤“¦¯³C3t›å)PMK0%ª”¤^=t·yÇ Åf¾BMÝËzͺwÔË‹lýû=ÖÍÆòìŠ)ºÕ1�¼Í²1|šeÖ5OtîsøôŸñÕ¦Æ:ˆÆõÍ|vˆÈbö# ›Òd;£0• Ò.Óë®Îß¼;Ë«7¼†Ðu]› ~­àwå·m–—Õ,yVÒâÐ y¦Mƒ\÷DH­°C~c ãFW (‰–‡�¯ýÈsú™ÑA°DÚ³4>$€Ìƒö­×\ }Ó&.'Ьµ›Ë ¬KJ$Ï„m�s\U IU ØÑÌÍg±ì6£Á™å5NËÔ³ƒý¬(¹ŒF_¬Ó+H4ÞRå�„(áRµkø¸¸™%+ü}ØÚÄ…Ñ�•Â¥¿ŠcØö±ÜCNŽŸæÞÉ$ ]?d‡¦w¼/G'ãEt#¦dÆl¤ð±PïôÿVš#ýÒJPŒ÷ÐCêdÈ$hçJWJÓïÐáŒ}q–WxgùD¥)‹xˆ� UQãÞ0ýä"š€$ÞÓA¼ûiå ‚E¦–èÆ´ò�Œb•K�ò}: ¯¥Dôcâ‚]qúÁ+ yoªÞk­¬ž»XEµ'eè»ÕZ¤[<@v‘Q±ljÙ¦Nç–:Y~ÃvVQŒ ¾l÷¤ÞߣŸÞ6[%O_kù;ú™Gg)ÛÏa×â…N™uBÙ6½m‚¼¿§ÞﬣÃêiϪ5ÿ®äÐø[pú«ÿòÁh ‚”q–jÖæ¼ºÜº™SŒêdA:N4¨ }M^4AÊ™K��+±<®Õ”²³ ú™_Û~�c™,�ãò *]H9]êP£ÚRVÛèìÖ±.Æ•ð�pä±mÏÔR­lCÝV÷ÛŒÏ%·¥:î©Q[*ÊÓ‹ Š×™ÈßïÂ,_€[C/U�Ïa–(Y.a–P^ï¡Ê««é‡déå ¹½ àLhòÛkò‡»EQ¼20o–¡k+žé’ž_ýH$kˆïÊíu’;øÚqkx¶žXÒ²¾6�q–~003kMìwTq`+\9_[‡èzÀYYýžø”•V³Ãô5(wO•;\°¾g/³}ªf¿YÈòÅ#|Çp�ù\籄&#µžç.pŸ=ÐÙš#ºžuöÐÛ_Ô¡Ü~ľ}¡©,‚òÂþPœ�ȃ�À`ƒ¡v×s^EÙS¶tÊÑÅÄÖ6ë¬ë¢ïW¿/£öè+ÛsçRv{Ô;­>gf‹�¿p!U0j7‚í&r({ì‹~¸�›Þn%K¶ƒ.«3È2Ý%¥Úâ¼LÕ»M?¯Ð_áÑ PúZQ« ú)ZöìTð^—”=wM?qi4pÉŽâ­.0´Œ¬~F›ÆôF­µFAýMܲ~¿r^Ý‚›‚1UïÔšX‰ÔÙ„ �j‰hƒwoõwû¡$ËÙÔÊ L?j²’b›Íûµ;¨:÷Tu‡ñÃ¥¨ý¬‡eÙï倡‡Oi‡(Aî¼Ä´E=Ú�fÏo³üýÄ<÷ÝÆ£²RúVÑjõ›”µG·ÞU­]ýÅaYÁ�åŽÚ´wTå!•¦o²�ÌtuMô]oVï›åå2÷�þ–rŒª�;ò»÷Ëãl+­‹5>Mè�"Nf ô‡=ú d ˆ¾¯Ôj–]ÑáZ´…åO™’�a9µýû³@³+]˓뷛˸G5…®o1ú�,VU –¿š]rݾ*ÕÄrðZ @—‚çÖfÛjºo?bJ³Íò@äœküà±üQ‹d­tÑí!¢•j±N ”M,[fÝÕÚ".(T"ƬºAÙ3Öý¤‹nëƒÖÁˆå=-¬vµn\WÄôî4Ó.ÜÛìzIœZ›#Ëÿ™$lìà[ÿÓí –â©«½ªlBÐ,egÆ™ºÉøfKö¸×ÝðHJø öð�è,­y–H—’v¾5ÓîÀÒœn?¿&ßhìèSVi4cOq‹®ß±Ò%åìûº@{—¦Ë¿³Ðøܾ®1²û¹É’Ýö²):†Ywz³Ö÷­º<ç�²kÅ®¶^»E碖]›m¢¾]±„9ó·­¢9Ýn™ƒ EлÊêø­´)xfùø}×úÒ¢Šúwà4ýª:[º£éÚjŠ¢xs@6ψn÷è;EQ|©ë§‚ðÓYPAtˆ­æ^VUbƒ^ïãî$ ’$/�Ü$¹Eò’ÏÊñÜŠÃ>÷Œ¼»)em�Ìò x¶ÊZ„Z Ñßx¼“MÛIN`COl¨ë‰ðgÏ…ºÏá�©kªßࡺ(çGEQ<*•ÕŽ)LÂq“ØÔ ε5CÞ]4C4Ñ ûœðíoúï)0�Y�>I‚ûS{_Er²(ç]˜/žŽabhí ©‘‰ 0)㭪ϽHZAÛãªÁØ€´#vX² hmfâÈ!¼>…å¬á&0¡�%Xjì+0^.Šâ;êoVÈV詳Þ뀶Cknö·,ÔùÀGü Æ3´Î&[-ш#0îø€ÿÂrNèU ´#lG„€NÔýW|EÚýk»mSúÖÙC`žoø"€?Á#<×CljŒ°) ꀠ-üS/ø€OH?ð ùÛIQ§µ„i@#"yF¸ïðM-y À+~#ÔMøVa…¯A™×¹`„m`ä\„”%|Àç¼À¿¼àuõÌ8@Ö“dó`m…µ'èMŸðmaö5ßðOõ÷ ”�Ñ–‘†Í¬€²eå45‚Ίb hKxÀ×¼OÊŸø€És§r.UÙVHMÒW­åˆ-8a_†±ˆø€WÜCŒ”»ÊC§µ‹ðAˆeH),'Âÿg`‚2ü Àwü¾Àí{Ö"¨ßäZGÝ�¾¼Â�—|À»¼ àÇ~g Ú’6‚ëº`hÊ¡*|À§`€€wüÀO‘Ð|Ä�8û='vd€ Å^À|\Šù‡4êwêÙÐRbñc«X ‚>ŸÂ(ËŸð¬*ë€_ÂĽ’¶Ã!Ãûû*0rG_c‚AˆÝÛë�Âò~)òþà·0ºªTº›Ãcy œxÀ§¼W½¿„q?¯Á¸Ö”¶?Îö:õL¥›Ê™šÀ�[Á}x®èE³ÿ ªâï~3<`­#•ié KgPgìª#B ö\ðgoø#Ê.'&ðÔùAä^[Ft,ëBìÇ€´Ïª>t¬ˆ t À_üÆe} Ƽ“^ Êß�¥»¡U¤@Ðlj”q*eüF Þ–¿]DÚÒôµN l]–?}¿g�øÃ0gT „XC8»ßîcýûÜ&€¿ÂÄ‹×aú ¡¥]f†�î'h7dËlj¼÷޼·¥Ê€ºŽ¥Â1�Ç›�,bií*‹Ðy{•ðcéçbµ!B:FÜb‰Ah)šÀï¨éô2&±BŽ “Û#lÃÃà·ªûÔð½}®+r\“5oª{ÛÐX*;‡¿Å~�݇®.榬uh^µŠÝŸTü¦ÏƒûØ{á;©ß­¥F;yÿršÙÏh iðIEND®B`‚ukui-biometric-auth/images/Iris/11.png0000664000175000017500000000675515167732630016520 0ustar fengfeng‰PNG  IHDRbb«¥ ´IDATxœí�MŒGǵ;ë¯ÝÄŽœ>ÖpÈ;!„PÖB\ÖN€°!wbÄA.ˆ’ `Í8 Ö€ˆ„¬C">’u”€ˆŒ�ð‘%f×±±µÞÍ>ïÕvuu÷LÏLOÏìzÿR«gzªº^Õÿ½W¯ª«k`ÛØÆ@DŽ‰È‚ˆ, XަÉñ ˆì¤,µAD&EdVD–$�C”'ƬˆLBž¾Ã*|2ªð‚YÅ@µPDöšó9„L R¶J!"3›EãLaf"‹�VyKAD¦ÍÿzœÜ,2+y0GþÍÓ‡X%f·‚FY]B in w%"S›Nè0BæBë´L…ˆú‚ÍeÆ%)ÚÂPYz¤-K"2=h™ú‰œúÞêM¨…@C¶œÁ:s�cƒ$$av`‚ ‘«ªŸ #aéz&ÁCDmñ`�OJ_×WðÃÈhÖf‘;Þn0­ÇMI2s]»£"Dnª?Ñ”$“vs})`‹ cIªžU��¼îBÔn¶W•7íÃ[�)Õ—º7\Ç�sßîUÀn`þvŸÉáÏØçeû|ÞŽeà°ìœ{¦VA˜ç8Ž:ç~ØËÍfêŽ�̧M£|„Ö ì^Óu»U«‹ˆ†¶Ý•-:jsI}­€5Ò¬¤çÿ[5ì¼sÁç2y}£ÌÖEŒ$.ª»HS’Pµ/a˜=Û¦ÁæD­rZJÎtŠŽu¦Dç‚NJöhˆ%©á‘h $�•#ÉÀm¾b�òž|Åšz¬l£wXö”‘:'ÙÅ ¾ü™>–-]·gUBI²z#O#OÊ¢1#|¶€”¹ªe’Ä}ÖþKþê 1¡7uAÔõÍÈY !Ö!a&§b³¢‘ÄÔ@„*€5Ò´¯»Ú|ÏÝ%»z#UIˆÍªÍ¿y}ÃOÛµIÉ.«Y’ͰP´#ŽÝPÊ´%ýCdÜ“$©oìXÞ¼…qW \˜–ǃ¯™œtaš�“à!éÇž™ù!#d>ªßp=‹‘´i‹¸œH³†îY†¤;ëŒYš¸®ó2 ®*Ò¤V˜ …¯[Î2�¬ÛÌíœ%»Æi©(m-�tTT¸ŒÆo…Ðm`ïÑrJ”p)¨WýýFäf–¤…¿�š~¡’î Z6®¤WqÔ[?ÉŽ� çO"s¯ä!‰$ã�)ÑÑñŒ•ÌI2c*Râi¤ÉÑ òô¿ÿ‹HhkŽ’îCzj(ɡǨdÊ$ªg[W*:î#Â9éG'.ÙÞ¥|b )Í dÈ›j…®GÃ’.r�‚|a'^ýc娀fI- +Ó“ï”üW¬Ê¢«x_ ïH‰$Ý'6¥ªN\Ò�W),ßl�¯gÍ�ÖÏ.Ú¡ã‡2’v«5¦$‹Dªˆ¨$kj¥M]·TÉòéÍ*:&#*¯´{ ò“txÛÝ*yIk`GþNÒ‘Ge!�ôþ »#Y$Q¦®¡ÒkxÛ –ÿX�¿²�Ž´~ìY=Ú¡ëwÁ%½ú¯<½’`÷Ø5;–¼õ};�œòÐIö]ÏtL†¤5¹Ù vŸy»GeóJ’�×ꥣ IG~½ŽƒB2– ï'-æå»(´i÷©ª£Ž5ªW”ª›¤;ìžûº2Å â™Ç^G¦E&èdð}RòŸ%÷ŠNÜSWuiq¿pb±)æuFì÷3èòE€u/U´ŸG—(ž÷R¢K(�ö¡ÈÃí“ô¶ôò¸}=œ�o�Øgœs_©Y6/Б6iªÄ¾öIú[C|ƾ‘©ÒÚq¢n¡Dd­¹Ø†ˆLˆÈ¸ˆì‘"Ò0YêBØÖG¨;ð8¼¿_%‹ˆC}hØyïW™nÖ�Wí¼¬‹ˆÿ¾ÜÐGB"ÎŽ˜Ï ͤŠNÉ“{XDFMãv£ >�VpÜÎÀjev‚Ñ ì‚#”m¸7ÈóxU#�y"Î8çmØ—ãÀYÔM=,"ç{|¿³ð`ªý£9go롬nð ÚÐBb¡%øÏ·yvãf1«À«Î¹õN �HOÙ×e¬ãn8ç.ŠÈ4JÙœ:%CDÀð{´ó=„jWƒöd< ÜÕiźÄS¤]S kÀ�Až´.kþ‘5`Õ9÷j™B�„³$ÁÂçÜE0" E†OXšŒ€þ·ý´x3°ˆ6úÅdü–zˆh/¡.(�„ðð®éD$ V±Œ„¬*:>:MBÂñp˜Ð;çž‘£(ІŒüç§‚d÷��X…oü�”ÒAC?ñsZ“°œï¶< ¨‹õniÕä_ ®�YHŽ%d^ƒËt>ιGÑA”÷ó§%ދȈˆìvá|ν¨ÝœÇ£ópx<Ûn•âÏhÿ�×1OŸ÷ïò=È¿;úìë¼ñÙ‚–p–$@�ýeÈ0+Ø¡@^ÈG-ïÝÁµq²d„ ð3”�~à*ðKÒ[LžàxW�÷wä7~xì Î;QBî¢ P@d†â d|ØA–mWðùW–ïV`ŠDkbÍ �k¨ë~ ¼LÒø¡öûÓq3ð6Ë÷꾊¬?n ¼uƒí>-ßÊm¡›ú&ðyÔ?î iôø¼Ë*pÙò½‡´ Ç&j㩞Œg�?‘&!v�¡ë|;É óÙF� ðõ³ó‡�ÇH^?~ ]ÐÓv€bd<@BÆg€O“Ñ KÊ´³{Âòܼ6¨DxxRƃsø)°ÒN¾6¸†FcÏ‘o 1 Þí¼Ïò_AÝRžðÇXôý’qÂEà#ÀwE¤å4N["l4ùð¡àò§€/“�–BRÀ‚< k5»¢Ï¡¥,¢d,¶“±¯ îèYK‰�}þ=è@T«Cm�?<�Ÿ²¼�ûM†æ¶w™!û¨¿A#‰‹vý~à‹$Œ‘&e µ¢§-ý;€;Ⱥµðˆ-E€'QËúO YAû�? ƒÊi7”×ᆮæFà½vŸ«h?6t\G쾎º$LÞû€çƒö¡UŸÜªFÆ`l~‡�ï™Ð c†‡P7»§1´³þ’¥ý'ð-´ó‹ïÛˆò�¿{bÇ­Ò»Lö𸊺’pÊÂ� V ŽkÑùN´µÆÇì·0]üý&´ß|“åûª rò¬ ãŒÌ³üvá+2ú<ðQÔôA£ƒ¯¢ÄŒDÇ(jg-ííÀ;I´$àÅÄ®lmðËv^!á’ž¼óڟױ†íË{= ‹¨%ú:„õ ¾¿ø ß¾`ò��V”0_nCÂ:/ì(ií|ð«À_PËx‘´{jXã|uMß~¥iä|�]]x=$ÒWÎ�’ãiˆøûjtmøJ¨F¿@bM>]˜ïI§¾ŒZý�sîíÏ–™7Y¸A„ˆäUÚkfL‚ÿ}j–7Ù½® ¾ò9÷™>héV€Ÿ˜`eÊ)+OÞï+v¬‘XеèÚíè¼Ø:ªHÏ·È³Ž†ã·ÚçWРä…yb7_[ ‰È›Œ 5.ž°óŸw·¡‘†¿~ øo”vÌ*{ ‰‰ûˆ¨hv6ÌZçHAºôuî*ÊVD²œWá��ý(!;£Ÿ×Ð�Ñ2p¹jK1¿ïGÝy�¿be/VÙ›K: œrÎ}²(]»‘õ ê¢N;ç>V•pvï"wàqÉŽ+tAŒi|øŒaOAÒetkÒÊû-Ñ)OÑÂ%y”Ù÷µI{—ß%c?Úh±¦z¬‘Ì/åiì(ÚØ~nªÞò.£ô¥� < ¨Gi¹°» þ†Ëvÿö,eëòö¢ zíµ .¡#Ú+hÃ÷ë™ø¬çQ;Qfaw©ð5ìõ EÕs3~ætOpöðÓß¾Á¯—ªt•EèTîÒÃwë¶ÿ² $ym­ú�‚Bü뵕¼=³Õ(kÿH°‚½—†~ËŸ:�Д:ön’ºÿOgÈ!éýþêÝ@KõOSCIÿçR=–�#DHÆu×gDž¡¿}B aÂׂg*L��ôæ¼óCQï¡0Ïš ö²$®mS%½cðÒVì7"+(ÞÂa é=Š6߯æ9�ìæ‰ýÙ¯¯jHz£ÁMkF@膚CmEÈ1åM1æÈ!`I6{T(âÅ3!’ÿ7b×†ß •…iY¸ œßŸu }ˆd÷kõʲµˆ‘cö"þ?IÝm€¸Y!Ñ_Ÿ X–C[ZûË@tü±e€ÛØÆ6ºÅÿïØÔÝ é9IEND®B`‚ukui-biometric-auth/images/Iris/15.png0000664000175000017500000000661715167732630016521 0ustar fengfeng‰PNG  IHDRbb«¥ VIDATxœí][ˆIþzf2Äݸ‰quAʼnD™Å'ÍDeñNÜñÉÉ""®à슂àÃäETfÔþÄ ,^˜,+>‰³"Š"8Y×£èŸõ²ú ûG×ìm&ù|¨SéÓ§«»«/ÿßÿLæ@Ó=Ý]U§ê;uΩS§ÿöiŸöi ˆä É-’£žù «$÷ÉËĈäÉɳ´Ø#?–$úàgì$^7Þ’YÑ«’<,|lYê“·N‰äÚn‘8˜53c7¦•ß("¹,ú×Óúné�Ì’Õÿ»Ç†H'{A¢¤/z† w…º"¹´ë˜Ž dCÏŽ¾y*$c v×4Ž$#h[S5Ó�´ŒH.÷ÍÓ8)Ðßþg½0µ¥$dÏÍ‚"cîi¥OF4ƒÞ鑌ªš<ÂèfÁÉE5«“lx�©=¹†§˜ŒáÄf†QGÓëÂõ@" “QSLã17µ:*"£¦ÆãM1 ÚmŒ¥�=B Œ»Ž*ÓE'o:µ)éñê²Òñ!¼‡Ii�([šDT¸à8€3I’œoË`}{DøðgÈõ¹¾,Ç\I’䑉2ªH4ÇEÇœN’äÁ6•­MÚC’¸,å=´6´%u-OZ­J_HçÚ6k›nÕHQIcí€ Ò€ÙøÙÀnʱ¡®cÊúAL ¦*ª™§ÉÔU‹&@*lƒnV.32ÒI·ÖY¢‹­3¿ªiÄ l‰*!©×Ó…ÛfÇ …v¾¬¤®ÄzͶ—Ô æ“|ûkcl›�dz+¦˜fo„$r�=xcø ”�®ybª>'ïþ3œ½Aaª¿Ð±!:Õ·QÀg'€ÈXôÂZ c:Ob©¦ Hi™ÅyW»oß�ùì�LG˜.‡]Oÿüú�_–{ ̧Ռ¸²é ±UC™©Íì>9ꉩ!õƒmù %Æõ.@A)·‹¯µÀ{ú�ÞAðÄì¶g.>$€lšþM×^ ³S›,P9F²¦n/ƒYc�"yÇöu“Ó ªŒ$•u`I3?i>cˆyµ4ÎÌç8�ŠÞ�1ë¦Ñãé`º‚Dâ=•†$DGª_“·FÍŒX¢ï `ScŠˆY[P:¸ÌfqL¶̯� ã'fºw²IÂt²D·:^“£“xÓˆ)±)| U™ñÛ?BåtdÖ†´(†Wè–: ™˜~VªRºu‡ö78#Î|†w”NT’2쀇PL¨Œ¯†™u.‚HA9mÄ»ßV6 #¥Dw¦•îdø«Xjäï3•ðZBĬM²+#άñŠAÊ T¹Ö’Áò½‹*ª½)ìZ­5˜L“È.<*æ§ZôTgª–:I¿a»YQ Ó^´zRåW˜uo›eÉ3+�µô³žGg.Ûïa×â…©05Z„²­{Û)¿¢Êw¶Ðaù¶g ÕÚWãÐø[pf³ÿâÁh ‚ÔqÃÕ¬Íyy½u=§Õñ‚´�h¨ ³’®Õ”¢½ f=¿¶ë ƨ°>–Äå4:”zº2ÔV¢ÚRTߘ5Ø­m]ŒEû‚�<¶]™zªåm£ êï†÷’ÛRõÔ¨/%õéÀâ�¢ufäù¸ôE¸wÒ©Š2à›p)Š—=—p)”§ÇÐäñêWÆC’zyFþ<àÌÐù·§äÁ…$I¾2aÞ’â òçi’K3ÈJǽ“gë¦%=Ö§fàÔ�§û'ÌÌTÇ» ª�xØ7X¹_[‡˜®€£¼&fWâ“ (·šº¯¦ÞUï�ë3HgÆY¶wÕü7 Qº¸‡ïŽ|¯s[Bç‘zÍs©á¾ñBg9GLWÖÑ¡¶_Ô¡ØuÄš/Ðt,L}v=æ#ðb#0Ø 4ÀîVÎU½eËT8ºØØZ`�¼.fõbu�pµ£¯l接èþ¨2­>gf‹ÀŸM¤jFíN°ÝæO EǾ˜]·QÓ ­Æ’-Á`ê‰Õ ²Y¦»¤â@[˜—�*Û4ø¹Èl†G3@™•ŠZ1ë¢EïN™r]RôÞ5³ŽK£À%;²·ºB;3¢Öm:30jå™ö›¨e]¾4¯nÅMÁ¨2µ6Vm6¡Fƒ@•"Ú ìªi¿Û%™÷¦*�0³žP“LŠ6__ÔJvPm®¨:ê†ñm*êxòa™×{1`èðI#é!ˆÝ—´hG«Óèým濟،-Û˜`”6Êì¬h•ý&u­0ÍwÕGkÀlrX”qg~¡6;ªq Fé3;e;ÙéꚘU½Q«oæÓe&ß7fR΃QöqGüò~ÂÄ|œ­rv±Æ§ c§Àz ̆=Ægȳú½Tª™WE[SÑæ?e*ì ó®]ïߟÉ.UIÌ&§ï×ܘÿÀ=()L×½ÐÈügeAÁ`þ«Ù§í«RM̯‘tؼ75?[ÍôÛ��Ð,0ˆÜäxƒ˜ÿ¨ÅR7h˜�œ%9GòÉy’I>OŽ[*ÿÞA){@êš%YúËmLCD ÕpœTùSrM‰ÎhŸƒK•ñtÀýú'éHÎÀmÙΘU×3Ÿ?'êïÞ àºº¦ºG×Ôß×äüŸ€Ý¾Î ßÿ©h³˜™Ôžœ Õ쌨’³Ž%Iòþ¦�K]kp zÿ÷2€ïø€ÿ! A5@�"òd�ðNð^SÇyg“$¹×Û0‰68àb’$'BïJÓUlõÀ$g° àãÈoÈÀüé¬ð­Áž<(×Õ=„7Xp'€Û Oø€ÇìH™×’$¹ŽÄôG�8U”(QÄ¢TpÀñ:ÓRÔÍœ³ê|Nò>àe¦Øá²+~` ÀUTƒaû¡7ù-wXpÀIÏ7íÿÀO üÔ ê¼�HPD%�†Sm÷½We´ÖàTÔ¹$IîŽhtÀ¸A÷ç9„A¹N"ßVPÝ#~à/~àiÔâõpöé^)Gˆ~þ��t„mõ·>¶“$¹V0«p©3…*Év �è¶:�¡DE)üÙ‚ÇŸoðVïð*‡ X¹ §*þ-‡åý/p;€•té*€_xÀ/áf¢x} þŽ<³€ì¨1ñp¥4w+_á©ð1õ,€¾g¯õÌР̨ë7ÃIïëàôö*+耧ü ÀoáT­7ÒVú Õ�9{ô½çÔ½CÒθìúÊÄî(÷U[}¸¬í'ámÅ@XPô¬(RWžð/„³1/QgOÿ„S]ÏÈõþ,gë²^G:øE è™�“|u¶×þøœ=ŠRé@�uÝ&Ð8—îcÈ1�t°õu”Y„ÕWÚÅÕk ÛëªÚµB!é·÷íáŸûñ}o�³qoO’䉘ñ�‹y ’$¹›äq+pR÷e¤@ø£„¿š)úº.šb@ˆ±ÛÂ϶ð°£xÓǶâi„G¼À3$ç´í(¢h ļÀ¯|À¿<ˆtp5(Ze]Í”�ý¨#Ã*ªAÐg;øœ99ûß ð ]ëÏù©ðI8»t@ÆU`D! ÌKå+¾ç–ð�<óÇ\àºhÖØÃÚëa�‘aq „Ô�–|ߎ¾Ö MÈ߇à@x#œv€?I?Õ’En®¯¨”dq¦mÁ<ÜŠû8×ó‹pzQ?·€Ô™5z¦„Œº•HÝ»‚�P¥óíñœ9ëëÒÿWxÀ}pjI—É”+ZÆÌ­³ý€\‚›ç|΋ù6òêFh,@öÐ6%†žE Xõ’üÐ*^“]µƒSÑwÀÍ€{༴9Õ¶;?;g� ÃÜ R d6X&ýß„ ’ýÀ‡¼À7¥ƒ¡õƒgÊr 2Uæë³`øò X5ämdCv&&¹n®?àÝn…[ýÎuö háÕ Ì8 •ä¾·¨šžÉ³p6ã._‡[Ÿ€ –=nÞ³3*tÏÎ ŠH×¥ƒ~ÚòúßJ»äP˜Ü¶¯×à˜ðZ)÷\yù6BÞ�¯'g+nHB‰ô{#šÆþù à¦é]p+ð/ÁÍûn¨|ìó:üèç~fh�B«êëæ=[æ$€�­–Ÿð9?­(j/øž¢h5…4j{.¢ð‡‚²eíµ§Ÿ�‡˜ýµù~°j]ĦÙoŸÊìÄh¢KCÑ9OÃi„áS@2Pv5‰”Ù¼ uöœ–Â|Öž–½€¥À´'{NYT³`ƒS”o5¢ù×g=󲸧¥?†è’ÑúOàݧ}Ú§)£ÿj}\æF9ÔKIEND®B`‚ukui-biometric-auth/images/Iris/18.png0000664000175000017500000000447615167732630016525 0ustar fengfeng‰PNG  IHDRbb«¥ IDATxœí�ëuÜ6FA7 w°î@ê`Ý�ÜÁ*È(8©€NëT°ê@Jt*X¥‚›O’ >VÒwÎI6 0 fX¥ÞñŽwlÀxÎ+ÓÑ÷ÀÕš´,`ÔÀ×+Òã¢vkÐ3;dÀßœ?‰V¬*…À•Ðq 0d¿&mE<\ŠÄ‰À<8{Ü*½QnÅþvøv)-¹Ð9kˆ ¢~ %c15¤¹sì/ŽèCަv¬MS/œµà²Ô8Ž =mJÓi9·kÓ4'ã]_ë…¨'CB^�ôAó‡5 1™P¯FÈŠpLÕòÌ&œß2:ׯ\Ü/Ùñí_/×ñ†!ÌhÓ Çm×…[" Ë˜)t<æM›£>8fjo ´;ÎÒÁ+�ÁŒ3¥£Ê´ÑÉ7碦œ¯’�ÎÇáW ÂD­¥UDƒOJ©¥Ô]UU嘱·…Žî§’ß_ä÷ŸòyQJ=+¥^ªªúgQB ˆåxVJ}RJ}©ªêïœÆ–ö�DoE¢:-OÒÖíÒfUÆ­k›Ö7í®1I³@&©ÆŽÿMìI>Gã÷˜w»I©—b ÚD¥yšhWu7L]�LØ‘V+o‰ŒtÒîuö´± oø)PgH‰B2­ôÆíT˜ PæË•ÔCì¤Oì{/L=â/tý?ÌØ7ÉóYŠ(tõFH"¿±‚7& ¯{˜r,MÚ|.ïþ®Þ@ˆZ/tì€Öô{è,™‹U˜ðXMëIìW!ª2I·ô×]]^Þ¿zÃzƒØ”Vÿ z»‰¿•Ûá—Õœ¹„j@Ú…Ø5C–jcç1`æ ½�v“íÒ*Œ[]€‚)w7_�çÌgVgBì´§†œœñm+ƒ­ÚÐcrÉÚ\.{±ö„HžqÇzb ¦Ê‘¤¡ìMâ—¦3øf3¸8ã×8�ûž]Ø^Qo�Þl‚èˆÄw Iˆž�q-¿n8fæÌ€½w¶™u¡ØkÁàäbWq,;>üroüÄQ÷"Iô>dO»;~�O‘x:b ÙH¡£1Þ™ýs˜0ªŽØkHÖDÞ¡»(2qÆ9jJi÷¦GxdŽE¿Â;Ê&’Ò !BònÛ¹: =xù´²ÓA)%æ`²l'á#V±Hò÷Ñ>Iˆ°×ĆR‹8öâÅy¯6ÞË– †sc˜œ”Á6«“&]<%<*|U‹Vu´Y*R~CžVLf†Ó_´y2Þ?`»·iUòØ8ÉÞa{Å\:òsØ“hA SÒ&”\÷6‡ òþÁx¿ØF‡á´g &åß�yH> Ž]ýÏŒ\&H¿\ÍÉ”·;Õs aŠd®É�ÉÌÀ–ä&… ÒÎIÚ(WÂ�k¥"Ú Âöür÷A&3νí1—Oè´‘vJ-Ô®Då"jlØ vöZ`Ƶû€yÌÝ™v˜äm¡;ãïá\r.¦˜§¤± ´gÄê|�ÿÿ¡ÚòE¥”úºt©¢LøIµ%Š?;*U[Bùe†.oÆ™Rzy'~RJ}WJ©´þígù�UUý¹0mAŸGž)‰�ã�Ì©!þ!~ö”-_—'ëÍœëÏTk:ü±01›ó¦AMFâ¡{!u.œöÜýP˜ŽÀƒIÌ !4@¹�ó¢S¶há(‘ØÚ1¥® Û.Ž¿ncrô•ü0w,¢Çc¼“uœ™ŒÀŸ[H•ŒɃ /ùƒèØö8ÇLï²æ’Lf =±)A6—è’è´…i©�wSƒŸ×Øi Å–ŠI a»hÑÙ)ç½’ˆÎ]c;.I�K ­·fƒ®fDí3r33&Õ9ý§˜eóýÁ¼© §2£6Þ™”X ô™‚¤IÀ(Mx÷Þé¿ìAI|ojtÆö„R*)v¤ï/&;}Œ6¦†ñÝRÔyêañí^ 3ÌðI’tˆÄæ%êŒ~Ls�߯??qŠ}7f vŠ­YÕoÒÖ]ïj~²MvqXÔ⎿Q«gg‚ѹˌÁ ÆVÙ"™®ÒÀ6½Q»oür™ådž}¥\ÇŒ¡ÃñÛû…�gÕ.&M˜� îõ°Ãó-d À¶ïƒR�oŠž61ü£L½ƒÁwíV?æHö IÂLnï67üîAIAï-V?Ј¬,(ø§fÏlíT© üÅë, ºržÛ̵Õè³!¡Ùá"Oløà/àj鲩zè;DL¡j¶$@ÑÀ?[Ö™«Í2DL�+D„´:¡í#S�t¡¯>È^Œðï´è¤+{p¥@ÿí4u 3Dέ—èÅ)[ñ¿™ÄìâWÿ£oP룩Ô]U�C�æ²SâbÀ0Q÷„o0;3ã]{èðHßä7Ìð=HhMK÷Ñ.iñ+¨é7NèûüRÎhì…é5Ã'�ŽÌ´n¡÷£&)æÞ×F•¸»´¿ý+Õß)}¯kÝ}®?å㢻ö“|úð¢ÚºÓGÕÖúþ7•æК¡®Vì&»v m¢Î¥Õ¶§¿[Ñ„ñWˆᄾ-s‘Pvì*jã7ªÒðAµåãÏJ©ÏsIÑ@ÿ{¥%ýÆøÙáYµ’njÍcUUÿ.Hæ/ o�þ^UÕo¥¯…Ãï_Y0t1+÷2ÖI·èm2§°6 a�� Ò‘$Ûìy LhY‹Xúût6ì|õ²yÖú¦©�;1¶Œ&ˆ0™ñæÖ Ç2Ì»&DcúËõªÄ,ì¸ÙiãÞ„z.ü‚·Õ³Œ°o Þv1Ž”/¥, ì;ŠŽ\BJqø ®iÉ�µ€]nr±Ú! 0ÍP³i-èC@•/bÏ`À™K÷ i]<3çÐl‘!„¿¦6”Î-‘2·.¨x6,�®~Ò¨yu pP{X¹dÛ¹¸¼r™à|õÙÊ´\¿jé�íþãÕnßñŽw¤âˆW¥Fã ãp“ Zg°Hii3ƒSg8íçÃúÖìo¯³÷>kïsæœ3¥ÿdg_ξ|ký¿ÛZ{�µá.à†"r@D¦EdnÀr̨wŠÈ–AÊÒ7ˆÈ.9$"s’ǾÊã�ˆì„<«-ð}Q�§Õ*ª…"²Eåx¼€�ýƒ”­§‘ƒkEãTaFûè°Ê›¹EýoÀ}k¥@j%wÈ¿vbˆâÐù QZk!3kÂ]‰Èþ5't”�G­u Z¦RD±`m™q""E›*K�´eNDn´L«‰‚òÞêU¨i£!ç�”AƒyÀ�A bI840AˆÈUõŸ %aî­LB€ˆì3uqg?¼K²üºb(3}³ŒÈ o 7¨‚öÇMIÖ³êîHDœˆŒŠÈ˜ˆ¬‘qÙ "uÙÔa çmÐk×é½FEÄ­’ÌÖMÕʦ’R ¸ ø¹sBVÜw˨ÙQùÂÚ™ýÙ8g¶Åà¬Ù?«ësιsí·ªUž}ÀaݽÉ9÷TÊuID¨©=<©7­�Œ¨&†Ê#«üpÌþ^Fä )C¨pÈPJB´ß ûÎ9¡l}9ç®O¹¦#M6ׇŠËÕdŒ’U´%£h ¤Xm–’%•„x»…'%ÉbŒ¹ß9÷µNç§1 \Üîœ{8QˆPÉ¡ÒËÖ–Œ°."ã}Àfà]º¾J5œÑíÀ+ºÿO`A×U$„cI$˜õ›t E·OSÀ­Î¹Çªê¬’9ÜK"«"2¬ÃWdX�QMJLÆà2àz`°»Ós;à_À3ÀSº,ÐN@ oš}»¼éœ;[RûðdÌ×U¹ôR"4êæ�©ª›Â:&£ˆ»þp#¾â/){ŽâE`Q·�Mº½¸¸Ãµ'�g�?â‰ù/ùŠ·KYå·ô·˜�Vü0ã¢rÎ}¡L¨*"nÂÇ…ß”œSD€=o[Ëx?ð1àæ^Žéò’.sî‘€�ÀåÀ$ðݾºä¯O¿ž¦Â Eë@‚=¶L‰…ˆÈ ÞE•Öe!êßóιüÜÈ8åDĤ¬.>ÜF»æ¿ <üC—×hOk£Fþ¸ qš¶¯Ôår|ŒÙ]÷ª–ù×ÀËdd´i¾YÇÛ¹%d[Æ».ªÏP�RˆÈ.çÜ‹Ñ1[¹�ˆq²Ê¶Ûa=  ]û_~ühmfUÀ‹ÚEDXŠ2¤>¸x/í¤<üìcÍ�—ð{°ˆes|9X‡z˜)JbE­¦’0NVÙ�ˆ°Ä„\|oGð•ÿgòq#l×%Ã"…„8¼¸¸6º×sÀ!ò„”-1+Ç�s-ñ/‘æËbm�–µ%ÁV|)ãÀ�ÏG·ù-Þô7ã- Ež€¢ žBFNT:“`×-||1>}”v+yOÈ0ÚNž„˜ŒÜïE�Ü"µe]TÑ1 aÙ|¸ÔÜâ/À�ðÊ;ñYÄÀ#À)sß@BYº[FFN\ÒHîfðq`ðC|F5�OŸ÷“ò:ðà—øøe+ßRFÐrYšKA!Ú �ÙÆ‚ñh?¬ß|ø”¹üoZ¸Wð¹ø>³xLÏ) úEm�¸O*Κlã­ˆ„Øç_Læ:ÿ‡ïšxIÅÇ5`g�ð ELÆ2y2Š,£°˜BDvÿ=À7ÉZ¼àµç±èüoàãúÛß)Ž5v±ipÖ*ÊHˆ³ž8Èî>¨÷8|�|�_"ŸÿøÕ´+sQ�²¦NÖ0Ž÷©÷àý~(Èwð) ueŸÁ›:øÆÔaŠãLU`‰‰É€ö³uCe6¬?‚w›¿ÃDz¸2¯nÞ¦ç=ƒïy˜£º,aÒZ‹N=˜6o�»«G�Ïß&#áààßÑyW“‘0ƒo@Ùî�bÖ›õ]6âýö„.›ñí“‹t{³ߤçnÐë×›ûÅ–¶ŸH,©Œ7â]mÜ!ù4p7>æ�ϲvFõSÖ}îSXѥОSë¬vÞ�Êà»AîÁgqb;ð]`›žw/¾k¢¬å]TIEÇ-‘¶÷µ²¢à¸=6 |Uïõ'àÁèw{ÝÍø˜¸ßÑx0]qïË,Š+Dh,(j ��ðuà³zéàûx�*ª¼Oâ[Ó?Åç¢óŠž“*OÕïKº´tÜ…=f·oÀ+À/ð‰†½Æº´+ð®*dVâ]ZüœØ ÆÇ–,eÝÕAã‚îÅw‹3| 8^pÍ(Þ|ï*–�¿šû=§ì˜=ÿ"SÉvÁ§Ä±¼¡ÀA#ãÌi™¼Æ®Ç»šsøÔz†j ¿Ÿ€Œé±çðU¥UYjÝ–õ.2mi/8çÞ¨8^kžwÎ�);7áÙ“tî™m§�ÓUr%<Ë–óçÜr‡óÇñÝõÁ2æ�ÙªvCŒNÁ:èèíq³?®™Û5ôÆ’² (9ilæ~o�¥¶�ŒÑ°ž„°}¬Ç~½#´ò§ÐìD¤Ö˜ß&ˆGmô ι×Dd_Þõº>:¢ù­ÍùO@¾q¤ˆ] NæÔshj»Ò""#äµãXÿÅzËÂÖõæò~ü .`5ÛuaÓè…ðdͤÙI 7Õ÷$»ZØìª—©ø6².ýyçÜ™�¾Î’UÞÎ:]%›¤QýNH¯Ôž[„¦¬“ºÛB³¨m/$5ÅH­Óî™Æ% µÿkÅ¢{ð>%�°‡,C]i0¯4èzLFÈ¿ët ô¤s0‹5,0drK•g%À¤è�„Y+G®‹C8j5%ÃjwjZÚ/"ê¤çAö®¬U-a/™…Íj »‚¶N?5Á0ú�iÜDé‰ùkºyù“Š…¸Ê½?èæ]û8ywÔF” vò™Ô,ݹ© áujÇÍ3{�ÙkÌØn�FÖZ I€ŠC†Œ€ºdá×wz;ež¹Œ¼8žpµýˆhô†Ñ�úÝJI€¯J•ŒØM¥¶3æÍuÛ«NŒž^3ö'jvÝl%ÓâÚÖ  :*[t ¸©�)d¨Ù†brï¥ m )B%Ôµ²P¾VjL Ð÷&SæùGSî‘4œFɰÙÔÎÄ—ñö…­»>óÍ3–Eü°Ÿº¹�Ì�ÔêÕAp¡›(ŒýJr‡uGúÅÁçTügÇ‚kv“ùÛF£ýô¥Õ%¤½G8…é×ä9£ø¿m—òlJ|0ïslº[ëÅZíér Ȩ|¨º¤ð'Á¦ïÀí½6Sü’f¡ÛÖ¯ºÜ�º{,%® ·<¼T·Œ�æ-* £²‚£q«/ë ¬¡‚Z]øGТ¡L¹Æ¾Tk\¶Ô!—9hƒíYÓ~UY@>No;{Š‚WÅß˨r]M>3j¬`�ˆ€•œÿù.ï½ñè=÷,ù”t²Î0Æ> ÖêR§ïÑ÷’Yxðµ’‚]O©¦Ú4E>�šh4L?9®&"·Yé’"ùÁ7öŽ–�_=›Û. tà5%×èç…l'ä÷=…*Ñ^|ºZªj½Sd¹…o©÷ìý~O',^-|.~ÒPD¶TM;ÔO(“xc¥Ç·lÏÀ^ÁRc'¡ç³=š‚Yá[ø”®+?Ú/(;ð£ƒR-áSÚUQ U™vr#í¹E¼æ %!ê‚vÐÞ7ö2‘U7¸÷£ºy{òì4Ú[z/~æ²®¦ÕØ�[]Âÿ¤«Âõ ZÞí´·ÜOácAWnHf½¬šÁ,LªØqbÀAFñd $nÜ%Ñ¥Lx×c{Z­L] Ï “,n¥b–Ð*"’'¬!Ô(¾ð;hÔÛÂ÷ÖÎgzm)¦{d‚âÊ_ÒgŸìe V—t+&¨L�å²rbÀ†–¹ƒ€]i@Œj|˜båc¬æñí�žÇ-ñ“ØßOÂD¼)³Ó„‰»vQ%÷oöá+­lÔw ÿÇ‘%òÃåFñ•æî(C°¼3ôîÿ}m0¼G©œ¸8u&ä'ñÂ_שۻ[¨¥l"ëeíê x«:‹·¬ù~ fÓ2Ìâì.çÜ�®éëÜàM!Ù¶ÇÉ´>þŸ^˜£oo1 ½nt¥Â$:=wéHöm¹·ôT:A²O;¬Þ7—$ûˆÇÁUyÀ‡QÖÕýð•ø/ªÌèÃ÷¥©!„!aFúñ5bé÷÷t†ªœÁÍõ…óðÁ|ijÈ ùo.õÇ „°d¼åbFäû1D‰¾G7PaúÉÑ÷ñ¡(÷P˜gŸ þg!ˆ Û'à”ŒûLÀ:ïâFdÃñ±Ø2ˆÈ#ìšý ¸…øï‘†XÊ5xWÔ j¾ÓFsÖ¤u(Ö Í µ”¡À”×D›£€€9YëY¡øÏ~¢~f Q+¶ŠppM¸¡T¨–M›Ήî�!‘µÊr~£ÀìE+b`)¯ä“‹[%Ç@ „ L X–}çµö§@|ûã¼m^À\@Sü¥EéåeÙoºIEND®B`‚ukui-biometric-auth/images/Iris/08.png0000664000175000017500000000726215167732630016520 0ustar fengfeng‰PNG  IHDRbb«¥yIDATxœí�ßoGÇ?ã븩I«))I R¥R( įD€xAÈ©H ¦ÿ �ˆ‡ô ‰—”�€ƒø%àBâwÚ‡– Ñ&UQ#»MihH±+Ç×=<ÌïÙ¹³÷îÝûÓN¾ÒêîîÝ�=3ß9?æìì.\Çu\Ç@Dî‘Ó"27`9fTŽ#"²u�²ô "²KD¦DdNòØ?@ybL‰È®AÈÓsh…�G>­Z1Ð^("[UŽS B R¶®BDŽ­—§æX¤±ÓÃ*o)ˆÈ¤Ú߀ãë¥Bª%Gò¯¢•˜Ú=Jëb5df]˜+9°î„.%dÚjÇ e*Dä Ö——DÔÑN•¦G½eND&-S/‘¨ïàµ^…:mzȆӂ"¨3¸�‚X¦&È™ªþ“¡$Ì]Ë$ˆÈ~ÓGúyá]’Å×ý»ðCɘé›fDæhxC¸@;hÌ”dù˜kÚ!2S½‰¦$KÚM÷䆌9évVY|vòš Q«Â¶W7 íÃÆ‚”ò¥®D�§�{€Ãιïv*`¨½�P9Â/º>¯ë³ºÌg€yçÜS}Ô@-Ç`7pÈ9÷‹N ;ÖïI5pR{TˆÐ:Ái-k²ßfUë"âCÛj×?j5I=­€6Ò”äóÿÍö”.Óf½Ì¹¡Q¦úEŒd&ªZ¤)Y¨Ú“0L‰žjÑ`ÓâµrRJf:Å�uˆÏ—Æ[ sÒ‡[¢¦“´wÉn§º,PêÎWÜSï/Ûèm^û€’:-�“Âõ�õðÚR¹=»%”d³7R=ò¸ S§ H™î¶L’™Ïþ‡ÿ’ž½!*ÔàRÇÄ›¾é9»Bˆ¶Å@H8–¨Ø”øHâÀ@„*€6ҤϻZ÷Ý¥qöF®"’ gº­þÈ~R÷í’Æi5s²fŠwıÊ©¶äïcˆ �y’Ì‘†ÆŽåMMŒxJB{y<ø:–8Î3p$Û³!?¤„œŠê7\÷b$¯Ú"&'êYCw/Còκ¡é1q]OÉ0˜ª¨'5«À+|ɲ�ˆÔDdTD6‰È˜ˆl‘uo±„ã6ë¹›´¬šˆ4䨤Ñl&�³4Îqš+:¶´LúAýAÝœÇ'[’O~Í÷8çž3ÿ�a©™õ•/ü:³]Fv^5ëbö °j¶Wõ÷ÀÏõœιšÔÿˆÖ?$v’d¬D„š–£º9-ÊÌF„=|ߘ£d�p´&ò„!48ä ("!,¿>¨ç½ xÒ9'$ >eqOt�¡n›ñÉ«Ãf×AçÜ#Çnŧ¦'€§€à ��"£FÖЖŒ°Ü ܬë;€�ºþðW{ù‚¥ «À>à÷ZƯ�Oëþ:°êœ{%ã^ãrÎ}!ÕÍÐ …ê¨æf8|UwOÁ7tŠŒð[DÆç�Oµqø ð[àYZ“öYRêÀW€Oj™ïÆw¦52€ )ê#N’Ý'9‰×ŽWZÈ»†RDhÏ~ˆ$ˆÈ(° ß�›ð¾á ÀàCäIh—ŒŸ[ÊV xøð�$ÄXV�wßÖr¾G_�±ËŠsnUë? ÒóÎh•"£,ö³zëpáwÞ ýTù"ðK2’Ú!cØ|³Œ¬ |obÊ’–À^àŸÀÇHo;çê‘OœÅß�kéÄG[ áæASð „õϘb^£ÿ…Æ·¤ŒDë1ËÀcÀûZÉ›Àç€=Àw(GBXÿžˆÛñ&ç2³´¢ò¯˜}5©_Öv:�÷‹Hˈª)ª uó žÝ猣˜ˆ÷êy�¨°ãdŒ’'%ü6#ãÕˆ@Ï~@æ˜ë“°PyXD’á}@!ê˜ì]¤�ˆ1#àp¾'üOBì?ìz2êÀ¿€×ÉÜïÁûª'(&ÁöðEàÞ,Þ ü�¬ñCƒ×ȈˆÇA?ž~†'㤒‘ o“DDÑQLÂYÃ"ÂößmŠ{ØlŽš`µ§­7#£|˜–È(tÂÀßñDìÑ:ÔË ù1� 0ÇkÓðdœRd4Q’Ûð)Rö™"_$OD‘)«%~c2^[ÐÀe±D#zX7gi$Á6\L‚Ý~‹–ñ4pi­Ù”XbbMÖ]ZV§¸?¸´�H°6úÜ\&k|È7¸]�GâÏþˆ'ã!™µá5"Ìü8á�’z¤5¶±âí12;~…b­±ÄiJX¶o§;¸ ?¿LÚæS3,˜ónS9›…üñ2£x2> ü‰Ìg¬ES£°6`;i ´á–µÙ±Cµ‹íÙ·é¹ÈT¤Acæ¼W�«º}3ž€ªºoÂ;㔓µ¦fÑœs›Ê� ÄÐà¡]ìv�,\þÞâ„üÔI¹Ç9÷JЛ¸:HPmˆ…Lmע퀠M–@KX á|oÙQ²!;Å-x3—²éR°êRÔà)â}#ø�ía²qÆ à¾ñ÷iêÅN:ç¾f.„lÕø1Aöü"�²û&è àIH™Vë«RuiÖˤïkÀˆ:ê`�‰È�Q²Dd©m‹o‹Ù¶‘EŠÚ`¸˜8&ö1­RÚÝÆñ6Û¦*R¿«æœ|]R){NÑþ0Šíx”lœvp¢|CD>KctT£1ÚiöÀV|Ò¯U9ýÔ€[ñ7�êøôɲY_Áû¨eò&kð~ó¿=ή§ÊÉ�#"ËÀ—LÙ�9Ùƒ�LjøÑä¿É›ŽŠGÀ¡GÛÈê�øÑôÿLY›¢rlY›ñáajÀ4ýŽjÙU³%ôJ›Ð»üG×CÙP¶®ûƒÙ\Å�‡ioÄçÄåÄZ±‚�ÜvèöËÀ¹`Ffñ=u\/<ïœ{™Š‘½z±çܹ’çÜ[õzð¢sîb«ƒ4š|³nþÃ9·Øìø2‘ñ�þKšõ¸R·7�sWñi‡^b¡¬ï“üıÊfI5Á𣠠~×û¬³tf¦B/«�Åé½@ù”Å„Y¯¤­ Ÿ�$š ¤ í’„¿AJNKT­x¡�k´ƒ‹e®ˆÔȈ˜µBƸ�h1¢U2b3Uvð5oλµä9¨°³e�/‰—œsíø† ²^ܶ6h‡½‹,­Þ”(‘ZH˜©�eÈÐ^*1ÑFôȰ *B#´«e¡~õvÇS"²�l²Y8_¦ŒR9%ÃFS;KN¼µƒ¦¶ÒzͳT�X–ðƒ¥vr™9iG‹‘;ðwòÀ“p®¬9lw¦_ì|.ÛùMçì!³·•F§"²?`¢Õ±øÈëåŠ×©o%3)O—ñzÞòáîùv|K•¹¯1M/ª&émº¹„MV¸ö¾²)3·ÐéèWMîNݼPƯ¨L{ÈÆ—�Ú­cÕÙà1MXU6ܵ+•çé7TëîÔÍ%çÜÙ’çì!k‡Êu«t@lgɆþãÀÞ&ù"Yþig‡y¬®Ã˜–€ %ιOœ�Œ*w°Ê7d4æ?KÖÀãÀ>í%ñ±«äCÒ;T«†q¯.4qúôÑ>2 Ö r¶:xbÈVÇkÖ‘&UTC;U”r†½Dd6›š¤H~ðƒ½óEÇ·ƒŽ‰ˆøž’Ë0êq»ð¼—*Ä÷]…v¢}øpµ°c¨öî&sÈuüH½­ð¶ºF$�W‹_²‘­í<ÄÑK(wàeŒ;Í~üc3 øv•.¢«D@®bVø:>¤ëÈŽö JÀvü�´Ð©–ñ!mO:P׉PíØM~šä¾ç %!j‚¶Ó˜{‘H«+”Þš|¤+I„fKv;çî«zq-k¾rvšÍ2þ¦yG•ë´¾·Ò8r¿Œ÷™!�S|8ãœ{Gê˜B��쥊�½�5sµ�FB ƒ”D‡2mÁ››iµ2uL€^'AÁßМˆýZÀ,þ!õŽm£² OH<³»ŽÏÖ΋ÝÖ“ÙBºñ—õÚ—ºéˆÍó‡Mûmê#̃yMŸÂ¯(`‘9XÐe‰ Äh�ÇÏ$ÇÌȈ0O‡Ó‡šÈpÿ4n¡I (óÞ׺ñîÒâòÃݰmøFK>ńט+øž›ê±5|c�Ñü9Š y‹T¼ûVÆ¢€·(Mf,CD(°á=½€jÊ8Y–µÓ‡Sð3ê–ð _v*MeHþ� G£‰ÝI”}ÎzÍëÓÆCÜÝ‚š™Èf#†ßûLÜ^cº=è* ètݤ#Ù[*¯²  ${ÁVï^h/ÙÈ’ïeºÖa:ko¿* þ¥Q3z±¡yÜ0À�0#ýxçŸôû{:CɿﯿŸv�A}ijÈ ùo.õGBX2®9ŸY†Á~iF¢ïÑ T˜>Bò/ç=5õ õìÄ¿!9ø‘a{mªäß<·ýF¤Ãñ±Ø"ˆÿ@vý½Ø<ñï¬ ¾ Ôkð¦¨T}O›ž³.µC °fhf¨µ  U^cŽs²Þ£Bñ!ž}}óÌ0"éψî~3TÚËì›òÃ'mêC"3j;ËÆ" FBíEü=É“ƒ’c �èÓg–eÿ†îýe ~ü±a€×q×Qÿ–íÉùÑùIEND®B`‚ukui-biometric-auth/images/Iris/09.png0000664000175000017500000000716315167732630016521 0ustar fengfeng‰PNG  IHDRbb«¥:IDATxœí]MoÇ~†¤%[¶j5r�Äq,nR¸_v€E ré¡9h.ŠZùq‹=*ÿÀ”r)P9E�zprK�v€ n‚8Rš¯æÃ¥ $Q~z˜w4ïg—»ärIÉz€År—»3ïÌó~Íìp à�¼Lò&Éæ€åX9ž'y|�²T’S$I6™Ä…Êb‘äÔ äé;¤ÁWƒß«¨’<.r܈23HÙJÉ…½¢q¢0 �Å.«¼¹@rNü¯ÃÕ½Ò ±’ç#òï�"�XÜ%mѲ²'ÜÉ™='t!ËÚ:-S*‚X°·Ì8'E»9T–hK“äÜ eê'"í¼Õ‹P7•†ì;+Hƒs‡ËƒD“°80AˆÀUUO†�Ð|�Ip yAõÅóUVÄˬT°’SKtc ûN’†d�dƒä× ’ ñ’#$IYu’¹žLºö”{!è«r‚8“Á+ rߢº/U3HÖ¤ƒFH!y”ä8­N�|ˆä$É—z ã%)ã!)ó8ÉcRש»A²¦äÒnµPgÒ/ ËȨØnj¹M�Þ--«sFuú˜tÆqé $¿Fò’§Hž&y†Öÿž%ù㈠É?IYgH>&u<"uN’ü*=Ac$ŸP÷ævOª­—™Lo3WÉ×Ò¾ Í£/Éá-³Æ˜ws qö¡9üE:þ€£Ž—ÏãrìÎ}E¶qµ¹ã/¼™§þ< àR—+ÓÕ;pÀäÞ§i][j…�…—`3L¸Î ݈�æåБðy^!<¥>¿ Û°ºÔ§÷5ù¬÷5ùΨãšo�!†ßø,©;(ûûjßRŸ_pÀX’Z$wlØ1ÆÜϪÌó*ÉY¯À’±D±Õ0mDôBÉ€C¾§N¿KDHB7d<‘GŽ Œø%€?"I@Œ„€·å¾ãžð®œoÁ’Ò°mŒÙI«Ðóz2DˆéÌËá*r’ p{g¯“suµ/B†³†ŸÂje¯ø €?#�½éŒé ŸÂ±-ûCŠ�V¬Â×H®c^u×ìA;àZ’Ã5ØEQ™$DpŸÏÈ%÷à­Ao!)µàsHƬ�/'| ¶“c$´Ô^·ÿ,€×a Øù·åÚmõ, ‰�q�ä¬[×vW¥]W÷Íf­’“ Õ0‚8§åÒ;ލïëêMŠÛOØДs'ü ÀwÓdé?„Õî4\¡î™ Ú²-Ÿ["{ž�mXB¨+2æaûÚ‘qÑó¹³÷\é@‚¶GĈpD]Þá5YŽ ýù$€ç`ýp˜‚�! ZÃÝÞá<Ûð�ïˆÐ®´KÈVhƘ—…Œ%XÅ[ðLCòÛY¹îº1æwiÒ #ðïˆp›;ïÐpIâœ%hrCu$6ÖE²Ó[ÁæÜ�ƒkK=ضáãX˜`!#;Œ1/’¼›Þ^"9Ó€_Ð WÒ$HÐ#%>´ Ð•Ní²þ KD¬ó9NóFÑ®ùŽ„pÛ…dIa ¿?N›mÀ¦¨×<J­HÐ�’ �uƒG·}n4¬³Ï¨Ãfs®Ó Úç×�ÌÒ4n`§;\NÄ$ÉÀMi¥¥&ËÅ] ¾çU`vAUkrìxvìçäx4²?,Û(lЬ5X‹8"Ûa$åqò�U÷¼…¤G÷z‹%#»#s&8"®c^uÌÎÃ[Æ ÁP¼® kDŽCBÁ�€�!I�Þ2ŠdvRî"Ùñš§,#h·ˆ´ÎŽõKKjj2ýsMÊ\ƒŒÛj ã…Yø},ɤUÌÆŽëÁ±›“šŠ6Æ5ú£"=Ù#>CÒ:µfk7ü¸ºgÙ# ìë¾D»%ëÏ®-Î5ý�•1 ÞaŸð{xæõ0A�¬ëþ àçþ&§ÿëK—•€®ã”îÃÂîü-ÿ„Ÿ*9ë_‰p®œpªc À÷;÷cÏxÖ5¹ i ÉlÉeP[ðD¬Â`×Ù.;tŠêˆu®Ngbg¼O¯üUÒv4î¤#©5ã°Ó.Ãù;¬ß�iЈfCOËùÿø ã:]Îã°l¡oÕû†4^O�dm®s]G¯K'oÊùÍà³S¦:€‡åüÒýý¶*g;R¦;·àG°IÁ€ÁÎër6S [ÓðV³jŒ¹›v}äþs°°iŒy#ç=#Ϋ:ËD Àc̽œ²LÁZ3ÜÊšaÍ(ãlæèÒóÔ>L}Ð!1cU�š&9Y@kF™ó!º1f ý‹ ¡ïFÖz áIä È Ø%ãmXm,�æ”eMÝw"ë λH*@øØóI�ë'à­r-ëÂDa¿ ?@ìèM:>úS–á:õT2D‹\#&Äíä‚­ [¸N(je®}­"îHž„LìÜaÇ2r=ƒ2î¨S§˜o!�äµ$]çmØàÚ 6Üî¢#'áÝI+ÉÓðc�€·òºÃŽë{‚ŠœßsfûY§*hÀ›y Ê8›ÁLtºv°v·Ëzê¾ ïRÞÈä¾s°Së€Už;EbK!"¤Ò�ŒÌJÅ%}G7`µ¤pðSe�#ùÌÃa½›ÎÊÀ)9|/O\™ÎÁ^«ïmca"¤ò�ŒÌ“}X?4ÆT9�‘ buß�à cÌíœ÷œƒï‡®Û–{�ކ1æKXÿ½)§Æ<™�?‚Ÿrÿ 6ôä†d ÀìtúS±k²žG¸—*ööb@캫“h'èaJ¢G™ŽÁº=ÓªeꙩǽdqKY³ˆ¸ ¬¸X†oB&a ×2µ`gk×Ü+ÛRÔôÈ1Ä;Sêþ¤Ì@,.é€kƘ_¥]—#d�Ó –Œ1Ï•%œ”�æÖeÛ@ĈÆ�Á>¢ƒO=C¬ÁŽJ�[´/N¹† —ä�çו+(ãÝ¥éå»§a“ð‹|chÁ®¾Ø„}Ö­ÞsKdÒà,ïº|ú–Ê£Ö£d¾ƒ6®À5)0×ï躅XÊü,k¯Ë1×aÚoÀvü—®ïÒ†UX»’µ°Û!Wúª£>Šÿž®gˆ›q ÂÆÔÞa~yý¬Å¬—=èÊ •è”îÒõï¦þ² ô¿Kïß íé�_øwÇ”²ö÷_˜|÷Òпò§J(VXÅ»›Xõÿé 9˜|ß_µ/Ðâ þijÈÀä.Uc !4\Ì!ldú…2(ßtl\åWq ¶~j!—Ο$æÞÈKeã�)ùÑñi;™/R6c*UxirÌGiúßÿ%$¬kŽÊ÷!=5”ŠGè)™2Iê¹®+•wÄáœúщ«}…w%ŸiÊ|2Í uBíѰòÁEaR’.îÄ›­œ0_QKâÊôä;Uü«ª¨ï+Óð®”Hù>q^MuâÊw^•H°t³Qºž5C�ß]¬‡®_Ê(ïV»jLe‹¤&"*µ›ZeSWæ–Y~£Þ¬¢k2’ò*»§(ýqåÃÛz«ä•×À®ü�ò‘Gc!�z‡Ý•,Ê”©Ö T½†·½�`é�Géè¨ókÏ*èêý{Ôµ ®üê¿êdôJ‚å±jv-y–‡“4.©%iBÒ¤º�œŠð3Ië.#2â~¢öŒ@×d(¯ÉóuH°|.Xëš´¤1kìII[%m—´S>dÞ#é^I{%=Ý ’ô¶å½ÃÊÚje·$�%²MEézÅd,¦ùµâB�söq ¿(êÚåŒò‰…qÀ80fe�Ùçp/þ~,º÷𓚲¤ø$ð%à5à6pËη�Û’ÂçUཤN/Ö-Ô9÷ФcÀ ø…qç% ‹àZ°¶*í|”îX�«äÚù’¤ÐÐáhQNÆcÀ�÷íþ~à§ÀW{�¥ÓÀ;$$DŸWíúƒ(Í!IcιÛu 52NàÛ:�qÔ9÷a°ˆðÀ©—*NÛÈ?=2ö?¾ØP¹ëá0°Yã§$„ë€I`»YÌ p«)ι猌sx…=<Ñ’�o�Ùsç�s¿è6óI-|ãLÛñ�݉Œ‡ à•ne$ÜŠÒ„º¬†CÒ*°âœ‹Ÿ[ιg%Í3ÀŒ¤©Ù‚^€Suj�1‰·ˆ |£‡sJÆ=uÊíãÀNŠIˆ�•(M°î@ÄŠ�'"Bb Z§ðDkáW,œž¨šSá: EÞ"bˈIÙÚEšÀ8Þ5‘°�c¹‚E¬Ø1aç@Øx—+ý c¶\´wß‘�“DJ†‘0IÖð�ˆp„ûo_ÆkIL\pO)9—�CÕÚ±gü¯ñq£¯&ÇŠÉð&¾.i8¾B~ äˆÆ@FÆ*¬‘ðY„z,ŒÕÖüyDFx0GFBBÜðE¤üDzÝ�@-&Ϥ}Êðƒ!âßÀu’ˆv‹há]kHs‘¶Ó>èL�5ÈÏô<ˆU 'âaBܱ†Ç ž 02€ßÒÞˆ) ñç×¢l�/Ón5ÉñvyÛ5Š¿á$nô@B‹¼«ùŒ¥yïšbm‡|ƒÇ×éÛãÀÉ“�ó6cIœs/âê0=qïÇB„krÑçIòS‡­“É9tráú&Y'ß/\Å�Ú·â-"ípƒ<[€ÏGéÞ"¯|çøˆ#ă¬C~ô‡oü@Ư�ï�…ž�”øHù³¥}”¼ÕÄÚ’ÅÒ¬àû¡´ñ·�' (ËãQÚ×èÜØEí2ny üßGüøMYX[J„áyà[@˜…= �óOš'ã*>€�_æZÃõ§ÉFû¯W¨kúyßv»ðm÷càwÑsmˆ§Á‹zþÞ¿ýo»€“–Ù/ɾ›IÅZ&ÀKÀ×€ÏÚ³ïPlÖ©‹û;~ÄÿmòS&uð2>,�§%¹ìÞ K{øSô}üLQ>+À7�§-ýuàÖXgo#pÙqÈÌDRªqt4|øë/á+|ŸFC-àãÀ×íùËxí*zn¢$Ÿ]À§ì: Ó˜½ì¸aǪ�W¬�ã{ñõ=xwrß±¿‘¤ ×E÷öSdÑØðQZ§4+À�˜ˆ2“ ÇíŠæš ¿ÐIû‹ñ#Ô1{ö›tYú1+o7po"ÉYcdVÏ´–͸Êä½m�´@~ô�¦ y;K7ay,áÃñ•iròTzwCÒVüˆ3¸µkÀ岉.›“ È2ðf·ÓÆI^;ñV“âšsîz�|£üï°�ï:ç®V”é^IÁ÷Eïu=5ÞÍÃQá)XÒ~¼›xß9w¥N¹ý„¤øN`Ù9·î˜ÆÒ"k‡Úu[/j*„sî#¼¿¿a·¶›vá Yõ€¤½uÊíìun<½òn…4ûñÄ…ÑøB/ V‹ç\ ‡Þ{ ïoö›U� R­.uq6Åý™…oÐÓ r-×”6ŽÆï‰nš¨¤}À'ìã*ðjÝþ¢)$n³£KJä¿Ñå&ä虈€¤£¯) æÆâçàGÛÿrÎÅsR‡)Ñ#ø�^©b˜õ$ë�W�+U:óªhŒ(ì¼Vñ£Ú«q%íîaÍT£02öãeL•f¸¯8×ð ÖèœX£D@®b±ð«ø�nÐoâjÁØì%Sªø�¶/ Ô8fñf°Œ×¼‘$Ä\Ð>òJ~ zµ—þLÙÏN‘YH„­ü{8蜫¼ª£$¯ûñ•‹_BÝÀ¿§î©rMÁê{ù€üàìJ¯nÈ œ.9ç>WôL§•aSÅÞ6dÍ]í£�ð•ý ×Qq ™và]Ïž™z&ÀÊ ›,î¡ÃRÖND± €£MøF#d/ž�-É׫ø9š%àzÓ–M�ì ¸ñoXÙW›ìˆÍ%Íg�sO•=×±�°5NÏçœsßmJ8Ë»Ì\³c™ĘÆÇk©¶•<º„4ÞoÉÿ�ò,\R@•}_çibïÒòüÇñdì%[7T„Uà#¼æil˜oÝÊ,ï:ž€¾ôQ‘GïQ:.ì®BDÈpÉ2ìëj ³”md³¬�µ ®á§š—ñ ÿÑ:Ï÷ «Ã^ÁNUYØ]õ'Lk½>Ñ¢¨AÁÜLx͹-:,“Íí/ã-æZÓƒ®ªˆ�Æ]züÛº»YÐÊ~¶ÖüÎQ!áçµ]ÿîøN@¤¬ý#Á Š÷^ù-‰ˆ„y bï& úÿtFÊï÷7Ø ´4¬š1(ÿŸKƒ±„!b2î¸>#ñ ýí*ïP6;Taå7ç½0õ óäw¬ ý�4jÛ¦*¿cðâfì7+hÛÂa¤ üEocó¨}óÄþì××4”ßhpÃZ‡»¡ù‘¶‚2˜ò†s°¨�ʇxéÆŒ#GˆŠÿ¦@voôÝPU˜–ÅÛÀ…ýY‡Ú‡¨}¿Ö ,›‹€f/ ùÿ”.êm€¸Q¡ä¯Ï†,Ë‘M­ýU ?þØ´À»¸‹»¨‹ÿ�n!!w3zÙIEND®B`‚ukui-biometric-auth/images/Iris/14.png0000664000175000017500000000663215167732630016515 0ustar fengfeng‰PNG  IHDRbb«¥ aIDATxœí�[ˆ_GÇ?gw{II¼´x)n¥•ªiUð ‹Ap+ŠÕ7‚"ÕJê£}pS©—Š�V|©}øG¼¡l|Q¤â¶Bñ¥˜ÚZ*ø�VEAýoªÖf7Éׇ™Ù33gÎÿnÿË&ùÁá\þ3s~3ßßm~3{.Ñ%ºD3@’V$��4˜2}ËÇaI{§ÉËÄHÒ¢¤ž¤�B:0E~bêIZœ?c'Ûá£Q‡OX­˜ªJÚkùXO²4MÞ:%I«;Eâ¬À¬F»6«üV"IËÖþ::ºS:dµäp‚ÿ�ãCl'z‚DÙ¾øÒßæJÒÒŽcºY@Ö|í˜6O¥ù‚�¥Æ)´3¥é‘´ $-O›§qR¢¿Ó×zËÔ OB.8-(#ëÌ­L“„ÞÔ™"E¦jò`X3Ž$ðÆâð$_¼¨<¾žÜ‹g˜,ý‰iFdŽf7„›Y�Œ™Rž�¹¨ÍQEfj<Ñ”ò¤ÝÚX^p��Æ@]g•e²“]ˆÚ”üñê²Ññ!|“gA*ùÒ¬Bƒ'€�CY–}§-ƒMÈÚÛ}–wÆ^oØëSöØNY–=>QF=²–ã$°¸5˲Ÿ¶iluÒ’ÕÀe+Q.BkC'l[Ë“6«¶/’ m›½[fÖ(k’ÆÚ;H=…ùÿa»n�5ïºJ]7(½I£ÜD5‹4•‡ªc Ã,н¶&£•˪˜é”™ë,É䂎ª¸êÓ@Xõ„¤Þ{”OÜÖ;f(µòKêJÕA¯ùî% Ꚋ›ÜûWÇøn5Ï®˜R¾{#%‘G5…hÌÞ+e­kž”›ÏɇÿJïÞ�ejz©ãˆdLßZ Ÿ�bÇb* ¬&:Ö“‰$–¦ÂT ÙAZVù¾«�·î®âî� #Ê'ˆý®Õ¿¿nà—í³E·Õ ´vÊ8âØ ª­pCšó¤Ü‘ºÁŽùMmŒ›º%ÉJy<ùZM”óËLG —= ù! ÈzÔ¿ÙZ‹Q¨ÚR‰É‰$kæÖ2:ë‚Ù2q_×5 ¦*’¤aXò™Ÿ4ŸUHE³™tÎ*îq”•�)ŒŠJ·ÑXÆû3Áô²ïhhJ áÀë×äýFdfbï#ÀfÆ/”‘B_0tpîâ˜lÿTœ!—æO"uïd‘Dù�¡©u7sE•—l• G [‹ª³¯K¡]]!ÝFíì«Ú§¹«RåþxuZý9³Z$þâ�TMÀ¨Ý µ[ü©B•s_ gÀmÌôb«±TK0”Gbu’l1Ó]Ry¢-ÍKÏ«Û4ùy@á�f€*”ŠZ ) Ñ*¯NEõº¤Êk× —F‰Kuäoýcͨ4ÏhÓ™1€Qk¯Qôþ&fÙ¯?t^݆›‚ÑóêÔZXI¼³ 5y[DÔ=½¿Û?”T1šé„FBMvR,ªùü¢Öfï�+^uÓøñVÔñì‡UÑîUÃOŸ4’+U×%z-Þã›ÓÊëÛ*þýÄzÕº�)ÆÐ—*ÔŠV»ßl[+Ê÷»úGk psX%ç®âD­7v¼—Ç` `…*[Õ¿d’æ%-HÚ%i·¤Ë$]n�+F®Üe¶î.ÛÖ¼¤Â7HšÞJ³o·Ë4N˜Žü(Ê&1ɳýöÑIÌÇ?þ˜(»×–ukÛX‘4‡I>ÎóÞõœåÏ�3ï¾ ïÎ{×òž 8çÝïž!Oò̲ì‘ý?JžÊÞÀ¬l6þhLc ,3ño`À(tBÆq�ôʽx3ø€ŒÑ`@H¹‡€„sÀð.[ö+À—�³î÷,˶“~V�{}>‰¬VäV@XÆöbÖ]ýµå#Y–Ýmw=|¸×–9 ¼ ø!óä탑:9PÎ{ÏTrÄ Ü|ÂÖy¸Â9[Æ]Ÿ> øs’ãY–}pô(�¦Ö@8²öñˆ÷èqàÓÀSÀf€€û��=Œô-`Ò�ë€÷ÃOWWáJàûÀ+�ç€÷Š \|x£m{¸;˲ÎV4;@ÒÍÀOÈmíiàAÌ ?OÆ-À¯Éµ )q?†áƒàîÏ—w?~GÂË�ÏòÚ}¸èÛ2[Y–�«5P êI À.Ì@¾øp›Wä9ûìgä`øça`ø~"#îGe œ£(ý瀫1Zû~à*ÛÞŸ�{€ŸÛ²[ö쎭,ËÎV´ˆÚ:k€]Ñõ;�¯¯òª<üxÈ–q`ÌE×UÁˆû Ä¹¯>€ÑXŸ¾‹Ñð-r¶l½-`“!¢<ßv(˲ÓñïI ¬>ìO9#r.»)Â]ß|”\²þ¬c4ä ¹fTÃEVPÔ (†©)Üà»óàÝÀ[£¶˜տàI¾wޝƒÃE[2ù®cÀÉ,ËnŠÇÓu$IÊ?ª|0ÒÄnrükwÞ|Yí‰^õ(ðàÔÃkÖ Að�³Âk€·o®ˆÚxøðWŠ’îw§›ÞóMÛß“v –…¹Ã€pqÿ)àÆ,ËN[v“¶Âe€8Pö7cæWG¯ü&Âzø“íHU0|*ap­=®.‹êý éý£±•%Ÿ4îø° Ü—eÙçSc #|„’>E‚?ð)P|“Uvýfàä!aLÏb$òv`0)0¶íq ðb{¼xYÉ{žÆÀcŒ–üXÚ}b06�O_eˆIrT廯}Lã6à„ø ¤îGiÍ.Œï¸c¯¡(©Ž61ñûóí‰�õ°cfbSãÓŒ–? üø/iÉßL\— ¾ÿÌÝ¿ãcÞ<6,Ì­ÄMÀo1ƒðŒtú¾!>�h”Ö¼È+0æ$ö)uéŸä >kï‡I~Êä¤¼ì¼ ¼“úÙ‹™¹Ëýže™?ûߦ*@줞ÀhÆ „fjwtă] øXÀø“=I¿ £5Wzl>OŽ:�9mÏg£c”“6À±äÇ¿»û¯Ç8ü;ü2es�…’ñ¶ÃÔyLà ð1ànà „t>º÷£&w¸rñ §ŠMÙ Þ oÎ=üÈÉQwÙç±ä;>¶Hû™Ô¤0…]Ï'îÀ€ðf¸à•™“”ùIDGC� ŒÛo„¡¾M˜~ˆ³¦>HŽÑ…!ÏbM(Ó.D_ œ¨ù’§IÜ §Òäîˆûp.z–ºÿ"f.ò4ðqàß„Ñ�+Wð£¢&_ºç1‘ǯ03л0y¥xÎ�:—ÍÀSšÿVÖ–¤Dl†R÷[Cž¥fͱIKµq&,?…ÉO=QÒÖVÊOla}Aj wÛN;óqð Œ3½ã”üß«¶—õ{ÓvÎØã¬=;{í?õ»ÿ,ös˜0õ:Lv“ÊV'~vÆ"•Œó%ΗÂë1s‹}›x,QÇoÇ™¿�Ô{Êžùå];euc~]‡}éö¥t“¢ôŸRǯ{%Æ]‹Ñ„/a2ÃêÄšå~kFѺuë?nÙi¤p;e÷ŸªÉŒ¿ýdr»¦L ?λ>ýVø/ÑúšÕ�Óv@*nx›­Ï¦*übð@³öqÚ(Ò‚î·RvI ¿QÔøSn³D*~ukui-biometric-auth/images/huawei/0000775000175000017500000000000015167732644016135 5ustar fengfengukui-biometric-auth/images/huawei/11.svg0000664000175000017500000001260215167732630017073 0ustar fengfengukui-biometric-auth/images/huawei/none_machine.svg0000664000175000017500000000242015167732630021272 0ustar fengfengukui-biometric-auth/images/huawei/07.svg0000664000175000017500000001260215167732630017100 0ustar fengfengukui-biometric-auth/images/huawei/Voiceprint_recognition.svg0000664000175000017500000000175015167732630023376 0ustar fengfengukui-biometric-auth/images/huawei/Digital_vein.svg0000664000175000017500000000251315167732630021250 0ustar fengfengukui-biometric-auth/images/huawei/12.svg0000664000175000017500000001260215167732630017074 0ustar fengfengukui-biometric-auth/images/huawei/01.svg0000664000175000017500000001260215167732630017072 0ustar fengfengukui-biometric-auth/images/huawei/13.svg0000664000175000017500000001260215167732630017075 0ustar fengfengukui-biometric-auth/images/huawei/04.svg0000664000175000017500000001260215167732630017075 0ustar fengfengukui-biometric-auth/images/huawei/Face_recognition.svg0000664000175000017500000000144315167732630022111 0ustar fengfengukui-biometric-auth/images/huawei/03.svg0000664000175000017500000001260215167732630017074 0ustar fengfengukui-biometric-auth/images/huawei/06.svg0000664000175000017500000001260215167732630017077 0ustar fengfengukui-biometric-auth/images/huawei/02.svg0000664000175000017500000001260215167732630017073 0ustar fengfengukui-biometric-auth/images/huawei/08.svg0000664000175000017500000001260215167732630017101 0ustar fengfengukui-biometric-auth/images/huawei/14.svg0000664000175000017500000001260215167732630017076 0ustar fengfengukui-biometric-auth/images/huawei/05.svg0000664000175000017500000001260215167732630017076 0ustar fengfengukui-biometric-auth/images/huawei/Biotechnology.svg0000664000175000017500000000600415167732630021456 0ustar fengfengukui-biometric-auth/images/huawei/Iris_Recognition.svg0000664000175000017500000000157115167732630022123 0ustar fengfengukui-biometric-auth/images/huawei/fingerprint.svg0000664000175000017500000000413415167732630021202 0ustar fengfengukui-biometric-auth/images/huawei/09.svg0000664000175000017500000001260215167732630017102 0ustar fengfengukui-biometric-auth/images/huawei/00.svg0000664000175000017500000001170215167732630017071 0ustar fengfengukui-biometric-auth/images/huawei/10.svg0000664000175000017500000001260215167732630017072 0ustar fengfengukui-biometric-auth/images/FingerPrint/0000775000175000017500000000000015167732630017075 5ustar fengfengukui-biometric-auth/images/FingerPrint/16.png0000664000175000017500000000653215167732630020037 0ustar fengfeng‰PNG  IHDRbb«¥ !IDATxœí�[ˆ$WÇ53;“Ù$;KŒš¨q×Dã-º«Qò¢L#ˆ„]AÁaATÖQß&B7A"ÈD¼mŒ‚Áiƒ0ân 0—žHt ²;7ÙÛ\>Îw¦¾>sêÖÝÕÕ=³8œê©ªS§¾ÿù.çV"r@DNˆÈ’¦²Xd—BD+ÈÉËõ„ˆÈ*p¡B�!V†üþ#éô!·…°°“æä’ˆ‘ù†ÞmÇBDæU¶KFÞ'íI�c ×u×@ ñ˜·6n×Úù¦ "§¶dolÜ¡¦+¶Û "‡Tö�DD I’¤éŠíFxùO5]‘²P�Ý_òò3I’¼\g}�‘#B\|}hi~PSÕrÚÀ2ph'Iòä@*Y¼Ûn¸óB{U'e„¢C_©F|„ˆÌáZûqM!–I[ò=^-Ó¢MÙà´ª…3i‡#—·�pÚÒˆ)ÛR‚aj„¸!”“"²i©Kâz÷µt$ÅE(Ç${HbQ²†jÄ–ü‡E„ ¢c^|E…߈™gO�¢SWCÈ©ÇЉ˜Ó—îˆôš«û™e õ:fÉPµbèDèC�4¡þe Îl];½ü¯u膗ÿDÓ¹‡ 44l¸»ËÀêØ˜#�f“ö¶cX%í{œI’ä…áÔnC£?mëw”AGCÔc£¥ea¤4BD%Iò¤FV�ÐÝ>¤jòcUá áø^ôwVé�ǯø–«Ç§õ\Os%’.†8Ñ”‘ojâz·K��Žè¹Cƒ4'^¹Fˆl_5²(Cèì‰ó= !K½jÝØB±aè+F"„¬xmÜñ�í ÅwÕ^§’Nâ‹=ÂæÄ<.Ú�‹÷[egÌ$�ch‘=·`ÑÆu”Úeû"r77�Þ{xܦ[ ¡NÙ›€ÓeZœt÷#úAGœ“.ô�Æ®”¹gP¨]#MhGóZš¾ü}ÀÑàT›î»<´ˆ÷ÂÛÀI’ü,çù¶SIsGÚ¼&,•¸Ö¶þq‘Ô‘~l¶Þ¿hÉé¼Ö.ÝÅŠŒóòS}¯æ§ ®[ „4ðØ^âaëBÉz½ïvúi �ÂhCæKèËž2/{bõš“îE×�,í0�i¨þbàP2r_@[ÝÐCFqDÇ�‘ÕX ßaG@\߈Ú�R‹odôÕ ¾lœ.’9§Þ6Çˤ}‡ßV¨Ë!­ËxGFUaœ`©þ„ÞÓ –¤‚Ó7¾ãTïo7&�îH¤os v~^ÜPù‚dwþ¥Ä€¢©[íAC£�îØ¼›¬d‘îñ#‘‹ÇÄù«M#¹ì§oH÷°w¦@T€‰¢T° Rañ˜¸a‘‚èXBÒ�1¹joÈÊìöøüRÍ_xÍÝY“FæÅ2a`j g}‹Ï2�’nðìÔY�¡BÒÝ“¹v·—V¨þ`^SiŸcýÆ ë3Ò0ö9s¨l ”tÁð)Ù¾ @$g¸"R–æˆ ÚÔi f²H÷îLs#é _žP–¤< [±’*’ã”M#ï)T)±‡Û$J–¤¾Ã·x¿`lÞ^/Ûó …gÈÍg:VTÿ±€`¦PÄÅü"ùŽ\DÊm0åöU qÑúi#ço�Hj–r_£roVµ ¦E¾%MFù>Cžÿò¾¨ÖAÁ:—å·4o\çd-£ŒB hí� ]R¹ ´ 蟙·¡­y«Jýª¢N"Ê Ø_·\±üƒ¤ë\ÃùmpóÎßµêá·#̹¦ Y£ ã‹ÆwJÛÿȽ Y¦EÌw.úy¾1±µy Ã4-÷r³yéqðMçV�ƒ½–¡åø¹�V¯e”Aí[·òx•P‹¸Ù)‹¶)'ö|ï?*ù§:Ðô:/äväÜ—P¾ðÁŒó~ÿDã[ך&â¸æ�DÎݧy;ç~ï@³éïm•¯R3¨íë4EÛ…%ý Dè¹ýZNÞ\²oÑ½š––æíïšÔˆ‡}ñ#-ÍÛeiÄØ "4Üláx_ä’–æí‚¢ÊhÍX`¨ÎÒ>ÅqRßp<Ôí%{'ó;C!BÕŽ’°Œ#!¶þè8º‡"¯¥›Ðs9çÑ-ÍO‹P½ÕUÑeñ’.ɇtÓHÊ �ä…Ç»Ò ¿M7or¨kõu‰òóFN%Ï›Í"‰½KQ�úAcá«…lßr¼àú9òû �jÃÃe뱫¡s•vvmˆÄI:ë—»"DÒùˆ“Ï«]#�¤ûã:�ù:d®IDdRD¦Dd�ˆL‹Èu"òsÏ="²7’¾¡ç¿§÷LkSZf¢Ï˜Ï#ÔÔe|M“…tï =J÷Øþ*ð ðMà¹׿™À­V÷ù›�¯ŸÖûN/û‚Çí¾¨Ç7bÒ¦«’l³z]""SÀf’$›ý¿qu ;j²xøðKàœÀo&I‰˜n¾ ¼ËÜû5àWl'áFàûÀðàe½f‹Mš{"¦ôÞM%hX×|£ü[÷ŽÚöGDˆxx øðwà_8Là„?i޽&øô;œ@—€‡€g‚ºû‚·êy€�èÖK‚ò3zýýíI�×��º4¦"Dd'ä)œ`³r�ÍcdÜ ¼¼ª÷)|îÐãg)&áàzý») Áäk ˜”�š&µ³{p‚ôùù¤”!ã%Í÷‘MÄ×õøAaÞ$ÅHð¿o1eÜŠóWY$¬™ßëÀºˆ¬kI’ôm¾B„!Àç!1r²È˜Óü’9gµ#FÄ'€{pÎ{’r$lÿ1e|ç¯6LÚ&|“Ö4ßcYïM‚}‘A€ý[xl5Ã’â5ླྀŽZÜ\&Ÿ €×.ß!%òIðÂn㢹/à4â4qM°ùšÖßþm² é‰ã¦É&"$ÅjEÌ\Ý |Fq®ž%%É0©×Í_ö?Æ %%ÍçII°QÑ�·àœõýúûà-_sÿ.kz¼NlxBÖp„”î{TvÖ�x"¦MíqŒ”IºÍ×íÀà}úˆ?�WÙî3BÓôYàõÀÀo|é&aøœÿxŽ”ßêý5o7¯Úþˆ‹òBm°É“uU�¯š¿_-«•ˆP¦I…í‰ð)‹Kœ×„¢»s÷#àIºMVŒŒœM¿?jʰ$ðà“zî[¤šówãÌÔmÁ«w€“À?ˆ“#bëïe|G•�9K‚|Œk²üñ>\œÿàý8Ûîñ\mƒ¸ÿɸñœ~­/¼UU“¼/8 Ü <<†3}1'ìIyðàmzÀ§Z;Ý$„dt�/"£†„�KBøû±‚bÏãã_qáḟ„Ö À‡qG/ã:z¡ê‡$lêýnÒkþ ü 眭y‰™š)œ�yžláÛ¿e]“k¦ ‰PÇl}Átð;Ì}úyPÔEœyx8Çv­ M™MoÄù‘=8ŸÂ Ù¾C²ZǼ�ë´Ýi® ×ΓorbÏʯF~[͈vË‘E@Ö*£A{2ÒuÀ]8"þ‰#4tÞ�M‚Ms8B¯7¯ÙÁ9æ³ä 8lùElû[–‰*Z{T¤ ±¿ÍPŽ�ðo¡šÅÙèúû2.âñacIÁö~‚í „éf\¿Åò_à÷8b.¸š®�ÖúqùÐûãi\‹¼^óͯ3¿g‚cO„?Þcò¬–oÃÝœ/¸Iÿ–¨@_Õ:‡£³a/Ûvæ6MÚˆ¤5àµZ�àüϳJ†'îJDЗŒ€/k~I�/ë±M—õ=¬SßÖ¦Äí›>o2­/ìì[êLäwØúc½è‰Œ”Dùû×q>Dènù“¤~Á -‰$?ö&�sΓ¸®eÌšçÚž=¦æ8¡ÛoÙPzÓ”�˜k6‡þUDäî‚K.àHX�Eª½³¸ùƒ½¤½ìµ¬Wª 9ˆÈ4pc’$çÊÞÓ¶ä?D\À íp!I’«÷M¯Ã…®3éµëì FI�ƈ¨ Õ€7áðfë޼¼5¯ûIµœý~.I’KõÕ¶:Æ‚%áœ@¯àZö¹,­É(c7d1£e<=Jš1òDˆÈ,nƒÉ^œ¿x®�²&�w’’12š1ÒD( wâLÑKI’¼8€2§qÚµgÞ^–CÎÃÈ�°Æó‰¤ Æh ìDKóö鶦Al0¿†jð2?c?%²S>$8�ô›R"þSÒýqÜEÙ©_hÃ_4ò^/°ßëŠñþæ]�íÿ6§ â;•Äí  ¿©]ãûÍ»>!Ý»žÊâ”ß±ú?u±¶¨²:ÀIEND®B`‚ukui-biometric-auth/images/FingerPrint/03.png0000664000175000017500000000647015167732630020034 0ustar fengfeng‰PNG  IHDRbb«¥ ÿIDATxœí]QnÇ}Å¥I‰ÑZL(Р!AH�‘ |éù˧” Î ä\ Ê däÛ>‚r l@€`Á Lˆ�BÆ”—Ye—KU>ºŠSÛìéé™ÝéYEzÀ {vg§{êuWWWWÏ ˜ù*€ßÉ·‘†¿ø#€,›ÔÏëÑ“Ï{r¾äå5ÕÏ—�ùŒä€I€鉤oÌùI5?1ç/=¤Çòý1€¿ø}¢œJú5€¯‰èŸúÅéC0ó=Ÿ'ÞÐÇ+Ÿ`šŸ¼OLϤ)d�œÓ„œ> ¦"A…_F±9W¡O¼s%ä!€Ë�¤|NDÖ3ßð™|ùÀvˆèïþ/™Ù wEò+(„mó!Rzæ3¿gÔ!ƒÌùT1M‚ž§�jýþçþ¡ß�%?6Ÿ�‰èÄÈî€mwQh›¿ÑŸH¾|(Þ%¢/}ᛩðUØJ„e„Xâ|•e‰Ð|]2,RH81‡mý±–oó¡Ã'âôs"šdy®ÁÀíe8và‹$XÁ‡HÑür$_ÖSBãGSUE5 6õ…¯ä,Kª c¨ƒ?fëÄÌðÉ ¢/™YÇã»ÄÌßÃu—ßÑ?*Hð °$„Ϋz�øcHÏKËÈQEBHý„TMYk{©æË®™RS"×ßx `‡˜™…!ÿ�ôâ%L�+Þ¹ŸVTÕklO ê~‹ô­&=ÊH¨Òù!•xY:œ[5õÆ“/C¬ Vgûª=lË 4• ÿÐßÿ\®óÕP�¡fë@\IðÕϲäõ^eªfJf^ÞJ¸ÊÅž÷PôÎ%ÉŸA”é ~%Cç=ï<4Ðë|!û„¬¸à#ÉŸ—£ F’þÀ¡©Ç1Â:=&p͇"Àÿl‰™‰ˆl€SÕàg˜¶xzÎÉqA„q.�®J~UŽsò{=ÿÀ¤~Ë×òú>”rRzé,О¡zßš¯¶×øêh„BÕhþµäG&?”üüGòC“?2¿ø ˜~h;�0l*Te1…,¡�5¤×à—~!•þ—)_+ú“Fag×V�Ø&e½t gq àG¸ž2Â4!š£|P·ƒ¸’622yéXžÕN݃U Öó3¯Ø°�³- µPöy82.À©>ûöˆh<ï²+êå䟋Ä585¸ÖðÀ´YvI}.À�CVŽà< so‘z$[MóÂNEŒ¼„#à$þ“ö Â>bæœQ°×H²öˆS° SYE=-˜y…™7:(—™™³Žïq*ßaöa ÀœùöÝ`Àá[£ŽÄÊYC1y ánò4ð:·): –±f6P¸9šXx:ã=pØ¥•V……"‚™ÏÑk±¬®az6|ÚÒ% anÖ®7Ÿ¼}G]Ì[ª°DˆÙ¸7Ïø–ˆNÄW?†›s ‰èuƒûªqÓ¤ŽàfÑ CH§DˆÞÿÎé§øŽˆ^ÉLüÌbÊ e…Ü+ CHgD0ó Š,¾{6åPB~hÒëæ…ìDˆ ®¡èÏsúwL=,!8?Ó«œõPd%"àø{ND{9ëàCTÖ¸±pÖNn +2\CÑúž¦ªi½çázQÙÚ‚Ån ¤ª:fÞ„#pcÇ“œdd!Â#aGBô!½yD?vmFp­ü Šx¯ÇÖj,³"Çb�%aàYŒÆÇ(T…b€b1ª(¶�ð,|àElðæ0ÙÈȱtB=­¸ö ŠÖ?�̈á&a�Ô3_D� Â�A{Å®ñ´jL´F„<ÌM¸9$¢'‘ë.£ÔÀËyÛö%fës)ë Érýu¸žÑú˜Ñ&ÚNPòò°Ûp-v'”—mÕÉ”¹·L )÷Y¨w˜ÆÔCË**‡jBì˜ù&œ…“Õd”±k®Ç–¶ø”g˜:÷5ÉàxÒ…g4g‹¯B'Dˆ�*|fþ´ä«�ÉkìP­pœ\-¾ 9£8L ‚`æÊùDú¡¼,�ª£˜±c•ˆžÍP§FÈíâ°–ÈÌ6ºèy X‡è#<ùKr(ÊxµçlÕh𑛈ë(lóVt²�­Ñ|vRX<&ãÕM9}’s©5[‡¸½µµÍE¹îš½Ð÷U ¢"z%ê帹 Ác"ø=8•½Ý¤ü¦È2F·àº}°U YëpÀ™­(,3è§´p"zÉÌëú̼‘kÑ(W�P¯æa™î5+h¥®�& ¢±(3ÊÌ×Õb ๤[ó¬G ­!ëÑ:.ü¹t®‡îÖ0k{Ì|AŽº›Yúpþ¤3�;°š+ 3‡jÒVõ²L5ˆõÓ0Š©0¼Ž"ZÃ~_ê®° ¢GÌ|ÀGõóÀ ¸^Úºzj•°º¡cæ ¶ºàj]I�A«>aæ�ݾçoÚ@@ÐDt$Ä®1óŶ—PÛî*àý2u#­\=¯gB?ÍúÀ2¦ÆFpÑ|'æ>êÌÛfæILx²3€”{%õÛCá”l•ˆ¶Ç»\�”#ñD�-Kþ["zFDD4µF!fë.€ïä£í„qCÕ.”|¯.‘jîh�Q'Ë¢-ÓÑAÑ#"z(£çÏ7¤¬)ûŠÿ:f×À¥ ,70j¡Í¡®rÀ©ÊÂ(ƒ0î’ë2àTW¿B€Zf,AÈ,ëæ•h“ˆT« êºtWëªCÕaÌüTÕÛŤØ[Û#´•–ª�êÿZDˆ‰ª–XH�j •êwcæÆz„*”m˜ r¨¦FŽ33ûm´çN„<�›”5Þ·gÜ1o­joé êc6‹%*D3~ÔŸÚ@×{èTÈ!õs‡¤B\F¸ªÏÎ7°tM„¤¡y†ºFbcŒêö2Af±xæ�ÖfÖ!»ßBÔ’ ò0ð�â1¿‘¶è¦ª¥r“ ]öˆmI÷ãHª€TÇw®ZfE'D˜Õº ÂŽ>u9¤š¾�F`ÌY£8Äí±�ÂÉ·ã÷ãêÞ¡ýß¹–Jý@àØB¾îq›TDªZŠE†«ŠëÜ<­BkD”…E·G‰pO’*ŠÐ�>6aŒ™Ç …\ªi'ØÒMç& yn¥®jKWt‘^¸&÷êd_\tf¾Z6‡ìT\]Lhoè|ën ²‡\ú�½k[˜ÞÙYå:×—¢"áô—ä~1§½³Q Õ<Ñ fÜ& ¯ft�ùí&ŠÞPæÙ”´êý)ëY�Ëj²»B×1ýàÚjƒ;wÌ=VàzŽ5}ËzƒÑéÖá:Èm5Y àôw´Õ–¼ %¥aVí–ž±/,rª&Ý:@�w)ÑØ¸Ëá6É—©/]µ›ØM¸÷‘„ðG�‚u �¦è|ÇP ê¼ ¥ÎÆ!ø×r}ëÂŽ¡s«)‰BÕðÉ:{ñN­¥HlSt½q¡™„ßhùJaz·»ÃB!NÁ`ˆLä76мɖ«}I/›HÙ±0DÈüàœu¤ƒnÕo¬•´ rŽÝkDà3o5Ý$3 :¬ïÞØGbh¾ÙóöBÂ-C×è^ dÖî½òA±gZgñSu6X‹SÎßç–Åm„kpnŽ˜©j_Œì1BúSÙ ±)÷½à’˜·I³þY��3»Öý 6`+¹´õQ1.È\a'Ü+²,GÁ�Y?éK=×ÞÚ7$̬Gp3ëƒÔÉ�7ËNzï“üÎn+Ü&”¤rå·+ÿODèÿE àto­“Vº�Ä÷>•Üã2Š—¡À Dv2åDçƒuøìk„fz ÷2E•ë¤u,,Æ‹ªïWJÚWãþáöOXB†pj«ñ‹ºšbáˆ0‘ëHxÁÕʳ–’"û_Ü3?"úC®B-xúO˜ÔJŠuŠäÁ|Æzø‘&ßd*×ÉŸ9ï?ªÌºNá-2­¡|™S]îµÔŒXfý\o8•ÿaß^YúžVãSòç U˜À»×¥wµ �QÆjÒ1CÍà!â‘€:!SÝ?×Á~^x+ˆð|@µ'€rkeÃqžÄ·áZô!ÍðV1ãøS2¦g,4<ýâÞRÏjÍ{úAl»¹ä–�„$ol�{û!�Ϩ™ˆ_Á©�¹’à•áÿ‰HënîH]²ÿWi*V�S—t+ ¢=f>„3‡/!ƒ›»,è´B‚Z}«@EùNþ\àbW•yWÁîOt™™y ÀCùüvwUzgq[Ò‡KËÉgÝÔå�†Êü1˜ùªQOw:­Ö;f¾cä~U?¼g>|púÅ{ÌÒðyßó/¸ÏÍñ £çêžPëâ~ÙMo1óW nøcæç_0ó÷ äõ3ß²÷ùˆÈkHT5ÕIEND®B`‚ukui-biometric-auth/images/FingerPrint/07.png0000664000175000017500000000711515167732630020035 0ustar fengfeng‰PNG  IHDRbb«¥IDATxœå�]heWÇ{r›´éÄD3M›:¥)m§V[[¨ŠàÇŒ   øæ(£à“/UÄæA…AQ‚>¨ø2EP‘éƒZ­R�Ú&2ÃÄÆd&5Ó;M&“åÃ^+wß�}>îÇ9çvò‡Ã>÷œs÷Ùwý÷úØkïs.‘ûEäi9«[Y,r@!"‹=ÈÉäú´ˆÜŸUá©*Œqµæß?2‘¥äv*®ìtpò¬ˆœ‘ã ý¶["r\e{6�÷éð¤ádÃm=0PB ÇCw`í|S‘3{²lÜM7ì ADžPÙ/9çœkºa&ÿVÓ ) ÕØ™’—ŸwνZe{†�‘#B||ý$pBËÝz­à° œÎ9çþ2”FVsÛ ·á¸†Ð毪ĢŒPth�jÄGˆÈ4¾·A·ËtzòyÝß(Ó£ƒºÁkÕ ¼I{2qù9à»xmiÄ”í)A�!>…rZD®&zêYñ£ûJ’â#”“’�’X”¬´C…Ø“]D¨ –‚~U…߈™oÏD�b©ªŽ�ÓŽÚ‰˜Ö½$>é5]õ=Ë@Ûu2è$µjEíDèM?Ù„ú—�x³Y»všüGv@'"8¸`³ÏefA¹«¥m»Î¹F#EƒÉ¿ñq„ˆ ø0ì›ÐSd@9"vƒ} މˆÜ >ßÔr×9·›¨«r´ð¡aÙë@Ð^nÂnѾ Ïg‘Ý„dÁ´ökE’`W Úvì|ÅÚ³ ÌTnŽDÄm[‹|2Æè:$ãÝÀ#ºÝKZ#6� À?u»L·6ä’|ÞIìïàI©Dc*!BÍM‹ŽÐ³Ê� +�Œ)àÀ�‡õs¯øð"ð¬n¯ÒM‚SŠ„ ¼Á�I*"Ònà ÒÊù¤„$¼ x˜¾<Tÿ²nKxuNµ}N·€w‡£ó¿Ã�ÔK7eH¸|·雥…”�¡`eLFŠœ°ü(p/¸/×�Ÿ«À¯�Ùï¸ãßÚrf�§€Ð�8\~Ž'&|¸e GÏÅ„ìô ¶. DDá±x?ÔŒÛðùŸÏ�Õ~ßk€+ÀÝN;å¸÷š”(ͽø0ð>`RÏÿø%ð{:ÂÏÒ„°4ÂcÛ  !}ø€q²‰ˆI µ¢|øLPí³À¯ðv<å3BÆ‚öÇ¿¡+L�öoÀqàCtyø)ÞôÅš°¯çe¼ßµõmõLD¤FÄ8a‡û)R¦€oàm8À?€gTadUDF<ÀÛk"‰ÝÒŽ¶óýø``h?þLwO�{~¼ÙyÓˆíàøvYíè‰%aœŽ°�Û²1"¾Ü¥U>ü†ŽðMkz%#DB?pø8ð˜~ÿ<ðcà”ìù¤‰Ø;^Æw”&""!|Š”ÐdÙþãÀ×€;ñ½ï{x§™Š´B§~ßcïÞŠ7-³9¿A€Wðcм©‹IKÛÞƒ'`ø6žŒ�ˆíÄþ�`?$£ë|¥ˆHˆ IH}¶ýw_Å ôð}mðmÑú�I|8ûpO™vfà5½ç‹Ài'l½}ø,Þ±·ñ“Fˤ{ûvTÚ~Ö5¹fª�uÌ¡/�>Çe /‹*€”Ö´ðBgi×ð½ü>’Jù3G3x“3Üœ_Åû¤e²mþ$ðiüXæ:Ýdd‘Ð%ðÄçP3’ƒÀ2Dd�õ9Ôœ‡€oÒ!ádkÐ=xç9¯·ÞÆ�ŒWñæÅ¢¥0-‡²aÃÌÑ4ð|Zİü¾¦z»>…ׯëÀ�¿³¿ç°ïX–‰r*ì8óŽx'€Ûu³ýñhÿv|xì0ðeàˆ ò'¤µio‚ ¸‚ÏÅ#ò˜„ØqÐ�?2“p·Þψûp•´fŒÁw¢+À/ðæj¯‘7´´ÍŽ¿ž(_Çjûá˜Å'•ˆ8Ä׆‡ñ*~{¢œÐý‰ˆˆyàcÚà?è��£¬ ¼ z“^·© Ž…‡[<ÂÎi‡Ñ“mcÚT WU@áXÁ|È£*—?)!&ðmm«aûí@è¯é~;Ø¿F7qÞd)á�JÍä#çÜœî¯åÔñ^mÔ *„Aî Ç»t‡¶wâ;Á„ í¯zÿø;Óº%:ž5h,[îí;çvŸ•‘q|&sàÄY÷Ã÷ø1à‚sîzÝm04B„ €²Â‘§2Nmû¦î›Î¹k=´åmKc$@S¥JÂ1Ý¿0 &L¥öuxXwέçU`h»æ� çÜK´©/Ôª “x{<�9›o˜À;ß)ÒHkÀŠsn» ¾Gµm�s«ý¶«ÔMÄ1¼ &!çcø(ïÝsñ[ÀržÙRõ¨~|¡ˆ¸a¢h~h‘y:½õ¥,DäAÝÆRç‹àœ»éœ{UÍËóøñÈ^kr«‚_Á›ì…~îß/jñêmd{1«W*Y3@{(Ó�*XY¦ÊôpçܪˆÌS"2[äc†…º4â>-7²l¯š…9Ôl óæÎ¹íP "ò”ˆ³ˆ)�ËZÎgœ:*'BDféø…‹9—.à5ôRa혈Ö-K¨Y˜¢“Vé‚jì&0¡í¯u˜&ëU«Y¦A£Ÿ)`+ϨߘÑmœÎT§�ß"ÇÿœsωÈQàîós¿†j??Q)*%B<¡óÂAëu+9õÜKñÚ¦ àí"²\¶¯à“€³$휻¦ÄNŠÈtÕ²T­&àµ,s£½üˆ~ÜHœÇ›��äÚ†í[½Á€ìn`ADvò„眻)"›x§<–Ѿ¼ÉœÁg�+CÕ>Ââø}`ƒ²�”0Ôœµtÿoι—œsëιkáõ¶^þ¥‡Jø�vÔ†–B©|mpeD¨9i¹=“޹Ù̺À9÷œsî¹Ä=Æâñ†ÞkYï}_ü�æ³&S'µ´�VÁ@O¨R#LÀE 8B;÷ªAºäX‚Œu¼éš* Ý3I„Â:H?koK£J"Ê ØÕk:Áfû&I›3‡yá§™¶ñœk,{Ãj„õÒL“£0ûߢZ$–¤EB™ö=só4bKˉœkF¦©¯ÄY0úÍë­™P!ïàe}Õ¡õ˜i}Ú& ¿§—ЃE,¹B üGOþ© Ô–}Í€ 9e¾òÒ!eaÎ"ÜÌgíÓ´1š&Âijœa©‘<c¶=K�µD<Ã@e#ëTÜBÍ’ r#qΜx^ÞÈzt¿¦¥p SšÔˆ-×~¤¬€ÌÆ7nZE#D³u;¤}–r(ú6ºc¨u‡¦=fé$ù–cmRÝ�Ÿ£º¥P×Té4^¸F@ÞDþ,�UfOBÏ­¬k蘸ÆÃÓ"TFDÆ¢°<É$  wo"©àæèóŒyáñH¡.ÓÔÆ 6™ê†=“´ mÚrÎ%'‰äúÕÂI­kä_´ØXø"˜ü±…gË×çN&)LjY…1(Fáí4sxsÔ¢cºŠRçGµÜLù‘€¨òMœig_k¨†‰FˆPAÍâ'æ-«ÙÆ“�Š*q¦ Yi�9-3MapOÈϾւº¢¦1üàË’xá·^»š'45_ót‡¾YÚ`Dù™‘AÝQSˆM¼ýÎíµ‘ÿ0$Wi³v-Ò#ö‘E�¦io 6ñ«/J É9·¤Ë7€Ë9æËfívð�ôÕ}M—ðç&{ <úEãO •�Ž/J½N¡—O”àÇõúÊ…�‡Æ£¦2()T[>¹ÜÃæ½h)gmS-hz>bRKdJ|ÇV‘�÷"̈àZÞk˜…‘"B“‚É%29ß W‘÷óÈÕš–Gƒ'�jÇÈ¡ãƒGðÑ‘9Ý¢ï„QÒ¥œEÎyu]B‘�ˆÈ|¿É ‚Æ�uð‹™†5J.Ížy{E—[¦®±Gx!cÔ®×`;â•&Ï×t_/‘zÿQeÐyŠh’i’ìiNK¹÷df42›ªë�{ò"lžâ:~p–—¦˜cÿ¤;xbWšÌ®f¡1"zE5™Ï°0¸MþJ@�™íª³ÞDD9 ž€ZGmá_ÿ32š1òD¨_À÷è 7À[łğ‘12š1ÒD( –ÞÎ̬öXg¼ˆíR]9#KDDB©lluÇ+BQ�2�áMÈPIˆî1O÷+ª+Osç´e4þ0� ØKIWçÜŠˆlàÃá#Ô�æ.„(mDƒÐÅ •¾U àþ^þÒÁHü›îA‚øÿ–üszüDsM:°8¡å¹CøÿÔøJ3m9Ð0™ŸGüÿ8ù·õƒñfn¸ßž .ʈþù÷­íø‹�¼OÅœ–þ±ØÐïj‘P{Åé¬J�‹È™>*¼ZóïˆÈRò:#"ÇÃzþå醲ûŠ—„IEND®B`‚ukui-biometric-auth/images/FingerPrint/06.png0000664000175000017500000000700015167732630020025 0ustar fengfeng‰PNG  IHDRbb«¥ ÇIDATxœí�M�G†Ÿš™Ì$Oì`3ÁÁ–D ÁÆY ±fÁp�ذ üoÙyÁ0+$„DıH$¤  $2,ØšIœ1žäš±çó°¨sæžé©®îûÑÝ×q^©Uuûöí®>oÕùªê¾à "gDäyM·º¸ÌC ¹<€œL®¯ˆÈ™²^à„EÜiùþ'"r}¹],žì’ûò5¹ "ç;º·�,Dä¼Êö5'ïKþKÃ…ŽÛúÐ@ 1œ÷:î¡Õó]AD^Ý—½Óq/tݰ‡ "ò‚Êþz!„®ö0Âä?ÓuCêBG챚‡¿Bø ÉöŒG„DÿúËÀKZ.é6èy^–�7�×CK#›€™íŽÛp^]h³WMâç"òr—÷ëa�êÄFˆÈQboY·"þ ÜÞÞnïSzLY{Ÿ¾¨õ¯ßÐ}Ï'Žý=ð3âȹì…ö¹—Q±/ÿ6‰‘%à'À÷9¬ïÿüøðg¢À§ˆ·ÒÚhûrØl¤ ð,ðð5à;‰ãü¸®¿ÝÑr7„ИÆh�™¦�¯¿,Çò±‡ÿ øµ3¥¥ Ú“‘Ú FŠïÍR²íjùUà{DbžÐßÜ~L)»ô ÙµrÜ#¦Q"DdŠèÌ;< ü•¨b.…ÿ?ýnÊ•ƒ�a°ºï¹9ö\}8üø4ÑIø \¹Í˜Hi„™! ÒÊ·} ø'ð.}’< ƒ’a¨C„'Á>!»ÀSÀ ÀoH“°í>ûm;„°;œÄÆL„#ÀÊ")r|™#ÃÛ‰"†*"ªHð‚÷[™ðwô»"!;CÈnô€®„¿¯X÷êÊ“2U¨×%"‰rPÊF‚/·µý~ß´ˆ =BfˆO݈5Þ]ßÌRND‘?*ФXY‡Œ ŸáðÈ€þ(ØKÔMðÞ+J‘àG‚õüG´´{ÙÖúŽk»²M$¤Ž·µ XF�1ëèë)R¦I«¯*2> œ>E¿ãÛ¸E´Aïë4ÎU$¤zqq³ï·´¾åöoÕ¡$ÌÒ¶a[!ž¸¢ÊòDX}xœô}X¤­Š�÷‰ÂUà‡mA©ve±žÚŠDìï¯c;jQ Á >EŠWYeõÔH9¬Ç�o 0¬ÿ%FÀwHíÇu{’8rf ·q…~Ä^&ü\ÏßJÔ·]Ý“qàû*2jáH(àIH}®5¶½Hôåçˆ1ÆðCà® oèQn34—¾:šž&& ŸtÇôˆÑû;”÷ü­D½Lø~_Ù1Y5UI„fo f Ÿ‹eAž�Ï(¿¢á·À ðI¢ÎuO„‘±ß\º¬Þ&ÌŸ!’b#¥ü…8Br*'%ð²r+ñÙ�ŒdX‡ˆ2Ê>§TTŠ�oG�áÄtõ&G‹·))2ü¨(#ÁoÉø<}BVˆ‰¿Uò.öü*í+SQY"jŒ†Ô¾9ò„<|—þÃMbêãýÄïÊŒ~Š 8'xw´¸A!gõ›ÀsPÏ×x–Ý6)qkƒ ¼íZ}–è­<®åœ–�ºÏs…ºaõG\ù b’Íôõ»À5ʽ(ïÒú-•ö0ø`nÏmŨÙz”è˜W¶Bôíïspl&}Ï ø¾–÷´~_ë~»O̯y›³ l[dí#[ë…ÓNÀÖS矋½8EOé±§‰Þ�m[ú?ÇPLSŠiqOBYªHD1~˜Öú ý3E4ð«®íż—o딫=¿¿¾wÐëw¬íL‰Èà"1ÀÕª@GGéqbð¶0Âå7‰^×í½Šk>¦íœ# ìjÕoÆ…6&ƒ< =àZŽÆÓN»ôˆ$Þ# 7‡bzû1¢Pý9ÞË-,‘Ymï<-’Ñ(*Ô³( !„«Çž¦ßûwˆ=y¸;lªY§e�'Üî `¹LÀ:ŸÑ¶ì;ÏÝa®_�¡7sŽØ#7BW2Ç�¢/¨ àVávíYÔÍlãŠ^ëÉzüYâÈØ®Œ2ïP…&‰°Ñ°KÉMèÍ.{ì&Q(·šj“»æIâDzÝk©Ñá:Ó4 «¨6T¹‘sDïi¹É—¸îb'˜#ÓãëÜÃ8Ðù2K5Ž»m’à®ÝZ�¯B'D¨¨+|y±ä«ž«[ÀÕݶÕã«Ðú’Kg‘Êx¢ ©ºN÷ˆ±CÖèÎvÌ…®�Ц¡Ðêˆ(x"#ûèªç¡á/�þÖ€ÕÂVÅùÎiÛn4í4Ñ6géûæ�èd%ûÑöAá&Ñ!(U[j¯ÎéÇ+UÄ�UËÇ9I¿·&ÝE=îݦSßW!„°Bø@ÕË[ÄXa“8j²‚UÁ¯UöÒ0×­Ø—¶€8쓽RÉ:F Gö¢L°"rX¨ÓÃC·Dä° "ÇÇX–¡­qZËõ2Ý«jaU[ã¼xaË TD^‘³æ1%°¢åÉq¶#‡Æ‰‘ãôíÂ�Ì¡KÄzs·vZDŽèV&Ô2,óI‡ #¶ÌiûGªÉzÕ­2Õ Þϰ™Sj7Žé6Kôpü÷¥é �Â"r x*£~VˆKù�ÆÕS£D¨€- �s­×­fÎó4ÕósÀs"²\C·¯óMÇI:„pW‰�‘£M?“×ôˆ0¯•©íå–y]O|oó3ô§"×­nç-$ó–Dd''¼®ˆôˆFyº¤}«ô“’�Ñ´�0?þ�€,([O CÕÙŒÖß!\ !Ü!˜£P·õ&ð/ݵTÃnlÚP„¥PZ< #BÕÉ �í™ôÕM¯ì€Â!„7ט.Æz­e½öéâo 0›5ŸúR;Á03„30š&જ a#{T.]r6AÆm¢êZ¨ ]3I„Â:È(óæ•h’ˆº6A šN°Õ#ó¤U‡©Ãœûiª­¸FÖÃ<°vDX/-U9 Óÿ¡.ªyb)Aš'Tªß�››¶Pa.sÌÈhC5 •8sÑo®·–B…¼C ʆ:‡žÇT뫚€|O¯! FóX²Btöc ûÔZ˾–À„œR_¹tH]˜€Ë7õÙú4m]a†4gXj$gcL·— ²�gh,²Nùýª–L�ë‰ï̈çòFÖ£‡U-•1L[èrD,i¹–°#ud:¾sÕ2*:!ÂÍÖí�NôYÊ¡®ëÛé Œq ÕUšö8N?É·\ .Õ ùÕG mM•ç&ò�ÓÏQåVšZÊ­ 7×¹{Z…ƈ(Y¶C$ ™TáîO$U\ }.`̹Ç…¶TÓQ°ÉT7X�n‘~V3û�ûí"ýÑP–±WG”ªBwMÈg_[A[^Ó41ø²$ž¿qëµÉ'wÜ9f‰#Ç»¾e£Áˆ¨²3ƒ¶½&�Qg{mÁ~’«4Ü¬Ý éˆ}bѦj²§B{ÄÕµ„BØréòu`%£¾lÖn‡øFƒªsßÕ%üÙ¤à ŽÇ°èü‰¡:Ðø¢ÖK¨yðD ~^�o\Ø9tî5ÕAM¡ÚòÉAžÅÛ÷–2k›ZA×ó‡�Z"Sã7¶Š|van|íRE„&“Kd2¿ñ«È‡yäjMËSî ¤Ö11Dh|ð,Ñ;2£[õï%ÝÌ,rÎ�ë&ºˆ xVDNû�Ì(èÜX'Þ½±FÍ¥ùî™·÷t¹eê{„J¢öÂ+ kD׺•Íi)÷�ÔŒzf m½q`_þ@„{e¯"M±Èᤠ;DbW»Ì®–¡3"…óšÌf˜¼A~% d¦ûÇjìÇ…‚ˆBhàPÏá½£ÆßV9(&ž5âKĽFx«˜Kü32&š9øâÞÒÌê€ç,.b»Ù–AÎab‰(�P+;À¹‹+B:�¨'™ˆ/UÈXI(\ã$ýyA iîL[&öÞç`?%ÝB«"²Nt‡OÐBš»¢è´B+4úV�ŠëGùKG»jÌà 9jŸ"þÉÄ¿úíâ%-_Ÿ"þÓÄ?ÔþíÂdþ&"rÆ©§ �6ë!‚ˆ\pr?c;/º�—÷¿øc‡vüËNÞ‹\’áq¹£ûꡊKe'=/"¯qÂ;-ßÿÄ@D®!¯WEÄÿ+%ÿÕgdØì%¯IEND®B`‚ukui-biometric-auth/images/FingerPrint/12.png0000664000175000017500000000717715167732630020041 0ustar fengfeng‰PNG  IHDRbb«¥FIDATxœí�]lWÇ×ë�ÄI·I]Ò&$Ui«ªA _j¢6©€TÒWžRÊ„7x@2¼€„RÄÈ­�x ^øPíŠB…$-EU ÅnR¥Mâ'ŽíÎ9ž;³3»³öîÎÚî_ÍìÎ�;÷žÿ=_÷ÎÎB9("'Ddʶ²˜d‹BD&[�“Ëõ„ˆ,ªp¢… ³˜ërÿ{"2³¹Md+;�œ‘ã"2VQß6-DdÌd;Éûd|Òq¼â¶n!Ž±ØÆmY;_DäÔªì#w¤ê†m5ˆÈ“ýL!„ª¶áòﯺ!ea;R²ø™ÂÕN¶§Ýè9"Dãë£À¸íÙÖj=ÓÀ,p˜!¼Ü–Fvî¶+nØ…Ðî¯:‰Ié¡èÐU‰�‘Ýèhʶ,fIFò;¾RfDGuƒjÕ8jҎ柞Aµ¥S¶ªÝÔÑ)”“"2—3R§D³ûŽ$’¢Êq)ž’˜”¢i‡bUþÝ"Â1u|΄_‰™5‡§2ƒb¦S¡A;ºNÄnëôŒè¤×îNß³ ¬]Ç£AÒU­è:vÓcU¨ˆšÍ®k§Ëÿý„®b¸üûªnÈûPôa¡aÅíØÊ˜®lsdÑÌQ’l;WHr�3!„·ºÓºM ‹f|Ù6/ï(ƒ Q�÷J”V„žÒ9BxÙ"«_�ΆÏd¶<²Í窲“„Ï¢YôsmkôfBÇÏùȵãÓvnMk%’< q:GSzf¾©rˆf·S!³sGÚiN$zå}B¤þ©‘IéB²'ê{&2„L­Uë6,LS!tý‰‘Bæ\7=¤~âo¢ùUoÓAIñÅŽ»aus b �„FÐx¼ìŠ™$k ã¯-ĘF¥é²¹„ˆœ@×&°k�n´åÖ¦0§ì&àt™'é&éù#‘�‰ú«9Ûzò±ŸuCÒÓÞ…1¶%Š2ÁNH �‰N«ˆ4I@7$$ùeLCµ�È*L×xÿƒÒš¿pÍÝ\‹FQÇ aÆ,t4œõ_d%ù�çL'ÛÑUHòëɆvw-£ÐüÁ˜m¥}Nì7ÚÙžžFdŸ �òF èã 5é‘‘»Däiù•ˆ¼,õ˜‘GDdXD¶Û¶Í®°ºjV·Osä :jS[Íd%�ôo¸‹¦úDäY+ó´ˆì‘]6ÚGDäù’ˆ¼˜#ø"|ÝH»Ó¶½"²Ç걺ﱲ/Qý"Ò—iÛŒ•éøj§C÷”íŸ !\‘ÔÐG=ûmà£òy`—}ïÛàgÀmÀ9à5à÷Ày;ž·kw_³º~Ü~gç¸e{Vlÿ'à1àtíá–ˆ¬XÙeà»ÀOѵ‘Â5Œv ÓDøâίEd;JB?i2>ge~kûÛЩ'â¿öÀvÎ7Hˆø1ð ðCàÀÓÀë$Ä$ÜÞ>imø��sV€¿x?Dä«ÀJáÖ:äQˆŽa*þY’õéç�$$ÄdðMà[À òIX.ÚuþHš„[ÀeàUà0ð(pÆ4f‰6“ÒV"D¤@é#ý%òIðýa+÷i³”%£�4 ;�ïÙµßFÉðÉÁ—€ èrçàߤIpRÎYù‡íÞ1 ±V>üÓ¾_–EdX !¬¬Qd«h ¾@ªþ;PÁ:I1Z¹yÂb2œ€,�Q»fx‘„PÍø<ðà9êIp­õ;ìs¼-¡$bý&!bÉö!Ë-Šnë"¢€?¾ÝнŒv ?ÚbRvZ¹k$Q†Œ+À ÀQAÞFB„C‰øpŠ|Þ³ò÷Y;VH4Á÷—¬ÌQ²–l°½V[�†¬‰óýÀ ÅDà'¨)ø9p•´6Ôìš¡hïÝýÁUà:°âeÜôÄ6~'‰ð]À˨³ø¸õÃû·dÇËÖž !K(!¥›Ø2-p"£ú±ã ‰FÄd wE圈Ztýý¨þLZ3|+"ÂGÿÛ¨é;ŒjH–¿ÿY’Ѿ’ÙDmt"–¢¶:±öö¡„Ü,«-a$ ’Û‰ð-&ı�4qýQ™G­Ì¿P²œ¨N>n×ÇÑTLÆ ]ç þ“´Q«#vÂ+hšsÄöß}€�ü¸/µÌ¶µ)`#£©ï(MD†„Xðy¤ F—f‰ˆÍ×§¬Ì뤉|ªü=ê£)ïø¬L°2�Î.Ûw‡Ðü"kÿ]£úìþ±&Ä#ß1DýÈÏjiœã¸ìhFF)""b!fIÈ~~ÂŽ‡ÈךQÔÉ‚F&qdu;J À Š£©a+³H½�¸…š¬¼GE±ø��ÿ‰ÙÉšš<"<�Œg}ƒˆˆ42SM‰ˆ³ÛîØ)ç}nF�—ÿ²ÝâT�Û¢úîµs¨ÏAb"|þÊMS6ƒv¢<:‹ÍŽ·ÅåàfÇMMŸÇÌ|®WfsŸÔOBFnXF#bÚŸó9KH^•%èqTØ7PGœÕ×”9ê}L† ²�4Åá> Žv¼ÿ®¹YS“…ß/t,po_ü¹F.÷‘ŽÔVÑ«£>åñIâù!t´l‹Ž3Çîâïbâû»ÐHè£vÿ v>kòöGí»—4ñqû4Á¹€ ‰ „ÜOÚG,£¡-À�hv½”³-F÷yuì‹Ñ9ßüû9ûh(}CDn� ½­#";’­³NÀNë̶œý�QO”�ôÝè(?@2ÒÎ[ã²yÅ.Ç;O½cŒG­Ûo!ß^Ç ^œCøqÍÚº`÷ŠM×’ w øC$ð›Ö~'Â�\èÀÿìx!:¾Fš¸%঑õøy‘@Ñwœ;BÚ©ëüYkX^Ý;Ч†ú‡¹÷»Øg�;[Іƒ(Ño›âÐVÐðu™] Øä;œma©r5Z‘Z;X+zî劢�D¶NZb6 ¶"Ì ÁeßÄßô"²u¶”%ÃÌË(êÞ\ÃmýÙ¦ývÿJÐ3DX~ð ¹ÓmvM%�+ "gŸ‡shÑ<("ûZÕÈv rgmÎõnÓpjÇüJÜ…Bn”dB}È>æfíVæ>ÒÑÓE4´îÊj*sÖ6‘¶—´mÎÍr®­¡³´Ãè4G£PÕ§èA§žë`¤¿!"ží[ÛöZx[*ë_ºFD”]�Ø6�.­½ 4ñ –+, Â= "…Q• ‚K6HFìCÀp'I€š¦™õ"šY_*›Üe²ìà�’&Ì}‰gççËÞ×®ÜLD,£‹8ó¨ím©c6J¡Z<¼ÙjÜ/"ûI?Ôv�ãª|*¤rgÝ 6"÷“Lö5\Ä)QßN”ÐØ46›:é8z–ˆhuÕ‚ET Ú",Ó°¤ Y@ÍÖµngÙ=G„�Ø=¨³ô`âi†e”Øwªœ]-BeD´Š(jrŸáað�ÿ ƲøAå¶9ûvaC‘™j9´:âèhx­—4£ç‰0'~ÑWBk™âöº|âÏÉèÍèi"ŒŸÞ.œYm±ÎìClçºå�¡g‰È�Pj6¶…º³O„TžQ÷2‡QÒV2÷ðg^ŸænÐ�Þ|x`V§¤;‚Â;"r ‡÷Ò…iî¦C¥�¨ö°Âöæ%;v•¿$ؘ/!ßÀ}o”ˆèO¶¦íûñêš´e1nûé>’?×ûF5mÙÒp™Ÿñ·K:6Ç‹7$y餈¿tRÒ/Ç�”Íúà€ üÉHÞÙñŸ[´ŠÉŠúU9¤þosZÁÉ¢JǤþ�Úe0×åþ÷ $ý¿zeqJ2¯åþ?[�ml­¨öIEND®B`‚ukui-biometric-auth/images/FingerPrint/04.png0000664000175000017500000000701615167732630020032 0ustar fengfeng‰PNG  IHDRbb«¥ ÕIDATxœí�Ýn]GÇc;vcb%�à6!¥†ˆT) @•¸mÄð 7\—'(%#GN]2¼�HÉ0TÑ„¿ ¤¿�€"b„ŒêÊ,„ðŽˆ˜=¾œŽûeáu‚BüµôØ× OÊBr\— ˜$D2û¦$Õ¿7üµÖùð!°DDB¡ü±‰LXË‘’âkE‘ºªC†yVp¼fÀ¸<Î{ã<¢˜_LèiMH 9¶•y[N–‚~l#$µÀˆXf,lœ#e‘¼úª"ã°J=v xÈ$uHÈ•þÉù’îí]GLz|G…GDêÖŽFD( ËŒ…mDØVDˆ'.UYžˆÀYàÀ��€3Àé&ïép øøøB÷©-(4ÂŒIXb,ðt{ÄdhB…*•¶£6 ^ð9R¼Ê*:ö]~ \! ~V¸¨ûWܵ_ÿ$/ü²’ŸªÊ:®5"Bµl„#!%À“�;/ª5kÀ�_¯f²ü¸üØöT@ß’·‹Äô˜X»¾¯ù朷€¿Ÿk~^çdŽÛ€ƒdoÇE÷dÕÔ‘ü«ˆPÃìmÁrržîËzø ‘€“¡Ü&ª�mòž–÷°|iI‹¸cã¹CìElÜoÐæŠ9Bx "ËÀ%b 0•tÝç`ÎÃ*±ñ–’· Ü!Ü�é‹ÏsA„ˆœÎ½“�C‡«? 6úöBZ¤»L¬Qg™$uØš'B%BõþbìÉðYឈœ¤ >Ó2¯e`�HŠÕ”¹!d0"Dä<‘Ã6Q(�Xµ=ëº!»ÀWmjݬÐ;*ˆKŒkÁ.p;„p€÷ð„Œˆ#Wîõù†^‰Pus‰±ûy;„°Õç;¤P•õ"ã~�"!½zX½¡öàãÒ÷i]U ¥÷$±-2ixsØ%úݺªNDÖ‰„@´ŸôIF/D$$ìI(ýȤ±Vvoö‰¥ünñI�mTX¦EçD$$ì7ËHPa\àx—é.ãvÄ~E¶kä[á»À×ev iÃôFF§D¨P/£$„>­¸÷EÆ¥„¶ˆ‰�°VjBDNI=ç.ïí@VÀ‰C1"žN�‰ÎˆÐ�¹B,‘{!„OJî»ÈXP{À�YûönëmÍ+×—¼H,D«ô`3º$ÂjÃ!¡»A,±ûD¡Üéê�\žç‰]¤h¾7sµÃ¦E:VQ}¨&Ê>@D®=œ^]Fµ]Ä[Xâë|Ã,0x¬I�ãá‘Ñ>K|!B@ƒÁº¹±O½ ƒõ)ï61¬}•ø*´‰ñOg‘ÊöDÖrÇÚû¸Kl;”}#ÀÙŽ•ÂÍ)Þ©úqxOdj]õ<Œû!ÖÈ7þjÕ^­€�: )ú&â2cß¼�¬dÛˆ>ß(Ü':…jKíÕ=ý¤Ï®Öª™™3ƒ†½­´fÝE½ï’n‹¹ß«B8 !ÜSõò±­°O¬5¥‚UÁoUöF›üÛ¢á«}¶T*Ygˆ À©½(¬ˆÜÖê”ðÂ9¬‰ÈÙ¾:�úªÕÜ)Ò½®m†BÚ „pà*"¯ŠÈeó˜2¸­ûó³|�2tN„öG›]øªäÖ b ½ÕÀ­]‘Sº µkÄxÒ1h�ÝVôý;GªÉJÕ�"Õ Þϰ_¦ ÔnœÑÍFkøß Ã!„Dä"ð|‰ú¹M«»t®ž:%Blaè2wÐJ]¶·®`�A+À+"²YC·oãMgÉ:„p_‰]‘Ó]w¡v]#LÀÛEêFK¹E^� ýtýKLÛ'Žæ;téX0oCDFeÂÓ!;»D£¼Xð~[Œƒ’�ѵ�ðýÀE°FYv$žª³%=þ8„p3„p7„0ÑG¡në-â$ˆdTÙ ¨vªàw ¡Ìr^_�¡êd (-™LŽæÈ"„ðAáƒL‹i{CóÚÔ¼_LŸI`6+Û®…`Xjá 4B—5Â\€3! £ÌÂ…K.gȸKT]k´<Ë#X™¦ß¼]QWÀ&¨¦á› ³J^u˜:,s?Mµ-—ÜcØ[#¬”ª…éÿFD¨‹jžXN�æ êwçæ–Õ¨P4`&èC5µ œ¹ÖoYi-„ yDl”µJCÓ1ÕúĪ& ¼¤×ÐÓy,¥Btö£‘}ê½E_ `BΩ¯²pH]˜€‹7õ9ø–¡‰0CškgXh¤ÌƘn/d/Ï,ÐYË:ç÷{¨Z2Aîd~3#^7²ÝVµT¶aúÂ�5bC÷Û;RW@¦ãW-Ób"\o݈| ÏBu]ßAG`̽ŽâаÇYÆA¾Í´6¸P7¤q‘ñb(ÿ4¤p&SŸÜXWAŽ/#4Õ:€Éb(†ªÐIç˜["\ÕÖWª5?®Aú§‰ó'èk=E‘×�Ü_²‹oº‹×�~x†™C þu'ï7ÓÞ’ö¸>Ðw ŽD¨MñVQ¢¯‰È»-ü¦çÈç-äõ®ˆ¼æÓùÊtyø8¾�ßIEND®B`‚ukui-biometric-auth/images/FingerPrint/02.png0000664000175000017500000000612315167732630020026 0ustar fengfeng‰PNG  IHDRbb«¥ IDATxœí]A‹ÇþÞîh×ZvЂÄ:k$´ �Pˆ ؗܤÜB’Cî9عäìr–sÈY¹å¨| lò ä 0±A ,¼Á‹-»dÅlFžÍ¬_õÞΛRuuõÌtU+«Šîéîéê~_Õ«W¯^U ˜ù:€_I€»HÃ?üÀ €žlíþ“ôø…@Z–mOÒ²·]’´,[’4õ’¾p*ÛïŒå·nÿk¶cÙÚý“Àþ‰¹N÷àç‰rz(ÛÏ|FDÿÒg/ÁÌ÷|œxC?ÄŸ�)ºßóö/`š ŸK„’qö&U‘ ÂUêÒ‰·õ�ýÀf”ÛÇDôèK0ó}Éɇþ`‡ˆ>gfš¦ºß!a7!ÈOJ„ÖŸ [+ªH°©ªäW Z·þù“ÀùÐo{ì'®ømó'"ú1óLªÌo|b^²`À[’tÅÛKe�ùD]¨8f^Wªj„&%†ˆS“B5Ã'ÈO£€pGæœ&=þ]`û€—fÿÀ¯üYžõ§=aBÀ߬‰�– ë.ʾ¿]•ýÕQ«† ˜ðC‚·i)�,À´Šòkˆ¶–«²,9–[ TØ'fÿ¥!B÷‡Fèÿ‘ý¡Ù?–ëþà~ àCbæolxÀ?å%ü�CÃëýcmæ§X"Bä°w®ê?þµ)çbÿyÀ#;ÄÌ Dä[o�*ÿ^éI3_„SS)xID§m>Ï¢Ñ9"˜y®ÍécÒ^­ÎpÀ™Õª¿DôrqOºXtB51ó:€ I�…Þމè°å|’p&ÿD0ó2\©¿ àJàµJÔ8M)ÑæÞ€«U}8•¶¸|à91ETY"DílÂà«Å�&":n!ï‹pd¬#Lþ€=":YtÞ5Ï•—Ä LTÏ®´–P¢߆#F ÅΣ°ð‚yŽìVÓ œŠ؇# ˜e#Â>U¶` ®�d­g`A¦¼.‰zê˜y…™/È—™™;a5�g¨ü—ê.|ƒ’ŠÒ^­Á9[5|ä&â&&¶y+:YÈÖh>Û)¬ “öê¶ü|œs¨5[‡¸½µ´ÍE¹î†¤Ôü)Ñ)½õò%\_a„„à1üœÊÞž%ÿY‘¥�0n ÀUû`©²6à:€s[Q*Xf>ÐO)áD´ÏÌúÌ|9× Q®¡^Í£*ÝkFÐÆ*]!³€ˆN¬@™ù}f¾©SÏd»µÈ爡u"du9¤š¾�]‡)Y£8Äía—Úñkƒquçhþw®¡R?86�¯sÜÆ5‚ª–b‘áªâŠ›§uh�ˆŠ °èô(îÙ@RMÚÐÇ:Œ1ó¸SÈ¥š†p‚­œtn’{p#uuSº¢íˆÔÂ5¹W‘yqMPÌ|µLÙ©¹>:˜$ÐÚP|ên Нr)s×¶0=³³Îu~U¶Á•+ QcÄUœÖΙb¨‰"D˜ùq›˜x5£³xÌ71© Un�MÙÖ­¿‘2‘¹¬&;+tÓ/®¥68sÇÜc®æXÓ·ª6(E§7An«Éb§¿£¥¶b�”`”†µë!Ücï,rª&�:@ƒµ”ˆèĸË�à&ÉW©/µØM¸÷±„ðG�‚M �YQ|ÆP š,�Òdâ‰ü®\ߺ°c(n5¥ Q¨>Ùd.Þ™µ‰mÊ‚Ò㯠"“ð�"_i"L�àÖc—bèâ †ÈDþc£Èg™ru Û«fRvt†éÜÂäSµþž•´ rŽÝkDà3oÍ:Ifo¬ko 14ßÌy{.á–¡kt /PÑk÷–|PÀ™ÖYüTÅkqÊùóÜR¢¸­ƒp ÎÍ3UíÂ(Á#¤?‘¹›rß+®ˆy›ÔëŸÙˆ0½ëÐ;’k�@Kï5í‚ô†p½&!ûÁ|¤šñ“¾<çÚk»ò@BÏz׳>LíÜy½ì¤uŸävZ1à&¡$å+ÿ]ù"B¿1€Ó½�^LJé6×}ª¸ÇULCÜ×T*g2åDñƺüê2Bs­è-†¢¨s�´ŽÎa¼¨º¾RÒü¸÷¿7Â2„S[Ù¿9Ô9"L¤Ç¸Z@~ÖRRdÿÄ 1ó ¢ßäÊÔ‚§?¤V 0§HnÌç|?ÒäËLù:ù3çý¢Ê¼ãÞ Óª‡9ÕåÞH͈eÖϵâÀ™ü;@„]½²r�VãSjúÑÀ1±{%½«U(FDS«IÛ 5ƒ‡ˆGj‡LuÿBûEáµ Âó5îÊ=¬u”}…ã:tžiÄ·áJôͱª˜qü)�©�&‚§î­ô¬6¼§Ķ›«AŽ¡³Dx$$ycÜÛ�)Þ£î2?‚S! %ÁËÃÿˆHënîȳtö ï«À™KºÑ3Á™ÃW�ÁÍ] }ˆ‚�`…VW¨ÉßÉŸ'¸TêaÎ+Ø}D—™™—<”ãwË=Ò¹Å]Ù>\ð…üø¨Ì³œk¨Ì¿3_7ê郢�uŽÀ̹_׃÷ÌÁg'Þ`á�‚ÿÀÈûžÁ}ž ½WqxBmŠûU7½ÃÌŸÎpÃg~ÿ΀™¿™A^Ÿ2ó{Ÿÿ›ÝšÁ!ÜIEND®B`‚ukui-biometric-auth/images/FingerPrint/01.png0000664000175000017500000000537215167732630020032 0ustar fengfeng‰PNG  IHDRbb«¥ ÁIDATxœí]ñjÇþ&66668¸¸8DpHié}÷MÂï Ú7È#äüy„ô…¡!†››:È(ÈÈÌï�™‘Vç½½½“n÷\õ![:íîÍ·;;;3»8`æ§Ìü 3¿ÕW,ޱ¤`æãr2¹þÂÌOË |U£À"þI|ÿ�3šCn¯Š…½v¾|ËÌ/™ù(Ó½ýkÁÌG*Û·Ž¼_»_^fnëÒ@ 1¹:niõ|.0ó›‰ì÷cî†-˜ùG•ý'bf"¢Ü [F˜üWs7$̼`%òò¯Dt×f{�ÎÁÌk6ôlX°Þ ø `@D_×ÒÅ¢ª‰™·ìè«¶ÐkâÀ ]µ\O&òÏA3¯@zý.€ÇžKFn !½yà.¦G;e2ªz•¶é¹|à3„˜,ª, ªvö ÕâÀ^DtÓBÝ2¶à'ÿÀ9Ý.ºîŠv¥%Bñ SÕ3†ôö«jBÕá7b¬SŒœ´ÑíHn5ÝBTÄÀ„€l–� ûFUÙ€}H'I:"&°5v¢º¶U=u̼ÆÌ»êefæNXMË “ÿ£Ü ù‚GN\gnÇ2ãÀõƒQGjålBÖe‹¾;ÈÚcqsä™x ³D¨5³ ±h6ÐÌÂ3÷Æ5€ë.ûŸ:E3oÑWµ¬žav5<ééúîÃ:Ä7e ·"y�ro¸èj6îCÖÑ�ÆGn!kŽa‡�ºY.©#È*º3„d%Bõþ·�á/"ú¢+ñÛE©“÷JgÉéq݇�`HâëѹgO_FÈÀß9ÝäɉPA<Ãt œ¥ôï8íp CüL_R¶Ã�”�ãÎS¶¡UYO s ÖIj +e b B‚õ¾±ªÀ‰1„b .�‰~«ê˜yB sÇû”d$!¢@ÂBBð& ëˆ^èÚ Œ ½üªŠøÂˆ­ÕYæEŠ`�KÂÀÇ *Œo1U†f#v!X¼»¸ øš k˜dd¤BI ¢×>Á´÷�¡+bÌÊdæm©nTn™¼.cHçiÕ˜h�½™�9$¢÷�ë0ÔÀÅ¢mû³õLëºG²^­Ïma£á%7¡7Û‡ôØD(mµÉ©s&…ÖûÑ7:œÎ´‚–UT Õ„Ð 0ó ˆ…“ÔdÔ¹«±¥=>æ�ì¾&�ïrxFSöø*d!B€Xá3óO%_ œ¿-ªV:Nª_…ä)—Î$f®\OT çûÛI·¬LÕ1œ¹c�ˆ>ÎѦFHíâp-‘¹mtÕóÀ4a™}ED9u¾Ú„8[5ŠHMÄ!¦¶y+:Yɶl>wQX™<¦óÕ ý÷}ÊPk²,u{[oõš‹zÝ3}ŦàÏ€ˆîˆè‹ª—? k…"’ÇTðç•ÝoRS$™#· ÃÞÛ+•¬Èpn+ÊËÌWz1=œˆ.˜y@�™wS�R�ój^—é^'‚6Pê i"ºuÊÌ?1ó¡YLœéûþ"ÛBëDh<Úæ…¿—ö!#ô´†Y»ÂÌ[ú*jzÒ=èˆXO•†™B5Y¯º(S jýôŒBªÀIÞÁ4[Ãý¾Ô]ႈÞ1ó€oêç ÀsÈ(m]=µJ„ ØÜÐ!sÐz�7ZW’dàÃ:€ï˜ù$B·ŸCüM»ðšˆn”ØMfÞn;„Úöˆ0_–©íåæy½—úéÄV1›06‚³i±àÌë3ó8$LRØhȾu7ÙO¹Ô½kû˜ÝÙYå:?ÐwïÉ•Qc„Uœ�ÎF9T‹D"œýq{˜z5ƒ»xœßîa:ÊÜ {ú^uþFL<" RYMî®ÐÌÞ¸õZïΧŒ5ÈÈqMß²Ñ`DdÝ:\©­&ˆþöÚ’R¼YNÔnþ{g‘R5Ù®Ðjœ¥DD·Ž»ü²I¾L}YÔn à4¢ìMá:ëM‘}ÇP ê�Rgã‰üƒ^ߺ°CÈn5Å R¨–>Yg/ÞÄZ ä6%AîxÄ=øRd"~cYäku„Y ¸õÜ¥:E„:½)2�߸YäM¶\]êû�³)9:C„®žcú¨‚Ê€ÁJ: $9‡Ê:…&‘xÎÌûM7É̃쓵çì�KD¦æ;{Þ>kº¥ïÛ ”¬Ú G>.!¦u?U¶ÉZ�rÅ}n1YÜ®ƒpâæ™ªîÁ(Þ£¤н{Zîc�Õ¼�ZõσdD8«kß;¢G�Âzï󂮆á>Ñ”}o=Ú ®œøIOÛ¹ù`OˆXY� +ë«ØÅ]a•uî“þÎÝV È&”¨zõ·kÿ&"ìyˆî­ucÚKûˆ<÷©¤ŒLCäi*¥;™R"ûd]¾ŒÐ\çC1T¹NZGg‰p¼¨v¾RÔþ¸åoCöO¸„ !j+ù3‡:G„“鱃ˆ®PŸk)’?â†XŸQJDÿKU© ž}“Y)À4N=™ÏÙŽb¦É‰êù3§}¢Ê¼qŠB�iåaNs¹×R3j™õR�80‘ˆpO¯,=§Õñ)Õ}hàBìyNïj²QŽÕds†™ÁC„3mAfº¡“ý¢ð ˆ(ø€j/µ ×:J~Âq:O„Nâ}H�¾¦9NsFFgFF§‰àÙƒ{K=«5Ë,&±�¦š�Cè,¢¼±5Ê.f„d_Qw™ˆï!*d¡$ê(>D¤u7w -�}Âû:0qI·":gækˆ9ü ÜÜ•`EÖFd„&+´zª@Eý"žb;Wc–,ÑefæG~ÓÏÎפ¥ÅÏúþÛ#¿ë?¿æiËRÃdþ;˜ù©£ž^fmÖ�™_:rj¾r><ž|ñíøÇ޼_/xÍÍqœé¾²£ Ôºx]Vè3¿iPà?‰ï¿3`æO äõ†™�Ürþ¦)úô¶Æ†IEND®B`‚ukui-biometric-auth/images/FingerPrint/13.png0000664000175000017500000000704715167732630020036 0ustar fengfeng‰PNG  IHDRbb«¥ îIDATxœí�ÏoWÇ?×ïÅNœÄ 4 MI•”ÒV…B"U¥BØ,ù!¥X° °dv¬�ùÒ[CŤP �ºÁ¦,�ø•T Z§?HÔ6©]œ¶sXÜsïÎ6Ü×ûJˆaÖû¸ûÖÏ7¹°-{çãN5ݱû "rJe¿DDB¡éŽÝ�0ù·›îHU¨Å®ØüRá£:û3hŒóëÓÀœ®OêÒëu–€+À%`)„ðÚ@:Y,l7܇YM¡-^Õ‰¡ìÐ:ÕHŒ‘CDmÿŽ.Y\!ÑäKº½ZE£Ýµ!ZÕÑ¥�Îi¾¼H´–F\Ù¶ Ó"$¡œ‘•M]”XÝ×RHJÌPÎJñ�Ä‚ ;Ôˆmù‹IJ{ð~#nB¢;¼�QŠåº¡¤C'â�>ô²ÄA¯Cuß³ ´_g�’ Õ*†N„ÞôLæ_ÝæÐ­Óäÿ  k&ÿ‰¦;òhjØp?îg\VÇÆi6sš¤ÚÎÃ*Iíq)„ðÖpz·‹¡ÙŒ½¶Í«;ª`YSÔ³£’¥a¤,BDN…^ÓÌêW¤«áK™%'u±±ªì áO‰UôÏÖéÝ—ǯ˜æêöE=¶£w%’L†¸˜c)#3ÞÔ8$V·‹!�Ñc§éN$xå!Ò9kdA†PìIŒ=óBwjuc ÄbFCŸ1’CÈŠY㮇tüÍw?«ö>��ä%¾èöÐ3¬a¾ƒ˜%fB‡‰ùþ\Õ7f’¼c˜£øÝ‚DZPZªZKˆÈ9â» ôÜÓãöºµ+4(› ¸XEã$]Gôƒe‰Aºk ÈXìJ•s…Ú-"c KÀ eš¦ÿcà…Ì¡%ÒoìÊ0G~¾¼Bx¹äþ¾†éÉrGªaf ‹Úzí_‘˜I�éÇgëù +¹X¦í’N(Vdœ§ŸêØ™_ìÒn!#¤�çö’Ÿ¶Î‘¬í­\îG…³†Â‡Ð‡½àöÜúuHÒ“®—‹¬Ã)ÓPãÅÀ¡d”>€jÝÐSF‰ IJ#£HYº>î€Ä<¾³%�odôÕ_5O)|§¾ä¶¯�Ô¿ï¡/§´/ã�õ +ÕzÎN°(=};.ìü鯒ÎDúvêçg%•ÏKqñ· ]ßjO…¤sóZ|²’}FÒãG"&�IŒW+ºŒä´Ÿ¾!éaïB�¨’E©`祇Éc‡UDº c Iþ2¦ÔìY…àïBz‹f¹»ë¥‘{°Â@˜q µ¦³¦ñEîQ’?ð\®³C…$=Yêww¢…fu©s|ÜdFÎ?¾ªª�’L¾ �DJ†+r®eù‚v}¨›l’þîBw#É _™P¥:ºj±’*R”��÷+T©ð7ÜN ¹dI;LãmÂØ¬o/�ƒy]…çÈ-g:Û­ÿc'ÀB¡HÌùEʹˆTûÓw½®µŠ#.·ª"ãü­IÜRéC8aô\ͪäY‘ir·—QV3”Å/‹Eµ Ö9-N×K]ÚÙD€Ô4J‰»Ñ‘¶ˆì‘IÙ+"ût9¼ ¼*"ÇDdÚàÀ[Àœˆ|AÏÝ£×j‰HÈܳl2‚õ®¤Mߨ“ˆ\—´»ªÞ/"�ÀÖ39ûŸNŸ¾™i7¼¢×ý^Þ5DäpGÛ<¦$åÉ£ Y}£N"lð’ý ZÞV �VaX»àQP¶ä‘amÞ^Òs?M'¿Öc_w×9è®1C2 ᔑڷIi- vðG÷½ Î/Ìéú™Zº´u=‘¹ÿAý­E|OòðgàGÀ5ý-»Lé¹{�CÀ=w½ÿkÀqà)Ý`K×÷tÛßKßt۱瑉‚¿ÇÀP ÿØOš[?êÚFÀsÀW�_RNĤžï3+^¾¤Ëoé$á mûÑJ²$ضa¿ˆlÀÖ I(jÊ{H ‘„6�$´�oh›¿¹vFÆO€ï…m$1Et5Y"ÞÑí“DA fŸÐãëz�<63ϲi‹ˆl!OÖŽ0"¶ÞãO“�ck#Ãò÷?’ÛȰêø2ikñD˜Fo‘OÄ¿uû4ð2iîûôx‹(ä­Ì²AÚ"¦IˆØÐõGˆ'­'ôED¶ý„n{‹ð–qœD�—H[Äúð!QÈ�N2f´ÍuÒDØzZ×-×e$lÏêqsMf~½áy¿îoè3n¸6­~,dGDh h}s~Û»,Ûÿ¡^n‰è�X‹¥Šÿr¿{Ìõ×õ )B₼ÆÏ��`®gR�Oê}¼ð� OÄ>÷,º½I’ˆ!DB*H g"2V`DLºúí�ï²&�/Ïö®úðsb±´�´Ûz^»MÔôl6ed|\¯u“(äí®ºåSúÛ*é¬ÈÖ¦íF„·¯ù†):5?/›Kͺ‘Q‰G‚w1Y²û¯ä\j�HÀ?õ{I[ÔÃ$ÖòK±ØáÉø¤¶»MÚ"|ŒxL[!ÉŠ|ðD˜Ûɺš<"¬Nò÷ÛÙØ ""enª+.0›0¼«ÉÛ7B<Þ~G$`S(k5û�¯é±5àuòkÐÃzí›tj!ZÌa"ù«$ÁØÜŽÝßä`nÇ\Í„n{Ofö;Ä•Y,&µIÈÈ-«X„šhçìg 1á~‹t0Ÿ,Øo‹»#À]àO$.Ë_ß+Ã#Ú¿l ¶Õ,æ}Ò…˜ÏvìùÛ¤µ½Ã½(Œ8/h/pëŸßo‘¤Ë¤‡a¶QJ„ZCÖæí·2û>kʘ%ì9b\˜"!á#Ý/ ú6 aݵ1™ù% {…ÄÿûlÇk{3×Àmû}ržÀóÈþ6�¢3­ *ðlŠiƒt{u9@Ôн9ë)ÝžÒÅÊö÷d„j÷úѽLi?¶ˆˆ{�,ÉF´iæ=ÍÍó×yn´ӴÙHú�´Õlcƒ˜Å ðý펮oéö·½®Û·‰éù-ýͶoºóïØ}Ì"²#‘& qê–1uFèA¢‹˜r¿Û=ÖI|©·24M!,M\#q!nÝÒvÿ%è³”Õ”ˆ»J„sŸ]Ý%Æ« âØ•‘dÇlm¤m 7#pksÛ�oõŒ”ž¾ "Ïvi²FLcW˲ Bœ¤&¸B¸‘Ó¶<©m¯wûÓ^}ò°Bx³¤Ý³!„¿–]¯ óKÈkDÍ_n…îV9)„pWÉ€˜ý\ !Ü*hnVº ¼[áÚ7uNÂÁ.íj#`ûuß`‘}@¥ámK Y¾í$ð9m_»°Ë0rßÏCE¡>®›WzýÜ.ÖD¤5ˆ÷ ;ÅÈ}\QgY´º·L�sŒX¼Mö"Ì ÁU¿Ä_ FŠ žOOV%CÝ‹Õ —wpÛëº>®÷o#C„ˆ%f0Óä“ä�cYRx·(pÁ>6ð”ΑêÉ"�ƃµ×GH\Ãu¢P«槉ĽBÈÍ’T¨Oëî•ÂÍ‚6�“Ξ®Së¡|¡¦±`­S%��ö͹õAι-â„€ib P–ªZÕ± ê€’þ¦ˆÆ÷‰¤ †ôÑ�ÈÅœ®—&H>úñƒfúr_Ãd~ÉJd·|Hp É7¥D죓’þ8î‚ìÖ¯�Tñœ¼ç³ ü÷ðzÅxó®Hç¿Íéç‹.:+�ßÔ®‚ñýæ]Ÿ�ôÿÕ«Š ’ù,÷ÿ_˜â™5 óÄIEND®B`‚ukui-biometric-auth/images/FingerPrint/17.png0000664000175000017500000000645215167732630020041 0ustar fengfeng‰PNG  IHDRbb«¥ ñIDATxœí�Kl]GÇÇvÇIåRªŠB ¦¼Q! $’ï‚×R 6 „‹ ºa¸ i%$,¨€.ˆ"_­„J¢‚( qÝR(�ì–’·ó±˜o|¾3žóº¾çž{mÿ¥ÑŒÏ=�9߾ǼŽÁ@DŽˆÈ)YÑTKìRˆÈR 9y¹ž‘#y7\¬qÃkC~ÿ‘�ˆô¶!·Åðf§Í�+"rBDZz· YPÙ®yŸ¶?zœh¹®»JˆÇ‚µq»ÖηYÞ”½±qGÛ®ØnƒˆUÙ÷€$I’¶+¶áå?ÕvEªB5öÖŠ§ŸK’äù&ë3hŒââëc@GóyMuïÐV�s@7I’ó©dðn»å:,híýU“X’Š}¥Zñ"2‡kí'5…X%mÉç´¼^¥E›{ƒÓªΤ‹œÞÄiK+¦lS †©â†PN‹ÈZ¤¥®ˆëÝ7Ò‘¡œ�ü!‰%Évh›ò*ˆžyñ5~+fBœ9\E¯©†PP�¡1§/Ý7è5×ô3«@ëuÂ4’¡jÅЉЇoCý«@œÙºvzùïuèZ†—ÿDÛكö\�ÝŒU`}lÌ‘F3ÇH{Û1¬“ö=Î%IòÔpj·ƒ¡ÑŒŸ¶�õ;ª §!ê‰Q‰Òò0R!"G“$9¯‘Õ#d{Ãç‚ü&?VžÁõ¢¿3°Jï$˜8~Í·\-ŸÕßúš+‘t1ÄÙˆ¦ŒÌxSë×»] „t\;:Hs"ñá•=Bd몑%BgOœïY YéWëÆ*ˆ•@C_1!dÍk㎇lø[,¿ªñ:‘t_´<ôk˜s ¸HèV\¼ß©:c&éC‡ü¹‹.®£Ô­Ú—‘S¸¹ ôÚcã6ÝZ uÊÞœ­Òâ$Û�Øzâœt©4v­Ê5ƒBãhB¸§¨¥éËßÜüÔ%;cW„ñ^xx0I’<ßöajiîÈB[˜×„• çÚÖ¿&.’:¾›­×/Zr¶¨µK6 X“q^~ª/ãÕülÉyK��ÛK.Ùñ#‘ ‹ÇÄù«5M#¹ìgÛ�ì°w®@T€‰¢T°‹Rcñ˜¸a‘’èXBÒ�1…joÈÊíöùü#RÏ_xÍÝY“FæÅra` g}‹Ï3�’nðì5Y�¡BÒÝ“…v·ŸV¨þ`ASeŸcýÆ ë3Ò0ö9w¨j ”tÁð²l] R0\¹—æˆ ÚÔi f²Hvw®¹‘tЯH(+R¥­XI)pʦ�÷ªTØÃm%KRßá[¼_0¶`Ï—­ƒy¥Â3äæ�3�(«ÿXÀ0W(âb~‘bG."Õ¶˜û•öU qÑúi#ço�Hj– _£voVµ ¦E¾%—MFù>C‘ÿò¾¨ÑAÁ&—åw4ï–œçä-£ŒB èÝ� ]R¹ tJèŸY´¡«y§Nýê¢I"ª ØŸ·Zóþó¤ë\ÃùmpóÎßµêá·#ÌœS…¬Ñ…q„eã;•íäÚÅ<Ó"æ;Ûy¾1±�y Ã4­ös±yésðMçÖ�ù~ï¡÷ñs�~ïQ�oÝ*ZàUA@âf§*ºæ>±ç{ÿQË?5�¶÷Ðy!w#¿}v÷÷žÏùÝïŸh}ëZÛDœÔü‘Èo÷kÞ-¸Þ;Ф›FòPeh¤(<Þ�,ü6ݢɡÌêë ÷_*9•t8¼h:4wˆ$ö.euÚZ _-dëæ�“%çÏQÜ�TÎT­Ç®†Î ÔÚÙi´!:'é¬_áŠIç#N—<¯q�h’î�ëæ«Ê>·Sæš¼å0ÞäNqJÅ‘ÕC„¤Ë^eëê‹5)عcîqD²;‹òøOÖ‰” *î "¤+Rá«1J@H^ þÜÒ ÿÝJÄŠ¸ùéÚßõ3-|YŠ7!úíb•W ޵�‡ ©ñ�©±ÕJÒU{D ÒÇ*rÉ.ŽÏ]£MAíüœ¸/pNŠÈ”ˆì‘i™‘šfMú² ó¼9æÏ›Ñk÷é½&E$1Ï+ô;ÃBë_0‘ Ü(ðnlèkúÓ‡�ôxb’1öu? üJËïžñ·nš²˜clhþ à“¸Žä½I’´²/b¨DhKœÄ sJóIMŸÐSŸ>M‘%ãnà>àƒzÉ�€¯ÿ#Õ”$'}xð0pšT úAàûZþ"ð;R6HÉø&ð.sýÃÀO�Ÿèy7p¤Øg �¡æfŠTè±üCÀG�÷›K¿<ªçøV#ãNÞ‹â¾Ï?ÚVCÓQà!=v/p�”¯þï�àÌÔ›ƒWzøŒ>k¸Î€I("2ìà Òçž�—àÔÿ8[þ sé£8a]!|è½zÀ€K¾ ¶:&=Ü<ŽóA/’%À—ohyç¯Þaêy˜T3lºž$ÉF}ie1" >ßü«ä² ÀÏ�_ÿ!õ>÷dx&€;€ÏG€§p&ì’y�<"öã´m^ûðk­CH‚M×�Y}îŸÿN’äFÉ;çb[DäàËá<À�¿ç�Ç€§I5f"(ÇÈxnè{ø+ðmàrðÉ­cþ8YSø3œ6zB6}�ɯGrO‚=v�mhH_D0M>¶š¬)â>$FÆAœm§>þ—ÀoLýÃwÃÔ0d½ øðRsÍ€'+ôhË7yXΤ:ÑVm"-ðDL“ Û–c¤Lšc¡/±dÌâlõ»�¸8ÿÀ³dû1", a„äÍЛ€ãÀmæÚ§qQÛ8 ޵ü0ùß½F\3ǯUÕŽZD( Ó¤ÂöDø”Gˆ%nЏ¦øòk�·ã5£�~ 8«/—×Áó¨B‚õoÞC6xxgúþH…–OœˆÍãU|Ç”.N’äSE'$XÁÇH±&+¯ìÏ}¥¦×¯&]½wó?‰óÓ8b¬/2ME$ØüIœÀ_¼)ÝŽ‹¬üó&I�õ[Eý+;òÈØ”¿y,šc6$„XbÇ´æ[yÏQ<üg&6Èú‘ \t.’™Ó{ưü[ÓUŠ�°mí‡pQÙãä›�ë¦Ë;'j¦¼üKÇl͇u¸áße…x g .âBÞ+æ~3澇pfëe8ŸQ†Ûõüë8RÿŒÓ,/Üiͧ4÷-ÿ2ÎGÌèñ°•™sa«FÞÔgˆˆH^'°T#D$Ô€²¿c&ªŠíËI3¸a�;ôï¸á�˸1)+¥là:�·àDÏÿ=Žð"'kí±–~-ò{ìïP+2&jSþfRdš­6p g f4ùòtPžQ!Ùc!QûrŽå…½þïÃ*Ô›ú2Ï« cöÙ·DH[ã-¸8Q2V‰wÊòœðÕˆp¯šß|òǯDò+úl_¶}–«!ÍËO+ž€C8s0É÷ky„¨ý† "áOiÒ<ߛϛä;HÈš «!±t�­TØWí¿ö5S¾lˆðåKFè^s/™ò‹q/@ÖG\�-ñy^”?ä� ååa9L³À«´ü,Îñ†¯ÛšîÔ{ Î/=GVƒ|›¿°yXŽ¥� ¼·ó%Õ¢¦aBD¯Ç5’Õ$I.ðÞÓ¸0yV­ÿL’äò žÑG�²>b„ˆ¸gÊJBðŒ;q“E—ôyC'¤røÚö4E‚Þû‚ˆ¬ã"±Û�Ù6µØ[×£‹ ªôKšz¾“ÿÞr’ö æIŒÑØˆŽæÝ ÒmMƒØ`¾‡zð2?—YvØö"«ÝI¿)%â×Köã¸K²S¿<�­Û Ãì÷ðê¢t üN…lý·9uß©$n¿@øMí*ßoÞm’ÝõTË|Çêÿœ-z–Ò H¿IEND®B`‚ukui-biometric-auth/images/FingerPrint/11.png0000664000175000017500000000717215167732630020033 0ustar fengfeng‰PNG  IHDRbb«¥AIDATxœí�[Œ]eÇßÜ;th�ZRÒÒj±HÀ´X$ñ–ŽˆÁKbQ¼D­˜c,‰ñÁ§ñ�&ÅŸ|‘DÅTbÄDLfˆ· �¶Dš� i ´NaÚ)3s¦Ë‡µÖìïìÙçœ}fÎÙûL‡²³/gïïûöúëº÷9"ˆÈv9("c¶äÅ(k"2Ú„œ\®Ed{­Gšh0�©‚ï¿c "+�ÛHº±Cчc"r@Dö•to—-DdŸÉv,’÷¡øCÇ�’Ǻf`„8öÅ6nÍÚù² "‡eÙ¸Ýel­ADv›ì'‚ˆ@!”=°µ—OÙÉ ÓØ�9O?Bx½�ãi5:ŽÑøz0lë¶4ÛÀ80 ÆCÇZ2ÈvÀÝvÉcØg!´û«vbT:(:ôA•â#Dd:Û¿jK“$3ù¨mŸË3££¶Aµj5i{2NDµ¥S¶¨Ej„h å�ˆLeÌÔ1Ñì¾-‰¤h„r@j—$F¥VÙ¡�X”QD˜ &¢Ÿ2á—b&DÍááÔ¤˜h×D¨3ŽÂ‰Ø`7=!ZôÚÐî>óÀÆu š$…jEáDX§ûËPÿ<5›…k§Ëÿ­„®d¸ü»ÊÈ[Pta¡aÉãX˘έsdÑÌ’l; çHr�£!„‹Ýe ‹fü±mVÞ‘¢è”(­:J#Ddwá˜EV¿£:>šZ²°Ã¯U¥‹„?G³è‡Z6èË Q?å3×¶�ØgËzV"ÉËG24¥cêM¥C4»K i¿}¶»•æD²Ë+o"Kß•’=Qß3’"dl¹Z·ja‚K ¡ð7F2™rm¼ì!K #�¯jû˜¶Kò_l»ð«ÈgûÐHh#ïç}b&É3†aj?[ˆ1Ž&Jãys 9ˆ>›À®Ý³Ú·6„9e7GòÌ8©Î#V‚ Q'ÝФ4v*Ï5­BÛ5"¥ ãÀÝõfšÝü÷€»S�SýÄ®†ÉÎÂÇ�C�Öé?ÎašÒÜŽ…Í0ׄ±çƳJ4’Ú¿›m×�¦´äH½Ù.ÕÅ”¬æ×Oíf\Í�48o4%¤–Çö’¶ŽÔ"ÙÎ÷Dpb%“¡TDÚPó&ìfG7{°€qm�ê—®'jiG4™ õ-‡‘Q÷lÖ2е&KÃ{¸, Ç—¢ö�4ãK©¾ºàóÆé"5Ÿ©�GÛ“$¹ÃMŒe·�euGFÍ"r‚¹ò »f9“&œ~ä;/ÿîV ¤:©kD_lè‘é‘>‘u¶ ŠÈ]¶Ü'"ˆÈ5HyHDn°¶ºE$ÓDck{Ð�F¡¦I4—&J”D¤ }vÞtGÛ]6>_‡h¿ÞدÞ|øxtü%à›À_l}ɶ/Û€§íü=E>j-²Ö4‚fÌþN"|' ÙúÛÀy–’Õ„ÔÂ%à:àà3ÀVàƒÀËd“àË×�Ow !„¶¿÷UD‰£¸ø—ú.ð3T�=T“q?ð-à9T€±fd-'åRÜu´lö�RŸßÿ ðàÀÃv¼‚’÷Ñ2´…37=¶t�¡³ñ�À}Ññ˜Œë�_[û� ,5SµˆðíxæJÆâ$üx ø1JzLB¸ øª=·Û±…h=O‹IiéUD¤èE…ìë/¡$¼üXoÇÓd|²s@m½› Zd\¼ÝοLÄÃ!›Þ^àð9ªIXþü%á˨†Ì“�Q*"RæC ËÙ"ZBDD€¯c2¾c§= ¼Ž ÏIðõ­À{€W€¿¡„ÄÎÛ Y�ÎÖÛ€M@úÑêkÀOPÇ\‹> Ü | ­òþ‰„_FQ"¾ü�ˆ[æmÝRYžWHD âcïC�$Ào�Aá;Y=À'íœGHˆŠ#©w¡B»±Á�Þ<üx’l|öÿÞÚüJ¾à„ü8e}ø3‰Yš·ñÏGǺW¢!Ë""ò}Ô&¢ø¬]òzóë¢s|>bç=K¢ NÆ&4ì\ü8‰Úõ)à40k×w Nö+¨ÐŸ%›7CÏ7›�iR>ø%½Ý�Fy•èþæm»Bl8!ó(!¹£­¦‰Hi�Ñ 0Þþ°]ö$ ® ¾½×Î9fû~½“1o×ü”jÑôGÃû+JÎ=ÀPsxš¥RÅÖ§Q-Ûƒæñ _@‰øªÍ.üyá;é<¨[DæòjGSD }$Âr"|‰I¸�Ýçí&¢Ïc2o¶æ'I¹›,'ãG¶íÚâDôÛþ\4ÌÓ¨¹Mèa) n†ÎÛ5ï@MQÚ\°qínŽG㋵ÀÇÔMu€ŒŒ†¾#7)bÁg‘Ò‡:TPó0@mSv½�w�uiÿ›©xÖõwÙµ�›@@MÐITÈ[­ý3T“àkÿU�m$3Þ5Âgþó(·/²tæ7 ­‘‘‹ˆˆ„XˆiÒûï´Ë_Bgn–Öô¢Ù/¨­Oû�îÔ:&ã*TCz�]hÌI¤t¸Õ¸§ÉÎ\`W[ß±Í÷~NÚ9;I40«Ìo§}ƒˆˆÔ3S ‰ˆ³ #vÊYûNÈzkâ¸Ý@–Öô’Øÿ9"Ò=MF7:ÃO yÄUhh‡¬¯¡DlCguœÌ[ÿ¬ïkQ­�MM—m¿açl¶kê%ÁéÜÅÍa ™I`�ˆmvOÆ~šâ-výÕ¥5ÈÑŸj㋨Iù7I¸˜&£?ºöJªó7EƒÀ5¨©râ™÷Ÿ65 æ4ŒíµíXбÀ}|ñ¾Ošk»y"LÒö0k¿;µ·û:*p?/öÕÑy±¹óÞ„ÚùÓ,Õ÷PM„“àÎx#:ãã}’™•]6j+«Lâp!g <‹€ô±.UŠ¥am,æbõ÷í>Te¯°u¿­¢ýþÔv?Õ3ý½$³=e¹£~u†q‰äZ¬»Ö„G*Nº÷s¥�1¤�Ìø­(é ©Å'ÌZ:÷ly5•s$Ah©f.Z.ÚzxÓÖmûMÛŽ—7� "2gýÌÙ8æ} ñLv�uGö™ÚŸ±ŸŽ¤œÈÇ©®'e-³¨ñ¤,P=_µwQmü¼…h?6)q5Ö¯ É*ѵ¯™°ûI4ÅÛð±³ãQÛ>†®h;Dãñþãqc}‡è\ÊûJ¯ˆôï¶ÝgBsYŸ…žªÓÆ.4rz>„p>ãóõhÂ6B8žñù4j;B8U§Ÿ½�ƲR”ùõÞ¶>“`²õtƒ6<âZqõ³l”B„ÍÄ!TM³f¢‡¾�ˆè!\lÝèÊA¡?œe¦â4˜Lkƒþ%Ä5óýïBˆ}mf# ³( Kì:JTP©7ÓEÄÍÒl­sHLÜLs#.m#Â\ ”€ÌËL¸[l÷Õ] Ú:í_b¸f52q¥£(Ó4ƒ ö\­z‹™¤6¦ÙzQŒ¡®1-´¶:þ›?m#¢™PÏÂÕ�¨à*4ø"Š‘æf®–qm8›we¢Pg�ÙŒš#¯ÿÔò1üñët–‰ˆªPßĹvv×9§”B„ 괢酻”„º¡¨çÚðr�Ó6Ûº¦)Œú„Äß”†¢¢¦n4ùBMF|ã>k_­'43_[¨}kiƒÑÈÏt ŠŽšbL£ö»î¬MùÇda‰í7v¡÷••±w,Š4MÓ¨)˜.æRaÎÈuÌ'ë˜//@VЇF�Ú>/úÕ‹¡çµ­Æ´ØG»;h,¿ÈõF„'zyÊy‹‹E ô¨)r u§mN6ñ‚×b´$"Ý­xur¹è¸W´/’4NZq#Ð׌0Sçý%þ¶ £ˆ°¢à.`W^2̼lFý ËèöŒ­·Zÿ¥ cˆ°üàF4:J¿XPëš8J:Q+ˆœ}N ADp£ˆliV#[�Ò�µ9×ëHLÃT¨yóM(q¯„2£$êM¶›™µÛ9;©ŽžÎ ¡u!uªÒœµå6Qm›3óƒŒk½@8ˆ–9ê…ªëH²÷L�1Ò�‹ˆgûƒ6¶MÞæÊúW‚ˆˆ²ë�¶Ä/çÖƒÏÞøËfPán‘šQ•M‚³Ñó“!ç`»Ÿ¶Í4åȬgÑÌúlÞä.•eÏÇsš0÷%ž�ŸÌÛ¯]Ûw9QAßí™FmoS7f³tªÅÓÀ ÍÆý"²}OÊñ Zã*½Rº³n›‘[IŠ}u_}ÉÑÞz”ÐØ46*�´KDTEÝŒ=µCµ %Â2 ÛF5!3Ø+ýEgÙGDô¦ÇF’`â$ Êä+è/Ž”õ^nh ‚Ø”†î-ªÓ–G ¢Ï =J�ä9Eng¾Âq¤ß4y¦ ~Uþ"Åþ£ÊJŸS¤2ù7Œ²à%÷¦ÌŒEfCyò™V`Qþ@„?§¸ˆ&gõÊ›Yšƒ4B%öT™ÕÕZ(�ˆfEMî3< ž¡þ›€ž�¹ío©³oV©PÓ  µGG³Às�¤O„9ñèŒ>BXN‰ÛÛòŸ“Ñ1šÑÑD ^Þ®YYm²ÍôKl'ŠrÈõбD¤HÈU�m¢íô!¥gÔ�LÄ-¨ i) ©>ü›B޶—¹ëŒ¥cÿá½KÒmAᔈœCÃáMPæn1”:ˆa/+¬k|fÛúWùK‚Õù#ä«¢?¿*"ú…öq;>\Þ�Ö,†m=ÞEòçz÷—3–5 —ùQÿ‘tÇÚþO¶!úG‡Ží~p$:8*úçß—lâ�FòIŸÿ¹E³-é¾J‡,ýÛœfp¨V£û¤ú?Ùòb*³Á5©þ_½¼8,©ÿ-ú?Í{¾({èÂ�IEND®B`‚ukui-biometric-auth/images/FingerPrint/15.png0000664000175000017500000000670215167732630020035 0ustar fengfeng‰PNG  IHDRbb«¥ ‰IDATxœí�]ˆ]WÇ{f2“¯6CÓF«ÕŒ´(­¡‰© 8WAQÁ!±¯ ñQðaê›oé‹ *Lë‹O’,Ì”*¢™Ú€"�3¥ik íŒMš4¹3³|Øk嬳çœ{Ï�ûqî�ä›}æžsöÙ{ý÷úØç 8ˆÈQ9+"Kšªb‘Û"²Ø…œL®gEähY� ]˜bmÈíˆÈJr[H ;çN.‰Èi™¯©m»"2¯²]rò>çON×\×ÛJˆaÞÛ¸ÛÖÎ×9KöÎÆ¯»b·Dä¸Ê~%ˆˆ„BÝ»aòŸª»"U¡;[ñòåÂÿYŸ~cäˆ�_ŸšÏiê¶€&° ,Í‹}©ä `n»æ:Ìkmþj�X”Š­Rµø9Dìíg4¥X%ëÉËz¼^¥G»²!jUƒhÒN\Þž"jK-¦ì– S#$N¡œ‘µ‚žº$qt?��¤Äå´”OI,JÙ´ÃqKþÃ"B±â¾¦Â¯ÅLH4‡ç“N±2¨ŽÐ¦C'â�6zEâ¤×¡A?³ ´^§]'ªV �}èÉ:Ô¿ $šÍ¡k§Éÿ΀®f˜ü'ê®ÈDL ¡aÍõ¸�± ¬��9ÒhæÙh»ëdc�åÂ+éÝ.†F3¶l[4 QO�J”V†‘Ò9BxQ#«gÉ�†—“T„9M6W•N>ME?Ó·Jï&¸8~Íz®_Ðs;Z+‘l3Ä…M™ù¦Ú!qt»”餞;ÞOs"ÅÓ+w‘í»Feƒ=‰¾g!!di§Z7¶PA,%BúŽ‘BÖLw=dûÄßBç»^§£’-â‹=ÂæÄ<1š%Æû�ª+f’­14(_[ðhJͪc 9K\›@ï=1nË­¡NÙLÀ…*=Nòãˆ^°"ÑIwô‰Æ®U¹§_¸F$šÐNµëiÚø'�SÉ©&ù»vhP< oO…žkó|?†éJsGÚÃL–*\ë{ÿšÄHêd/6[ï_L´äB»Þ.ù€bMÆyû©6ÆÔüB‡ë!õ=¶—â°u¡Œd½Þ‚+½t†Zá´¡´ÚØó®±g‡P¯C’ßt½R¦®3 Õ_ôJFÛh¯zÈ(1€Xqd”u–ŽmØ�Ç×¢ö£Ôãk™}5ÁW�ÓEJ×Ô›îx•lìð‡.êr\ë2Þ‘Q·pN°ÒxBïÙ –¤ §ï|Çù�·nL ùH¤gs v~^âTù‚”þ¥Â„¢«ÛÀƒ†Z!ùØ| 6YÉ>)ùù#‘ ›Ç$ú«5M#¹í§gH~Ú»T *À¾DQ*Øébó˜Äi‘б„doÆ´U{GVép‡Ï?*Ýù ÓÜݵhäVê³0ÐpÖz|™y”ìÏ•AÖc¨�ìíɶvw'½PýÁ¼¦Ê>Çû�~Ög¤áìsé"PÕ(Ù†áó²}C€H›éŠ‚²lš£PЮN}5“µ@òïp—šÉ&ýÚ eIª£c/VREÚ8e׉Æ{ U*¼ÃíRH–d¾Ãz¼m›÷×ËöɼŽÂsä–Í3�îTÿ±€`©P$Æü"í¹ˆT{uÀ•×q¬âˆ+¬Ÿv‘qþÖˆdf©m#œ0ºͪi‘õäN‹Q6fhç¿Ì tRp�Ûòš7;\gʶQB hÍ” ÝR¹ 4:ОÙn3BSóF7õëƒ$¢ª€íºÕ.ËŸ#Ûçš®oC\w†â·V ö:Â\›kª�5ºpްÓüNeû_pïB™i÷�‹^žïLì@§<†ašVwr³5^v8ù¦ë ëÀÜNËÐrlm£±Ó2ª`à¯nµÛàUA@ ŠÍNU4]9EÏ7ÿÑ•ê~‡Î„Ü,8÷ý>”ož+9oïOÔþêZÝDœÑüÙ‚sOjÞls¿9Ð2AÚ½�êUªû:M§×…%û $Dè¹Y-§ÝZ²õè�𖆿ÍÞß7Ô©O[^àGš7;”ÑI#Ƶ¡áfƒ(À' .ihÞìPT­ õÃY:¦8CæΤڠ£dsâE¾cWb(Dè¤Ú)2V‰$í?:CöÅE™"î¿ D 6ß󍿝ˆÈþ¢Ç_Ôã—Dd�þ&ÀV¡Ö�…¥%£Õu"Ϲë&ˆž>Efª~ ÜE&|OÀãš¿Ü]TÀfUÿª×°¥ÕÛ¦õü¤¾BØêª¡}°LÓ2ñmœç€«"2­Ïž&5Í¿ÐüUà'DáyM0m€M�ü�b"¾."’j±©¹1£ç·” -`CóÍ^__EÄmé ædd~<¼ ü�LR�zîú¨›}õ½ù+šÿ–b¶Èˆ˜Ök< þmËÄ 4f D¨¹™Ò4Ù&Ÿž¾KìÕW€ÿ"ODJÆôQËÀõZˆ8| ¸ ü†Ì,y6�›zý½ÄRD‚׈ª1-`³Ÿ¤ô•µ³{ˆB¶|Ší¤Ì{ô·�éíÿ~ ü‡LkÌ,y2¾|Yïy†Ì|AFÄ·4ÿ‹Þw7yŒ”ËzÝ#D2‹H¸¥D‚7,‰ÈÐ !ôl¾úB„#Àò”Œ{€OŸ>|ÂÝ~ø5Ñ\'¯ ¦58|øœÞ÷3àm¶±Ÿ¨ �iC [À>½n’(äÍ$µÈkÄ~2"Zšïq„xÒºBOD”`Ç�6g½`šr"R,—€‹À+À;dæÊL‘™.OÆ à>-ã"ð{à-"i>’ø p˜Hìï('ÁLÏ«zß1½Ö ßÈh#´ "qÖ¾–o¸º!-"!•Ç*]‘h�aá¨?~œb‚Ìd`»/)#c‘Mµˆ‚?ÈöÀ5àWd‘ âL< [äÃ^ëí›Ižöü)Í­®F„7¥DBnVÕŽ®ˆP¦É„m�µTDˆ'Â~KMÚdrœ’ñžžÛKùÏøóD-ò¸”ó÷¸æ&FmÞ”õ|ŸZ®Ni€”ŒŽ¾£2 ^ðE¤x“Uv\¦)û5ß`»f¤ÜÒ£ÀLjæn/q€ÖŽËßuM|ŒeµëùiÊÆ9¹%¡•ˆp$xÁ¥$ýÝIkÒ4GCˆm’{‹ÈØòe²·”ð”ŒcD�x‹88óÓ&!š´Ü7ÉÆ-bˆ;| xÀ5ýïÀKÄ0û¦¦–»ÇÿÖîïÜoe&ÊæƒRûæ�Ï4ÑæÎ¸ãéäxF5“œ÷DìI~û0pxÈÕç"1¤,z͸�h†n*�UÍ4Í��A.’9äVAzˆ8ÊÞ›Èé5âÚÈ«‰poèñ ÷·ÿí¦ûí}wìë(!„-#"uœÓÚཚcè½ùŒ {É“·ÇåûˆaâbO6Â…hŸ½ôi"Iö›G‘½6 1øˆ)� 6\²º[[D�òu'\;¾¦Çëú›_e;�7�ˆm10ygU4�—†˜©à&sp>·g´ˆëf‡Sa§)‰<¢¿¬¹sEÓå^C;‰è½ï¨`Ì„ùwzŒ Î~óz·ÈÓ䃄MwÏæ€:�¾NïŠÈ{ÉOÚð+ÄÿŽr½Ëò£ª)-ãR·S "òÑ1ÞÞ !Ü,¹eh©ðA×3 NU¼Bx£‡ò �q?¯k¹]uŽ~bd‰PŽhš"ÚÓKý–jØGÈr x¸Ú�©ín0rDh�=L\³°qÎëDÒwáˆÈa²àÁpX !\í÷óÊDß !|gXõ‘}D!$Ƭ‡nÃÒ·‡aÃUCfÉLàKCzn”¿í¶ÖT‘Ç:\r…¸à³^¤j²öIÛOŒÄŠpMËêÊÌèÆ†»BoW½§Ü’ÿq…,ö¾RÖ U@Gˆ½v¦èšl‰}cØv¿ j#¢[¸¨É|†…Á×h¿çu–Lk Ïξ_ "”„‰½AìÙ]ùŒ$:ºüs”4cä‰P'>GìÑë!„K=”5Ié#£#M„’ðq¢)z3„p¹Ã-UÊœ&j—íĸ<,‡Ü#KDBÂj?…•�#0¢e"ŽMH_IHžq?ÙÆ6ˆŽµBLþC}?¢"fi6BoˆÈ:1¾Ø_»ÏÐ÷™Gê]�aBD&ÕÖõü(É0ž!cˆûDÒcô ì.DCóæÙB}?^0¿ƒî`2_ö‡Ù-HöM)û†ä?Ž»(»õ+À#íø‹NÞ éþ{xÝb¼¿y×dû¿ÍéçÊ �—íßÔ®‚ñýæ]��üÿÕ«Šó’|Çêÿ+ž¯öW}ÌêIEND®B`‚ukui-biometric-auth/images/FingerPrint/18.png0000664000175000017500000000640115167732630020034 0ustar fengfeng‰PNG  IHDRbb«¥ ÈIDATxœí�MˆeGÇw¦3_'&£ÁÌ(�(3f#±ßJ…PW3ºu1‚àF¥³ÄÍwÑE'ŠëEé7  :4‰ˆÒ�D�B°gb¾¦33UÕ÷ÜzU÷ãõ{ïöëž?\ªÞ»÷Ö«{þuΩ:UuH:&霤´Å2{’–;È)Èõœ¤c¹—:ccÆÏ¿c imr[Š ;oN®H:#i±§gÛµ�´èe»bä}Þž 8Ós]÷ |zÜ]ËëÀ*0,Šâ©‰Trn»ç:,ú.tðWÓIJvPï0Tª!é(®µŸõGŒuÊ–¼êóWÚ´hS68­àLÚÉÄåCàœ¶ôbʶ”`–!B9/i#ÑRWäF÷SHÊõPÎ(’XV.ì0ElÉVDxA¬™ßðÂïÅLșà Q£X›VC¨©Ç̉8êzM.èutÚ¿Ù¾^gL#™©VÌœÿ£§úPÿ6�3›3×Î ÿ[ºž俯ïŠÜ‚Ã>|×°çzìe¬WæÆùÞÌIÊÑv W(Ç«EQ<7›ÚíbøÞL˜¶M�;Ú`ÍwQÏì”^Z;J#$�(Šâ)ß³ºHu4¼)÷GˆUÅAÂÇp£èÇ'VéÝÓ�ß-×ç/ûscÍ•¨\ q9¡);&ÞÔ;äF·+‘�Nùs'&iN”¯Ü"D£«F–5ƒÁžœïYŠYWëæ^+‘f¾b$AÈFÐÆ]�þ–šïšz�Ž©œÄ—Ïϼ‡5Ë9ˆE\Oè\ÐvÆLåÀüÜ‚Å7P¶KH:‡››Àß{rÞ¦[á�r0—Û´8UÇÛÁšœ“nô‘Æn´¹gR˜ºFDš0N×µ4ÿð§£SCª3vu�…�GŠ¢øqÍïÛ1L'Íݱð-,hÂJ‹kmëß�ëI�ÚŽÍö÷/GZr¹®µ«Ú¡ØÐ4ùuʱåu9áë2ß=£®0N°ÕxÂß3VÔÁéßqaü§›¨ÚÙ¶9ðv~Q.T¾¤üàoY-ЦnSï4ô UûæS±ÉžìSªÆ�¤‹ÇäüÕ†?v䲟mCÕ°wV ^€éEyÁ.©Ãâ1¹°ŠÔ0�K¨ÜS«ö†¬ìpÌß?¦nþ"hîîš42–u„‘Y˜jw6´øœyT¹Ásmšõ˜)Tµ»ã´BïýÑÚçX¿1Éúìhûœ�jÛU.¾ ÑRM¸"QVs$mê4Q3Ù TÝÃ�57*ƒ~uBYQ{4¶bOªTã”M#šï)TµØÃm’$K¥ï->,[´×k4˜×(„FçѬׂ”…–Ü4Æ uþ+ø¢©§¹,àÓaÃua!@než€!0ŒÉðK*×�AƒÃoÖ-FútÐ¥~]1M"Ú 8\·Þ±üã”ë\ãùmpóÎ�Þµ¶#¯¹¦ Y;Æ6ÅwZÛÿĽK9Ó"óž‹íü¾1±S yÌÂ4­�ssxx�|óó W€ãã–áË sƒqËhƒ©oݪ[àÕB@Òf§-†¦œÔïÿÑÉ?M}ï¡ B&Î}eåÏœû'zߺÖ7g}z1qîaŸkî4'Èpï }•úÁÔÞNÓ´]Xå[h "Ÿ»Ã—S7—Zô¸¦eàÓá˜÷O }jÄc!Mø‘�O‡ e4iÄÜ "|ws€àÉK>6ÕFkæ3}q–Sœ¥ô gcmð£äàÄS¾cWb&Dø ÚiJÖq$¤Ö�Åké¦ë¹^óÓŸöÞ=mÂԈȌV¯àH.‹W¹$ÊM#9´ �Ôu�÷TEئ[79TY}Ý¢üåºÈ©ÊpxÝth6D’z–¦:m½u_-4º9älÃõG©ƒ@© �µ­Çž†Ÿè´³ÓhC2§rÖ¯vEˆÊùˆó ¿7u�è*÷Ç­Eæ«Í>·sæžÜr˜`rj§8Õ2²ºkˆP¹ìeI£«/6T³sÇ”qLÕ�E¹…á•uRCPqO¡f¬¨Å[c<1yu$„k'ü÷*+róÓ�ßëgZøÕoB ÛÅZ¯œk!Ïêð‚uØj¥r•Æ-"&�±Š\ÕÅÑó¹ktZPf‰LÃ=K^˜�—G6ù�= ï<»në:¦ml.QÙ›ï�í“‚ªãƒV;ŠTÝTŸmÑu©ÚÓ’Zt¥w%¼�¶Û¬–;hC`vdlÈZ˵x�¾C*Ôc¾·�ÒûÜZÙiUßXÐ4X4å7 ðÎ(½Ü¿Õ¨. rt}^ùÃŽ-�{]ö~I ’n“t@Ò!I‡%]ò÷=%é]’Ž$ŽÃþ8$iÕ_QÒ�’šæÓËT¶ê9]éLqÃ{‹Ê¯ã"£?^ÀMÛî÷i8 “À}ÀãÀ�?Ÿ^ÎU¸éó·ã¢´òŸ¿ üxÎ_sç7‹¢¸Y)Ä5�ãÓžŽ�%á-Å¿~ ïó/ßþNiªâç°-7E Jíø(ðUàÝæžg�ï¿®‘`Ò7™0)%BÒpN�!] ž”˜Œ�OâõV_ô�€Ÿ¯Q’ЕKBø|gò> Üoîý'ðuà "áûÏöx³(Š�•@!..Šâ‹ãbiLFŠœ�Þ¼ø0px§/öUàgÀ%à%ª>£+9n˜üG€‡p�ÜTëó¤…GLLÈõ.r7²GÄØÿ¨’!À~çpj_‡g€ß—�7¨:ò}À[€÷à¼8’ªðà¯À_pšTGÂuóù.\¯ìçT5Á¦�ûÝ&chÈ–üÇ!Âø€䉈I Úð머§q-ïœà®’öwîl[WàuàIà8- ½£ëŒ’�2C#-ߤq¾r´ém�MD¤�ˆ”¶ù)ûI›¯`®B>�qøðàNKþã�¿eªy§1÷÷øï6p¾æ_äIHµþøûøçƒFlšï7›´c,"< (…ˆGŽK\l²,!>>çz׫yx…ÒOÄëwƒ Ç{qštÔ—ñ}œ© d�0-[>i"¶¾¯ó�‰ˆH°‚O‘bMV.ŸÓ”�ÞƒsœïÖ€_Q}§œ6TI¾`7 ¿7¿ü›´ðëZþf"ÿ¦É[2*çsdt"Â�`IH}nÒšø°$œâœ÷õ–ŒJu©’|ÂAÜZØ;�k¸ÁÓä[þf"Ÿ¾ý.wMÒLµ&Â;fë DŸã´‰ &­¹ø´Ü8'n»»qLÊÖ;î²ZÇ|ÃÿÎCÀÛýõë¸pÉ‹¤µ Nà¹t3ñÙjFË´[rimvìPía[vlzRZ’#è8žÄ9ä#Œú’œVäH°Ç%ܸåʽÚ/áÂ/&ÊÜ’Y”·ã’ð[¡~öó~JíÜG5 ³…-"|Ë·0àxÁ4ùQþ ÔÁè|NcRÚ £éW�»©š¬X3b­ˆ…c{DÖÿø#ð>Ü€»)µ16C×míöܦ¹æZôݦùî àš¤kQcšp%ÛãÙ�ë.òÂ9ìóqzÐç ‡"òn3iì/R>«u6±³Î�´mëÍEXñ‚²„Åæ(Ö ùu#è�ÍçßÀ5¦×ýw!ÿJDÒËP5MGpaåð£û| ¸vnÄœ ]Äf$¬pqMÍE¤Ž˜€l(<6)qØ#6k¹Ñw*X×íµ½­k¦œ ýØW5ìþùÙ•{8VöQnkšÄó[è† óÕʲCÝZd53¨|§”5¨úrÜeíÖ·ïht{ÁR|�}^W4.�ß­ÐèßætAz=–Ür—x­QÌï;ï¶ �. jƒ Š»ý\P´Î”…©ÉIEND®B`‚ukui-biometric-auth/images/FingerPrint/05.png0000664000175000017500000000702315167732630020031 0ustar fengfeng‰PNG  IHDRbb«¥ ÚIDATxœí�Ï�GÇ?å�íŃÙlpbã –Œ‚@ŠÄ!qñp²ø Âà wŸr¶8pö $$”pà‘(‘,L¢lË«¯²Ö8ëìzÖ�C½·ý¦¦Í�îÇ|¥V÷ô�ªê÷­zïÕ«ªp‘K"ò–ˆ¼£[]ÜⅈܚAN&×·DäRQ‚7fH0Å—-¿ÿÊ@D>]@n7ÒÄnº‹ïˆÈu¹ÖÑ»}c!"×T¶ï8yßô ×;.ë %ÄpÍ븕Òó"D¤'"}9."9)"§t[«Øì¾“úìqM«'"¡ë÷‘Û&û "Ÿ›ÀOCtP˜c€m=w| nÜoô¸4ià™;wN€C÷ûP÷ÏBϦ“j"òà}`+ˆˆ„¯%ZMØ}2áÛ9½ˆ ˜$¤&p˜$ �„ä÷Ø~‡„†`òï7•�ËÈm[Ÿr2zd‚ödü2Ù: vlû70b²%ÌJÂѱˆÚ¹¦ZL#D¨ºé“ ½hïɰý+ÀUà à p^·yð>° üø‘ O‚SH‚í•”§,™”¥ª&éljB¶}ŸrRŽ?®¿d~¡×Å߀€¿’P‡„§î·ßž†ç-Ì‘ü—A„#Àö)é~�¨j~ ü:'É/€ÿ[ÀgÀCà ð9Õªi ø¾_Õ|ÖˆIŠ�ÛÄ–óˆŒÛŠ„?Ök)!ãrIMc)Dàϥǀ߅:Iî#àŽnw™ö¤¼ÝH ÷Q‘rö¦‚^Ñü_~‘ó:þ Ü'¿%ø½‘àÏ0G Yˆg‘’rø#ð=Mæ+b�ÿðO&�¹·)æYÁtË€i75uYÍ0ÿø‘˜5}öð6±…S5ßíÓã‰­Ž·5·×”´#b@&tìIÙ%¶‚À_ˆÂß×kß"³uÉðníD™$!ÏC�øŸ´¼¯¿6ˆÞÖYM?ÎdÍïëÞÊ:fÒã;*¯ˆÔm3µ%a@&l#¶"BŒ”Ÿ÷ˆ¤x¢zÉñ¬dxÔ!!Ï|x•XAfªùLª¦ƒô|™í˜Y5%$xÁç‘âUVÑqª¾òŒz]2&ŠJ5 ~Ÿªoüæ…œ ü€i2&®‘1“jr$xÁ¥$äý®j5éÖsyä¹»EdL—z$x¡ }¦UMQGò=7+C"B‘25Õ'Ìõ¢œaöê#õŠüï*‚ªZMš^JJª‹Søt &ôù:ÿ©Kû)Ó-¯Ls¤½xË¿OFFÚ ÜÖû!„WK†I��T¿ùš½AéfÏ—¨Ç‡ÀIò[Ã!°<Öí ùê'¯æ§!•¼–æ�½S`7¹øß=²ÖyŒ, €É?ÀQ0.Ïé©�Nè6pûArîxrŸ·'~Ÿw.m¶mÝÝ!ó…cö‰Äì‰ñ®h]£»ïÎûÍ®¸{ö“sîÜ×îØ(!„gFDZ“DNêv8¥Çéþ„ '™$ï¸Û§‚N;|§´€à;L ß:f†TUékó”˜ö ÒVã�°ºò'\;ÞÓ㯉}¥'zÎŽ3Mà�1å3i¬òŒgêÕøë1òuz®¿MT;&øÏTà¯j!¿$Syê£è÷Ü"ɾc÷±O“F^ ŽÇî\ê�Ýõ²°ˆw}š�ŽT‰Èiàe¢ê1|Bx$"§ˆnßܵ$¯QÕ�%kiûÀvagy,‚Έ‘óD ‰B9h8ß‘� 2BFÀç!„'Mæ]†Ö‰PA\&k#à~áqåð„Œ�­£6Ëah•U7—‰Æ"Ûm–!…ª¬‹d}©]"!KQ‰uÑj.“Õ¾»uU�ÖÞSÄVÔ#‹–aDôJFuU�ˆl �h;î´IF+D$$ìI(}IþYbM–Ý[�}b-ß©">i±3U–EÑÆÌ OÂø¤ŒÆËL‡]Fd>ú~E¶Cb«±þ�Oã‹2; ªê²>ß�¡B½‚’B¸[qïE²Ú?&Öä]àñ¼jBDÎI=çNïí@®€‡bL¬<�:�¡/s•X#÷BwJî»@&¨=àÁ²}û·õ¾æ5E²Þ…Ø2·Ma­á�‚—ЗÝ$ÖØ}¢P4U&—çyà%=µO¬ñS­ÃU¦ «¨6Te/ "W‰N«.£Ú®Mb‹-¬ñuÞaè|2®ÇöývÍ»µ_…NˆPPWø"òFÁ¥‘;¶ˆæhÃÚV�¯B#S.ËàŒ "RÙŸ¨À0ïX‡�GľC©Ñ7œí8Bød�2Í…¶CÞYØGW=Ù`Ô�üÎ_­€¢Ú«5b°Q§!EÛD\!óÍÑÉJöi¢;ì;…ûD‡ Pm©½ºª?ï4 ö¨Zc°4hØÛjk®»¨÷]Ö­—w½ !„ÃÂ#U/û ûÄVS*Xü6QeoΓÿ¼hÅF¸°ÄfŸ[+•¬ubpa/Ê+";À°N !<‘u`("gÛ4j«EXTs·H÷º´1qòÒB8ð‘7DäŠyL9¸¯û¦—¡q"Dä,™]ø¼äÖMb ½7ƒ[Û‘Óº µCbq¦øq:N£h”°…¡ËÜA«u¹£u“ òpø‘ˆlÕÐíÛÄxÓYrBx¬Ä®‰È™¦‡P›n&à‡EêFk¹E^ws®Ûø@ŸlþЮ[ºI0oSDÆe !ŠÈˆh”{åÛ& J6JDÓ6Â�Á:e»yÂPuÖ×ã�BŸ„vBcê¶Þ>ÖS›5ìÆ^R†B)œ¼,4F„ª“>PZ3™œÍ‘‹Â{!„÷ròè¥ý ÍkKó¾˜>“ÀlVî¸V‚= ?‡30šl&જ a¯ô®.\r%‡Œ¢êVÐò,›Œ`d‘qóJ4ID]› f 'Ø„æ5òU‡©Ã2÷ÓTÛ äóÀžÛaµ´På(LÿÏD„º¨æ‰å Ò<¡BýîÜܲaN”ܳ0ÚPMsÎ\ï·¬¶B…<&vÊæJCÓ1Õúܪ& ¼¦×Ð�Å<–R!:û1“}j­E_ `BÎS_eá�º0nê³õaÚ]a†4¯Ÿa¡‘2cº½H�­x<Ë@c=ë<¿ßCÕ’ r7çšñ²¸‘ÕèyUKe¦-tÙ"6uÿ0ÇŽÔ�éøÎUË¢è„7ZgŸbHa!‡º®o§30–�VgqhØã,Y�o+m .Ô å1ªoÚ*M'— äÛ·qÅ ASKe3ÃMÅuîžV¡1" &…•.�Rá $Uda†¾¬ÃXæ¯ÚRM{DÁ憺abBrŸ8RWµ¤«ÔŽh+\Ó´:Y7 :s_=r‡lUÜ_:˜¤°ÖÐùÒÝ:h}Êe ]»vžÉ•�U¡ó º•L§?§é•©8k�sÍ¡Z&:!­�Û ‹j–®âqÏn�µ†¢0Ȇî U¡ËªG6޶¼&¿*t�É·Z›»rÇ¥1 ¶ïúµ#¢Ó¥Ã³ m¯ÉcDÔߥµ6±†ÜYnÔ®O~�}eѦj²U¡#âì‹ZB !¸pù.q‘|‘ú²Q»1ñÛ�Ui?Ö)ü¥AÁY�yÑùŠ¡:˜å)³,˜E˜ Á�Ï]*ÃJ¡AÁÜ)2%ÏøYäó,¹z¨û nRëX"´`Ÿ‡6£[õŒ÷’î•Lr.Kë:‰ xMDÎÏ»Hftn¬s¾½ñ�šSóÝš·/tºeÞ=¶„ zíÉ' ‰®u+qªÎŒµåÒunufqûá1ÌQæªú£ä¶%ý®®…ØÐtÏçÔ½­Õë_­áz×¶¾ÁOØªÝ V{÷¨° ÚWØ# ÷¢NÙÏÍG+ÁŽ?j9מÛ/ÔèYï{Ö;u;wI/»ÖwŸô9¿¬â"”Zù곃ocâ<ÒQ÷ÎôbZK7©ùݧ‚4.�} â?·®dj�ë*Èôg„ú`ò1CUè¤q¬,.ŠjßWªµ>n†ôÏ×OxBöˆjkîuÍ‹•#ÂÍôX§Æ®–�Ÿ÷” •_)X6‚蔆~ßV¦Ú�X#ŽA›—Ù8Emc¾`9Ò™&¶”o”¿H{‘©/4N‘ 2­Q<Ìi!÷™ÔŒzfö¾8p$ÿ ½²ð;­.¦”öAª0&»Ýetµ�1+œ×d6ÃÜà=ÊgZ‡ÌtÿR�ý²ð\‘Ä€fîjÞ;jý ÇUXy"ÔˆokônXà«b.ðgd¬LËXi"dòý…‘ÕÓL'±ÝkË —ae‰HH¨��!ítFHç=êU&âu¢ Y* I韈4æ.)K;ÿð>NÀQHº„¶Ed—蟣…0w%DÑi!:„NVhô«ùGùK†3]æE…ˆœ1áÞÕóovW¤oêþÝcÄ?ÑøC7ey¡a2¹äÔÓõN‹õAD®;¹_²“7ÜÉ[Gþ�¥C+þ-'ïé 7e~Üêè½:G"ÔYq³(Ñk"r{Ž¿lùýW"òéòº-"×|:ÿÒuÛ‚Ã�uIEND®B`‚ukui-biometric-auth/images/FingerPrint/08.png0000664000175000017500000000715415167732630020041 0ustar fengfeng‰PNG  IHDRbb«¥3IDATxœí�[lW†¿m;vêÚM¨ƒ‹Û”¸Ò–¦´´¨åH$žR‘¸�@¡ðÈ¥\„@\.¤ B� *o„Hx@B•"’¶Ð6%MÚFvÅ­]'vœ,ÖZž}Æ3sæøxfNâþÒhÏÌÙ3³gý{¯Ûì9Dd›ˆ< "l)‹ý¬SˆÈþäär}@D¶å�po'LãlÍ÷ß3‘ã]Èmoúdû¢ˆÈÙÕн]±‘]&Û‘¼÷Å?:ö4ÜÖu#ı+ÖqëVÏ7yhYö‘Ž»£é†­7ˆÈ&ûãAD „šnØz„ˠ醔…�ØÍ%«!¼Xe{Ö=G„¨}'°ÛÊI[:=ÀAàp8B8²&�¬n¶nÃ.s¡Ý^U‰ýÒCÞ¡7ª!"›ÐÞþ1[Ò8AÒ“ÛúL™�tTíFUÚ�Õ?@GK#ªlyÔ9"DS(ûDälFO= ÝWHŠz({$?%±_òÒbYþua‚8ÝøY~#jBT>”êÇ«êí¨�ˆMvÓÇE“^›ª¾fX»öD�¤ÖQQ;vÑ÷41üË@TmÖ>:]þ¯t Ãåß×tC^�¢s nÇzÆ `æ²QGæÍÜImga†$ö8Bx¦žÖ]Á0oÆÛfÅepÜ\Ô=½â¥å¡§F„ˆÜB8bžÕi�†��DKVÛ_ lÞ¼�•IÂ_~Bh4­“FãDˆHšæø:*¸Û€Yà9àYàÇÀ¿m $F»¶ pð.àƒÀíÑoÏß~\.Zy)„p©Û{Z j%BDÐ� sxðUàmQµû�¿;�)””>k«·7&$—P2°rø8ð>ÀÕÔsÀw�ßXý˜”%ß®côTN„ˆô£Â÷eÀÊ/_ŒªþxxžDо„œÅá¤Ä½Yr–aࣶ\cuÿ |x”„„‹©õ%””JFL%D˜º z\¾ ø9ðV«þ0ð#à_$‚ï§éûˆ{n ­¼\|ø00 ¼|ø39$DåÖ˜”5%BD€ ¨ ½ˆ–�¨Î¿Áù ðSû­/*Ë’‘¾�""b|ûðjàÓ¨š8€Ú«³dß¶ãåBáb§²JcMˆˆð2MÆt<ˆö¾YàSÀqZmF}ÀÕÀM¨!¿õŒŠðð?à?Væ‘p1Z¿ø¤? |„V2V�Þ!,•Z ]‘C@¼Ï×ï¾�’ðð9`‘dÄô¥Ö€´—ÞÜÒE3O£Þ?Po)‹ïõ¯¾\ÌŸ§uD\ !!Þ·H#dUDD6`�|"|ý^Ô3Eòm`�lÒ�öüûXùDíêEMþ4-­¢@{üM¨—4\ýöªzŽ�xEN‚÷ükQ'âu(ŸždåHH²béÄÛꘈÔ(p"Iˆ×o~ˆöîGÐÞæª*­¾&�o°K�CUËÀ3vsi;áÛ-M$QAì°%&v ø-Éq¼‡o@ ¸ %ã[¨3‘%p?ÎGÄb´±ìèèˆ#a�DØN„/1 ×?^< |!ú=&óàýÀ=v™iÔ�|Œ|›‘&#FL‚“â½ x °Ñêþ �´_f¥ Ø|µG§P55CNïg%ËûËØŽÒD¤HˆŸEÊ p3ð=`ꋬTe£¨û¸5Œ‡hõ¸Ê�ÑÒTV’àÁÚ’p·ÕŸ~ œd¥ö¢±Ç7€£D½�VÒd´üÞŽŒRDD$¤ ˆIÈÚ~½ÕŸ"{Ôl@]Ç—€?‘ôļ$�Œ–æ’OB쎎ïDG䋨+=ÇJUs�•O“/üx_^�B5Õ–3̱-Lm§ËvmH3 +mèã%íaűÅrsi�²HˆmAÞ ¡iŽ)²UN–ÀóÊÅŒíxdd�efúÅ©‰�ŒíXççyNiÛr�ý&ÀyÛ?”:G|ü»sÚ6­/¢ÞØ,ªnbÒþÿ@´þW””—¬ E#-^��¿–Ë%Þî'�}´¦a–QH„�†¸÷åm÷§¶Ó±DLà(ð »ÑßÙ�¤GPÚÈÃhÁosÀ4 ‹{¸·ã‚µáe”ÄàÍVþÁEÀJ/,OàY¤÷õ‰HÈrk€ˆ¤{ò ¸Ñ–47³1£²õ![6’ôpïå^£Frí‘ǬÌRCñÒ—±¤�uºŒ‘¶é@ÎÕÖ¸µýyÔSŠÕʉªñõs¶¾­ÏÛúy”äs¶Ï×ç¢ãìÜ‹>"¼q1‰®kç1åuq¬pêž^B{jLBì¥IÈ#à ‰K¢r„Võሣë8°ÔíÔ^œ·{wO*ÈeyIËÂM Üëœ�Ž÷kK�ó]'€ëmóÉÂ\N½í¶z¢Ûdšˆ ¢ÎÀ:* !,¶9f¸˜ !íæú� –iù"r Ï�0�>¥›_“Œ¦ }ZDΣíH°cN‰Èf`TDÆBgºmGÔ5¯éF+gB§²*XïG‡ëšöÄÂb,P¹[DvXÉ”•kÙŽ"TN„ˆŒ¡ÞÍúh2“è=Yv4ˆH¿ˆŒØ’'Ô<ŒÛ³~°; Yû+GªÉ{Õ©<Õ "#¨`ŠT�=vÝlË ê…Å¿/ÇBçŠB8$"[�ë ÔÏš¦GÝàJQ)&à!ÛÌTIïuÓ繞⸻ÖEäD Ý>�¦/ÆÈtaΈ‘MU¿ÈRõˆpŸÎS7ÖË·ØæŠ©Ÿf;¶£mu}Æ×ý¼vž T¸“"²T$¼ÂE™E�rNû¦Q•¹™äH%¨ÚFø¯¢¹µ#^'K¦Îlý±±™Â\\?„p1„pø¯íš,a7æSmHÃS(eßf]5*#ÂÔÉPØ3IÔÍl^…¡¡ŒkôÛHˆë¾ˆNì ñÖòà6k8ëGëóÀÀ*œ�ŽPåˆpgÆ \ó…µR0v;2È8ƒª®Ñ6ôkfaðÒÎ>u…*‰(+`TÛ`+O± “­:\¹Ÿ®ÚŠ‹î�]¶#Â{i®Ê1¸þïˆsQÝˤ{B¹ú=rs‹FÄ‚•CuºFª©Óž´D¿E½5&ä%4([Õ9ì<®Z/[Õ÷ô¥;�¥Pˆ‘ýèÈ>U�¦ß¡s!g©¯¢tHY¸€ówõÙu‚±[4M„Ò¬8ÃS#E6Æu{ž kñxÖ•EÖY~ SK.È™Œß܈å�¼G¯Vµ´�aêB“#bÒÊÓv¤¬€\Ç7®ZºE#DØ O�g%ú<åPÖõ-̶^¨õ�³,í1F’ä;‘ QªÖÑûßu=*Ý„ × X@IÈJŒ‘ä¨r{zäz.äÕ!Qq�»§íP"rwÆî%”€Ì$  wùAR›K¸¡/ ‹ÜãžB]ªilfª–UÒ¤µi!„�ù�(B¡±Q8lçêù?ZlÌ}�=üÆFM›ú…“ >j™…Ñ-ÿ—K›G4A25ÏvÄØjål–‰ˆZ¢XÅùèì/¨S !Â5†>˜÷¬æY=ö7t_�#%ÔN±/碌D¿vÛ)ÎÖ|ÿ=Ñ/wЇD? ½ŒÿÓˆrȯ'ºAIEND®B`‚ukui-biometric-auth/images/FingerPrint/09.png0000664000175000017500000000705315167732630020040 0ustar fengfeng‰PNG  IHDRbb«¥ òIDATxœí�_ˆWÇ?gw»I¶Y³61²iÚD£­ÕÚ¤ALª‚‚bUŠâƒD_|´ }¨ �EÄTŸôA£ XlAÐÿll)Š64%-ÅÒ4‰�‰)‰»íÆÝîŸäçÃï÷Û9÷ìÌܹ»÷ÎÜìö ÃÌ�;÷Ì™ß÷üþžsï…"²KDî‘ Ûªâë"r¤9¹\ï‘]E ê Á“5?ß@DN­Bn‡ÒÆGoNˆÈAÙßг­YˆÈ~“íD$ïÃñ›Žƒ ÷uÝÀqì�mܺµóMAD]’}dãö6ݱõÙk²?DDB¡éŽ­G¸ü‡šîHU˜ÆŽU¼üxáÕ^ö§Ûè;"Dãë}ÀÛï¶­Óvާ�ãÀÑÂ3]éd/àn»á>ì·ÚýU/qDú(:ôN5â#Dd :Ú¿d[ŠÓd#ù¸OUÑQÛ Zu5iûr.? <ŒjK#¦lI êÔÑÊa™Ì©¢Ù}OIÑå —$ŽHQÙ¡‡X’]D˜ NE>iÂoÄLˆšÃG“AqªW¡¤µ±Åú”hÑkK¯ïYÖ¯ƒÑ ©U+j'ÂnzOê_¢f³vítù¿‘Ð5 —ÿ@ÓyŠ,4l¸ë§�©kÆY4³�,ÛÎÃYîq<„p¦žÞ­aX4ãÓ¶yyGœ²õ`¿DiEè+�‘½!„g,²zŒÖløx²åa·m^«J‹„?G³è_t­Ók Q?é#׎Ÿ¶÷V4W"Ùbˆ§s4¥oêM�C4»�H„t�½··›æDòË+o"ËW�‘’=Qßs(!db¥ZwÍÂ1‘¡ö#9„Lº6®yÈòÂß¡öŸêyŸvI6‰/v\{„UçÄ~4Cãýeó "Є3�Í'ì·ã;ÚÜî à ð¸í¯mWC-õ5¹�›M²ö]kÓ­maNÙMÀÓñˆ‘‘aÙ$"׋ȨˆÜ,"ˆÈ²:œ‘[n‘13K›í^›ìÞC"rg¤±“R£ßè¹F$šp¸˜FçË€AÛ|ôßÜ|ˆ’ñyëÇ•B|�®¡'DˆÈ°ø° 8|˜Œ„˜Œ7ß>mÿ'ðð;{ß·”„¸ï~Û}I¶ëQmü0j×üø%ð* ‹v¼ÕŒ÷ÿ>ü×Þ[ Ë¤t•®C…|'ð[td˜¡•„!` ð´qø5ð2-q‡]DFúeD\±ý&à‹ÀgíºóÀèpœ�àQàM(‰'ì|¼-„®t.­Vt…ˆˆß;{Q¾h¯ý|LÆÏ€ÿ?fÉÌ•“áä‘‘>GNÂÕèõ»�¯oµû4W¢mx*ðçHH_‡;—^ë¬ÄçÒcßbRv ¼NFBU2Òg�œ} î6ßCÍÖ·ÐãZáû…œ½“Ÿ›g²""Ì Ã‘’â‚¿5ICÀ­âÇ)?,èÊKÑñ0iç^¢5wHIpÓs·ý)– ?wäGûô¸eKs•2t¼ä2Ñ'b˜LØñq)£ÀCè ø®uºEx{ι�Øþ ðŒmi˜ºí'í½mhT·ø>!×Ñ:ò‡¢>Z®µ¾Ed¾ªvt¤FÂ0™°�ߊq"Æ€o£‘Ô ê.� ßµ¦H3b3И%w5s7ætýYàITk|ÔÇ~ÀGÿýhÞñškTù´š¦ùô|ßQ™ˆ„„Xðy¤Ä&+>~M²f€¯°Ül¥N½é3 ¡xpst~ø#ŠÆ~ Þ6_GÍØC¨�‰˜Ï9^ˆŽc2ZÞoGF%Ó‘›˜”„¼×ñçîEI�”.iÕ¨Aà3¨pÿbŠ#¬"2Zº‹æO¡áæ.tÖnÔÚ»žåÎ×GûëÀŸ€O¢kr¦ÕìÄäGnÞ‡D„"efª-‘cŽÍGůóÙC–°=¼LFBLÖìÚKv~cÔnLFl‹SÄ!ëUTÎ7�%v vÏ<› MâÞ‰fÖOR¥-W²¹O"##7 ¬¢±ÍNj¼Å#;%è ÖÖ à¯äkÐ hÞ1�–6±œð<2b!¥$¸C^.¢ Ú‚õçðw2'Ž�o>†V¼m¢ã8ó{yÿâ׃dÁ­e˜%I“¬8ÖßhBÙ„ÆÝ¾ßh›ç£æè£&€? !kž3¿-wœC«4’Š‹ƒ±6¤Z‘ +&Åô»fŽ,lM�ñ]¨Ïx -‹ÏGÛëd¦l.Ù<'Š÷³¨_ô½ßoÞú³àá#,¶ÿƒ‘°7sö19)PÇy�X6X[©æl°û½fÂ+~l¯ó|,×�xÔ^E ˆÞîv2'rÞúñÞ\D„Ï&ÌEßü/zNï7v] Ó¨Þ®w‘ÍèH]ð•ë¬D窷§C— ÚÙAV¬k‡Üv’6Ñɦé ×ÜŽ’{=IÔëïÐmµýÅQ g駈¸³÷L|Ö®›f½]kgÕÀÝ"²X&¼Â™FEd° çшk �Äz†^/Bö^ekk7û5yÂ!Ìc&„ðládáRár|}áJá,Z/%cS›þÍ$}H1�K1|D¯Ô´´ÍaêB“±ÛösüHU¹�oÜ´¬�!"㨰ÑzN /9T }Ë´æš@­?œee�­dE¾Ó©6X–\¥Fµ¦P ¢ËðÇȘCIÈ+l%«QŽô(ôœ+º†ÌÄ5ž¶Cψ‘»rN/¢äM¸-½’wMwôe cYxÜW¨Ë4Í ‚Í-uÃ’IÚm}š !äùŽ¥~Ä´pÄÚêûoþ4¾Æˆ&F0­is}éd’Áµ¡t¦®_Ðø¯\ŠÈvÔ ‘™®v¥sÿÐtž‰ˆZ¤ÜĹv–\S !µ�¸÷ªæ JBi(jĹ6•A¶Û¾ÐF÷„òêk-¨+jD“//âÅî£ö•2¡™ù§5ô-Ò'¢�ŸéÔ5ŘFíwé¨Mü‡£hµ‡ÏÚ ‘Ÿ±÷-ê4MÓ¨)˜FW_TRa>*—OçJÌ—ÏÚ-g+´}Yô—ÜJ‹‚�+E_ýLP,¿¨ô]Oôª”=Œà÷Úõ=v�šª ¢P÷Øáé¾:µ-•¬mªMÏG,CÞ™ ŸGƒ€áN„™ÜóµKeè+"¬(˜»D¦ä3Ãh”´œ\Ám/Ú~§Ý¿ô –ÜŠFGîtÛ}&Ž’ÎmæÆÏb‹È€[Ed¼S�ìwÖæ\w�™†‹¨P«8æÛPâ.Ør˼kɾ©”›µÛ5{h�ž.¢¡u-uªÆœµå¶Ñj›Û®â¶Ïz�p-s”…ªþ•(¨Ôé/ˆˆgû#Ö·mÞVÊúWƒÚˆˆ²ë1Ûâ[•µÀà£w†6~Ár…T¸7‰HaTeƒàR42jýéõ,`ÏLS…Ìzͬ/UMî’,{x¡¢ s_âÙù¹ª÷µÏ¯%"Ñu¤Ó¨ííèÁl”îFµx8ÙiÜ/";ÑïO8. 5®ÆK!�;ëv°¹“¬Øw®Â¤QY{›QBcÓØ®tÒsô-Qu;Ù·…NvKX¦a7ÑJÈ j¶.×�e÷ÑJ�1²`âmÊ䫸_)9Ê7ôAì?JC_®ë¦1,�Aç =J�lž¢²3_e?Ò•&'jº¯Ê_¤ÞTYíO1‹&geeŠí,ÏAÚa%ö|“ÕÕ"4FD§ˆ¢&÷ÏP¾Ð2·ý]uöÝÂ5ADRê8´6âèhx¾Ÿ4£ï‰0'¾ÑS!„•”¸½-/ü9}£}M„‘àåíÂÊj‡m¦‹ØÎÖå�ËзD$$TªÆvÐvº"¤ñŒºŸ‰ð"é* É=ÆÉ~*j(s—ô¥oÿá},•¤{‚Ây™BÃámÔPæn 14Ú‰a‹zú«mî¯ò— }ý?mk¢ÿc!"úÉGíü�溴nqÀöGÈþ\ïkÍôe]Ãe~Üÿìȱ¾ÿ“­FˆþÑ¡c—Ÿ<�<"}úçßk6ð�Dò>”^pXVŽ# =WãH„Ú)5º_Zÿ“­*&k~þ¾�´þ¯^U<*ÉŸ þÛmK_CŽräIEND®B`‚ukui-biometric-auth/images/FingerPrint/10.png0000664000175000017500000000710215167732630020023 0ustar fengfeng‰PNG  IHDRbb«¥ IDATxœí�]lWÇ×vìÄ�‰Û¤)©Rœ(UÚ@«D”RBÉB¥â ‰*Tâ«"¼†'„�Pú‚T’©@<�Ê—ˆ…¨@ 4Iù¨µrÚ„DmìÖÆ©LJ‡sŽçÎìÌ쬽»³Žû—FwvæÎ�;çÏÇ=wv"ˆÈ˜ˆ‘“¶UÅ8ë"2Þ‚œ\®GEd¬¨Ác-4˜ÅT—Ÿ¿g "“«�Û±lcÇ£“'E䈈¬éÙnZˆÈA“íÉHÞÇ㓎#5÷uÝÀqŒmܺµóuADN,Ë>²qûëîØzƒˆì7ÙO€B¨»cë.ÿ�º;R¦±£«Ÿ !¼ÙÉþ´=G„h|}8då.ÛZm`8œ&BgÛÒÉNÀÝvÍ}8h!´û«Nb\z(:ôNÕâ#Dd :Ú?g[çIFòÛŸ®2¢£¶AµêjÒäTŸžDµ¥S¶¬ÝÔÑÊq™Ê©'Eg÷™HŠF(G¤8%1.Ei‡bYþÝ"Â1=ø” ¿3!jOdÅd§BI?ºNÄ{èIѤזNß³ ¬_G¢AÒU­è:vÓÃu¨ˆšÍ®k§Ëÿ� ]Ípù÷ÕÝ‘w èÃBÚû±žq˜^3æÈ¢™$³í £±SU®i:®M˜)iöðßÉœš ½bW†CäÏÂ'€'C¿*¹<‡iIs{6Â\NV¨�þ)ÑHêðjl¶]?žÑ’Óe£]ÒÅ”¬å×Oía\ÍO7©7žRÛc{É[�‘lõ}"8¹šÁP+"m(|{ØÑÃ�Îé‘Ù "ƒ"²QD6Ù6ÜdózíÚ ÖÖm’~éz²H;¢ÁÔqÑQá�/³±¦-¯_fÑÔ¼o!*Côš÷]€¥h_¢c|x C}΀©ÂRª‘ ÏÐt5é'"èG…9`ån`%!>_D¤ )‚ ÒpÃÊÍÀï�-À§€çíܰhå�BÇ—’»5õ£Âõm¸䜕~Î÷]о=_Ðü©hÿ2pÉŽ�"­ñæ$,Ùþ=¶ÿ/Ò$d÷QRRÓ.t„ñ?@"ü˜„ŸYÕÏ×HkHÏ® g€ßÏPL‚[†�Ç�;�/‘CBT^§Í¤´•6 ‚ôr ÚF�Ÿû€·€//‘�PFFÖWà>»õvÛî‹ŽÅøðcà5å܈öŸF5ä;¶ß |ûo×C7V&±m!""ÀË,^>�:Åà+À$�>#KFì'²ddŸCБ}/ðQà�¨ÎëÀ÷H› ˜„EàvàVÿQàUò…¿ˆ“%d±EÑ5<ÀŠP@@|,Þ�ŒžþM¢1}Ñþ×­_?Þ¦œŒì3H¦¼x��¶ß@ É#Á?? |5m_%Ñ„¸tâc ¬BCVôZ~ä)&"Þ¿—„„§Ps4L£ù4ð pÁ>�ШYA£f@:L]þœöóÖfÅ$,¢fì#hŠã0ðk;¾ÁJ¦ë¶¿Hl\úEä:JHåh«e"2ZàD FŒ÷½üš]þWà·( Y³µø8꼿ÜB±™ŠçyDÄ¡ªûƒHHøð2ð ÒæÇGø à~Ôt´/ #oiãåÝÖ—YtB•Ÿ²òvÒ¾#œ hÉ<Š’üŸ ñ¾ w �éÇó�ûü†Ýw?V/Dçæm>ú[ˆŽ½ Ì‹ÈA,ÊIesV7¢knt, ."{Qa¼B˜-©÷@áTQ�’kw 6þRáræÜ&à½À|áŸ+½¿ˆlF�3!„s­ö±*:ù�¡+Vr±ˆ< "{Ed°yíF„®¡#nh¥mX;>ˆFJ+®ÿêV¡�ˆ ¡úïoä¡Tˆ¦5 6¼VÔý:òLι mhß\D¸;ûU¯'¬u±Õʼïðí°2�$ǰ•E‚ôk;jVÚ�Žý:M3çkfÉ9�snÀÚ¹VÒŒ�蕚'¨Œì® N�Øeå•?RU@nãk7-«E-DXØé¨Ë9U6[ÙŒˆ*Z³&ÐÕβ˜|+šî8ŸÕ{ýÆ�øºùþwWˆ°W.GI˜GIÈ›èmµ~-–�ô(ôœ/¹µ›¸ÚÃÓfè>cÍ`% ÷µ|®GK¯7¹…;ú² cYxÜSè–išC;]´8b&i—õi>›²ÈA©1-¶¶zþ›?µ…¯1,\݃ n‘&_D1ÒÜÌù׆«UûQ'jÿ•KÙŽš#_¬)ò1vZ9“çG"¢)7q®�ý%uº‚Zˆ0AmEÓËCvx%¡45â\ŠÒ ¾N^h £{BâojC·¢&_Öô$^üà>j_/𙝤Cß"mp"šù™žA·£¦3¨ý.µÿá8Bh°ýFÂ^ô¹òfì=‹n𦒷0®URa!J—O£‹@EæË×ÄÑ7Bšµ=+úKn¥IÁ•,ZµŠžú™ "Øü¢Òë‹>Ñ«’ö0‚ï·úvj�šª ¢Pýµœó-¼�½-‰H;¾ç°RÔ½Ñû&iKá¤%G�ÁV„™!x5+�«FOaIÁ½ÀÞªd˜yÙŽú…—WpÛ+Vî´ûׂž!Âæ÷ Ñ‘;Ýf×ÄQÒÅ¢ ÉÚøE4ˆî‘­jd;P»³6çz'‰i¸‚ µŠcÞ‡÷Z!7J2¡î³�¹³v«³‡tôt ­»’§ªÍY[RniÛœ;?ȹÖ„Ãhš£,Tõ·¡ Sk¤ŸŸí[ß¶Yx[iÖ¿t�ˆhv=jÛPtº²|ôÎÑÄ/Ø\aî]"RUÙ ¸­ŸŒX?‡;½ ØÉ7ýšÍ¬ý>W«Nî2³ì9à\Eæ¾Ägç—ªÞ×®¼™ˆXD_Â�AmoKf£tªÅ3ÀË­Æý"²“ô—]^Cs\µ§BjwÖÍ`#r'I²¯á=×ÛÛŒ›Æf©“Ž£g‰ˆ²¨Û±U;T Ú",Ó°»H2‡š­Ùnϲ{ŽˆèM�Q’`âMÒ䫸_)9Ê^nè‚Ø”†ëÖMcØ£îe"îCMH[IÈÜÿìèxš»¤/=ûïC°œ’îB—Ed ‡·Ñ…4wSˆ¡ÖNÔ{YaS󚻿Ê_¬Í!_ÃýíqÑßà˜°ã‡êëÒºÅ!+'úHþ\ï‰zú²®á2?ƒèŸ9Ö÷²u¢tèóƒÇ¢ƒãÒ£þ}3Àþx$ïcÙ ñŸ[´Šñšž«vHãßæ´‚ãE�”ô²UÅT—Ÿ¿g éÿÕ«Š’ùߢÿÄ^<ô¸ôIEND®B`‚ukui-biometric-auth/images/FingerPrint/14.png0000664000175000017500000000673015167732630020035 0ustar fengfeng‰PNG  IHDRbb«¥ ŸIDATxœí�ßoWÇ?×»qÇi"ŠÚÆ¢ˆªRi"Z� $�Px€Š·”'ƒ��à÷?HÅ?`àxA)R…Ä“ÑR�I…jK°©Ú¤ v•à4ñ�ÃÃ='sfvfwÆ»³³ëä+�fÖsçνç{~Ý{gÆà "'D䬈,ëVKÜ¥‘¥ r2¹ž‘E.V¨0‹µ÷l "+Èm1[Ù9wrYDΈÈ|C}Û³‘y•í²“÷9Òp¦á¶Þ5PB óÞÇݵ~¾)ˆÈù;²w>îdÓ »Û "'Uö+AD „šnØÝ“»é†”…ZìÑ’Å/†Þ«³=ÃÆØ!1¿>,è~N·ªõt€Uà"Ð !¼2”FÖ Û ·a^Sh‹WubIÆ(;´F5#DäQÛŸÑ-‹UM¾¨Çëe4ÚÕ Ñªˆ.íTNñðÑZqewŒ`”!q 圈¬åhê²ÄÑ}-I‰Ê)ž’X’¢i‡qGþ£"B±â:¾¦ÂoÄMHt‡ç3J±R—"ôhÇȉ8¢�^‘8éu¤î{–�¶ëŒS’‘ZÅȉЛžnÂüË@¢Û¹ušüï è†Éªé†ÜCÄš6ÜŽ»«Àúĸ#ÍfN‘Œ¶ó°N2ö¸Bø÷hZ·‡¡ÙŒ-Ûæ�;Ê`ESÔ3ã’¥a¬,BDN†^ÑÌêyңዙ-sºÙ\Uv’ð§ÄQôφÖè½—ǯ™æêñ=·«µI†¸�c)c3ßÔ8$Žn—3B:­çNÓ�HþôÊ=B¤û©‘%Á`ObìY̲¼[«›X¨ –3Bù#9„¬™5îyH÷Äßbÿ«joÓ IñE�Gža�r bž˜ %æû eWÌ$YcX xmÁ£C(uÊŽ%Dä,qm½öÔ¤-·ö…esÊhœ¤Çƒ`Eb�î2»Væša¡v‹ÈXBøF/MÓÎ? |#sªCzŮȅw€çB¿éq?†©d¹c Õ0³„åe½ö¯I̤Nâ³õú¥Œ•\è¥í’N(Öd’?ÕΘ™_èSn)#¤¡çö’Ÿ¶.‘¬åm ¸2ˆ24 g …�ÐΞw�=;‚v‘ôC×+EÖá”i¤ñbèP2zv@µnä)£ÄbÅ‘Q¤,}û°' 1�oÄìÇIã™}5Á—ÍÓE ×Ô;îx•dìðû m9©m™į̀*\,5žÐkvƒe©ô]ì8¿ûÞM$�‰ ìÔÏÏKœ*_”âÁß’”˜Ptm«=ih’ÎÍkñÉJöiIω”xxLb¼ZÓm,û’žö.ˆ p(Y” vQ*<<&qZE¤Ït"!É›1=ÍÞ‘U8ÜåýOHµxa–»·�\Ç aÆ-ԚΚÆ¹GI^ð\©³#…$oOöô»»ÑB�󺕎9>n ³=c çŸ �Êj $ Ÿ—îDzLWäÔeÓ¹‚vmª›l’~‡»ÐÝH2é×K(ËR}µXIé”�Möª”x‡Û $—,Ib‡i¼=06ïËK÷d^_á9r‹æ™ÎôkÿDÀ °P(s~‘Þ�\Dʽ:àêë;VqÄå¶O•@d’¿5"‰[êÙ 'ŒÊ£Yµ‚<+2Mî·ec†^ñËbQ­“‚u>–¿ ûNŸrö @Ñc”¹P:@'K†>R¹ ,ô Ý³×ÃÝ/Ti_UÔIDY[¹ÕŠõÏ‘<çš]߆¸î ùo­ìu„¹eÊ�5¾p�°ßüNiÿŸsíb‘k÷�‹Aîï\l­S£pM«»¹Ø:/»œ|Óõ…u`n·uh=¶¶±°Û:Ê öW·z=àUB@ ä»�²è¸zòîoñ£R|ªM¿CgBîäœûÞê7Ïœ·÷'u­i"žÑýó9çžÕý‹"²OD¦E䀈ÔmxRËlˆÈLf;¼¬ç¿ u´E¤%"cõ‚Ôøuš~¯ Kò€Ddh•cŽD[W€ûˆëë�Dyp¿ÿSˤnÔã¶ž`'Þ^¶�¯èù?ˆHØ !ì”ïåð0ÒÏ©&š°®þ°F"ìð%=÷2pXË�ò¸þÞ¦›ˆà�·´Ñm[÷Óz~¿žßQ‚v€-ÝoÐåÒ¨�ia[øðyà=à'À, A-ÀRÞ ¤­!»™ð¯Gˆ‚»sk`F�½E ;$DL‰ð$øcëËT]S "2¥u·I„ß>|xZ‹þ�HƬ–™" Ì,âOt[„ß ‡íÖ¾¤-â>Ò$l-ÝÏ’O‚·ˆCj1›Àö0I*êg÷;nû6ð5à«À7µè[À�‰ˆ„„6ð-¢`oo“‘%ã#Z×UËÈñ)=~ƒ(è;1‚4fy$l%UrHo["²l†v_C!Â`û}D!fq�˜ ½H$É»¤6ðQ’Lꢀ�€,�i¹kñ=~]Ëx²®é�þÝo›¤-b†„ˆMÝïs„xÒ*a " °c�W�_/ï;ä-fЍ‘? ’óà·¤‰Ê’ñ„ÖmY$Dˆž?¼ ¼F¬�„mÒDÌ’X€ßoº~Òß›ÚþMW¦5ˆ…슦)&â wì]Ö Iü°Øñ!àûDÁm3*ï’<�(�Oks.‘Θ,3²1Æ_é&Á\O–/|#ÃqÐõeS�·H#d“HHé9´ÊDd¬Àˆ˜v ôÇyµÜßZÄØqšHÐðKbäcG–Œ¯ksÞÐk²Dìž"ZßE’@íIð©émßÎì½u›$Â7"|§ˆ„Ü.k•ˆP¦I„mDØVDˆ'ÎRÉyàË$ƒ²·€_ƒo6€{2>ØÑËä�>©ÇÿÒ{¶H“`1à¿Zîiÿo–`šo8@:7+0i‘q¡JFߨQšˆ ^ðy¤x—5MÔ¸G€�]ÆÃ®ê›À�?…“?Œ¼§€�éu/·IRWß'±ÿ�$-ÍfB>kšÒûzKðšoØO·æ÷K­ú‘QŠG‚w1Y²¿×§ÚKÄôõubç³Zü8 |ø€»ö/Ä€nƒ=ߟÏj=6ë{˜|6‰ŽÞÇÜNÖÕäá§YÈ9ÎÆéå¦úá³i¨w5y¿��,^.³œ«ÀÿÜuÈ�)míÔ¬Öñ6‘À Ò=Ã!;D> æv¦I\ÓÃ$nÇ\Í”à»Dë›ÎܯK\™Í,±MBFî °ŒEø©‰vÎï,!&ħIó~´¯`k-`K;צ;­5á1UÝ!jø~Ò~ßH0Í÷ñÅk{—{¡{Œâ‡&p“‹ÿmñi[ë.&B烼ÖÛñ>¢¦t³ýÝìx:çØá É æv¿¼©¿ùæý$AØ ËgKÙ›w; À-’q‚‘f»í¶÷õoïëy¿ÝÔ¿ûýM¢ß‘ ¥¸­íØ4‹0èýË {V 8�³÷äd‰Ø¯õí'MH6¥ÍZW/áç‘€îÛîØ“áµÖ1—uSÏWÁ&|;¾åˆ°ã›n™ÀUÞýšŒÑr�Ä¢Æë£"2 <¤?_+“ƒë:†Mwü#„p»â=OLj\ !ܨrý°Ðô ݈ÈqàQb°- øÙkZÄt¶ ¼YD‚’U„7‰ZÜ‘´Þ‘¢q‹Ð%Í“¬È½KjkxŒHÜ;!„7 Ê´H,f5OãµÌ#¤Ç$ï¿Ð?’/Ô4ö�<ôé¼c¤?€¸B¸VâÚq9u¸^D‚ÂâD¿Þ%ý5¹Ÿ+f´mÇô‘§ mÛÍ~mÛ-FF„ ï QðGI„¬@aÚ»A/"„pC3•à!Y-º�*Á5U’£z�ýÀL�$@�®IDžìSäq-áZÙ«¾þ’ ²Ýb‰-�^.{_½vz/a©âu¢ï­Ô1ÕÒ9¢_'f8•æýEäAàƒîOïW«fZu ñ`ݪ‘}6Àå•ê›%ê]ãºÖ[«Ö÷ÂØ¡×­Mte—†%,µ°‡H²At[7†±]cG„jìýÄ`iÉÄe¢ ºp2™’á©n]¢ï‡…¾3ª›zè8b†8�bY Ęr• Á|ÀvX¦d.ðo#ºo”¿½0ªÿ¨R"›ºN̦Öó,À¥Á‡‰�‚7´®JnF3³ÃeÆ3ÃÀù�×I&Ê®÷™¦8N÷¤¶ˆÄ^µß/ƒÆˆ¨ —5Y̰4xƒÞ�ÓÛ€Ì|ÿPƒý°0Ddæ€*µŸÝ"ÎÐŽ�eŒ=Ä爽Bè9•ѧ.›ø32ÆÆ2Æš%Á¦· gV+Öé§G¶ˆs[# Ƚ0¶DdH(5[¡nOŒÁˆzœ‰xœèB†JBæ×@ µOs÷h‹Àþcq45­Óm„®ˆÈ:1>Ʀ¹ûB�6¢AH|¹ñ`ÿ’µÝ?Ê_LæGÈ'â>‘4ň>úq¹XÐ}gŠä¥ða¼`~Õ`2¿è?%²W>$8�ä›R"ö) IwIöêW€ÇªøKNÞ‹Ùþ{xU1Ùß¼Òýosªà\Q¥óÒýMí2˜ÜoÞ Iÿ_½²8/™ïXý“)Èn³5à²IEND®B`‚ukui-biometric-auth/images/ukui-loginopt-lose.svg0000664000175000017500000000232615167732630021140 0ustar fengfengukui-biometric-auth/images/VoicePrint/0000775000175000017500000000000015167732630016730 5ustar fengfengukui-biometric-auth/images/VoicePrint/16.png0000664000175000017500000000237015167732630017666 0ustar fengfeng‰PNG  IHDRbb«¥¿IDATxœí�ïYÛ0Æïxú6„ p' �:t‚Ð  $� tÒ H'ÀL�à퇜bÅ$þ“èdaßïyxœçtÑÝÉ’¬y¸ð(M™Ò@0mQO®^¯Œvœ´0Xæ5òçOÏÔÛ¤lìÎ{ñÀ%€óŽ>[op.uûèÕ÷�ÿ¢ã²c_ƒâ8÷cÜ`ã|W˜¯ëÞ‹qã®ÆR÷Ï DDÌÌ];6D\ýu툱¢•ÆžPÕ6öÃ¥íç�J}àWIôÇ1üì+ëúo*„¼éÀ…—í� “úwÛØKˆ’�6/u´ç`! Ý"Nä˜+—óáÑ"“ãR¹œ�¶grÌ•Ë1ª€­™J»†hŽu_Á„H"LˆD0!Á„Hm!fDD®•Ë1ª�‰!·¢Ã¦K»¤¼¼ÆÖ:uˆ´ 7ÜñTqÞ%ä^dÆ(îs>äâù~ÚvPJ-ck˜ò–à)­µ ~ë²çû^_¢h½&fþKD·òô&V¹…¨ÝWfþ)Ï*O Q…°D½›ØtnÁÙ[›7¡Ø2A#‰kçç{åímŸB¼Ã™rò½Çê®ÔSfþ£Pž«Ð%3ÿ l{DD§DD!}WoÛD`æDtED ¥bò§‘‹®<ûÁˆÒ"„“ÐßÎ>#Gär¼�PÖ‡E{�ÙBX—µíÐôà=nÕSj‚\¡ŸÑ"tÒ—„ŸIN Šô¢fÌüB¤šr9Þ3óWûW´ y™‚íLlß*Ø&±{Ꞩ !Ý<·ÂÏÂR š¡)÷K}#F÷Õº­ PレͰʼn`B$‚ ‘µB ÝVÕnNØí6�ëºß*{M2É~ÛÂ^VzÞæ½ƒ¦®ûêv ˜1ó·ªE47ñ³ ïòݨ§©‹:C²8àó¡ •�9B†(ÜÐÄîóŒ0T%k×ì¢LŸªÐ”Éq¡ïÆÞ¸AÅ\ÁvNºŸ}AÞÜV!dÙ˺E(:sÌü]Ñö/"ú¥h#Ÿî MN„¥õ|â°KˆLŽÉ¶†¾Q×"LˆH¼Ë2áBD¹\h1#½d˜ÉQc�)ø½-YgrTm ’{Tò�ÆêA϶ŠßÛBSã«i#-¢´®ówíà†VáRcî{Iº¡ÌùžW�´!3¿8!o™G hæ*5Ð e�|—#Ä1Í$ml!æ"ä&䤗›Þ<Û!.û¶[›a C~£´nÎÐa]ÿîŽû‰ÌnpõoËiÁ„H"LˆD0!Á„H"LˆD0!a-„má¿Î�¨κpfàdr\Q1~nÛ»ÅÇÕùÒÿÑ>Àöf�V»b:FîŸþíYÓõ Fpä‹?õê{R>á®Å½re¦}®Î)Uj[¶ï‹Õþvó= ö·HQl,܆9JûþJž½zМïiIEND®B`‚ukui-biometric-auth/images/VoicePrint/03.png0000664000175000017500000000234715167732630017666 0ustar fengfeng‰PNG  IHDRbb«¥®IDATxœí�ÑqÛ8†w=÷nw t w`]¾<©ÀIöU`§9Ø©@JÖU`¦;ü÷À…1IˆX"÷›Ñ@¶ÈÅ?�"ò0p `%¯®,i¢X”“+×[³Cï VyO|ýÙà­G¹ÝU�=x®Ü¸èÚF €+)Û•WÞþ‡Ž›�}� "ˆãÊoã&Û΀çmÙ{mÜ|hǦ€¹”ý3óÐŽMWþgC;b” !ÍØ+šúÁÆq¸°Ýá¸Y¥ü.�þ<…Ÿce[þ]…�“Î\{ÑÞ r×~¶QÇQBT ̰ÿxÿjµ#œÞBx†æ"$†X78€hBˆ±s¯v¼[ÍèNT!<£N k¦:¢"„~51º£)Ä\š'xŽew¬øB¼!ò|öGt¯cÚå_ÍàÎõ¤Ô21º�ÝÈ®Ís´ =è÷(é?ÊùM`7>5Ù9ílˆÝ++6‘ &D&¨ �Ý`¡™ÏЮ’Êùœ<ÚB,$Ý(çsòh q)i¡œ�ÑlÍTØ3Dw¬ûš &D&˜™`Bd‚ ‘ &D&h ñDDàV9£ ™r+:lºtHªËkl­Ó€HÍpï=mÍ!ßWŽå_ÅþƒØP°­ê{ˆ½›)ÍTLÿ<û+1½°š|OÖkbæÿˆè^þü’*ßS!i÷•™¿ÉÛËÆ'HR!,P&õ�[pöÛp‚ØáPùšÚ_F«ÔÎcí�ûçœÓ® Û0óïÈ>Í©œSÿ�øÓv°ïê5¢Nfþ·Ã©—D´–—FLyÛ­7Åûž¤F±ïê1‘"F’Þ'ÈëdÑ^`vM;!¬ËÚ€vÓôâ½?ØSòz"kfþÓ”€-ˆˆ:ƦPûÎ÷'fþu¬m! "úDe€þÚpܽ—F‚JœýèBx¶×Dt´jMÊMSÜ ?k–ZЬ…÷>úÜØHÑ}µnkÔ»¯&B7lñ@&˜™`BdB«Ûªz%/·Û@¡ëþxhì5ÉPñ}€½Eåï�s'M[÷ÕíðÄÌŸ›ÑÜ�òšz>òO�®B¬Û ÉäÊß}š*c„ Q¸¡‰—CÇqh Ö®6¼ØC™>MMÓBÒµ¾Û< Ûé^ƒ³Ýk<­V™üÞÖˆ>t�™Õb 3'¢ïŠö£ø~¨ir"l¬ç“†CB,$µ �ˆ¶aB$â�!þDTÄ^xȆt÷òøB²ÀLÁv°ïuÁÚ´6H—9öüµo_í&;Æ÷º¦©óÓ´�½!OÓŸˆˆ˜ùÇõÀo4p¶ ã{B0ó/$bœ š25ÛD51B.hÈ =IR.BŽÅ鯝M%�‰¶ï†1ò¥m3p†Ûòwß豟ÈWþ¶œ&LˆL0!2Á„È"LˆL0!2Á„È"¶BØ>éñËüŒvò‹!œ™8 I×g´w·íÝÒãÊ|ãÿh_¯M�0Üxå>sÿô¿žµÜ~`DGnüåÁÑPîwz,Ë�®kp*…JýÞ²(÷Å{>Âàd‹»�…CxF¹kΖÿ×`©ó*ªP‰IEND®B`‚ukui-biometric-auth/images/VoicePrint/07.png0000664000175000017500000000240515167732630017665 0ustar fengfeng‰PNG  IHDRbb«¥ÌIDATxœí�áuâ8Çgòî{Òé€í \¹« lÙ«€lä*€« ¹ `+H®‚x+H®‚ÿ~ð ÇÛhdaÏï½}‚ÅÌ(ú£Y‚ÈÀÀ=€�ükÊŠF €U‹vríz`rÈࢅÁ2ï‘ÿþdðvB»-ÊÆ–Þ‹wnzúÛ €iÛ�×ÞKÿEÇ]Ïu "ˆãÆ�q£�ó}ài×ö^Œ›ö]±±`*mÿÆ@DÄÌÜwÅÆˆkÿ‹¾+bä´BÂØ êÆÁF7\Únpݤ4~—D£žCe×þM…�7]¸õ²½dqüÝF�„(˜`ÿöþÅzG{NÂ34 9ĆÁ-&„»ôzÇ»õŒæÂ3êİ0Õ!Äð‹‰ÑM!¦žà)”Ý¡â ñ†Àë ØŸÑ½ i{hh´ÙÁÂ�¤ÔœÍ@1³këGОô{”òe?F(æ§F»¦� ¡GeCÅÖ#Á„HU!PLfš~†€v�¸’2Sösöh 1“òUÙÏÙ£-Ä)3e?F°=Si`÷ͱák"˜‰`B$‚ ‘&D"˜‰ -ÄšˆÀ½²£Yr;:l¹´OÊÛkl¯S�HÏpÓ/-ß»„|ÓU¡^wb{Ú¶ØßhÕ½3¥žÑ¸b(¾ |ë¿·ågÚ¶ØGÓºG51óDô O¿Åò{.D¾2óßòðKí…#$ª–¨û†Îm8û8Õ�ƒU¡™;°¿/xW÷ßB;:༼&ñXqÍ”ò5îÉ'!ýOˆèšˆˆ™„´-ö]ƒfÌü³‹ õQ%3¯¸ô‘ˆ¶T!Ræb{«`›<Ûó®¢ôኙÿ�è﬈‘#2)"ø:[´7˜ÝR!„ YkÐMÏÞ㽑€I×ÄvIÊsyºV°GyÒϘùŸ�¶µCS&å#3ÿYzíZÁß5å!ðAÉþ\lÏCVB>�n‡Ÿ…¥#h†¦Ì{|ò ÜЉ1|µakÔ‡¯&B3ló@"˜‰`B$ÂQ!Ðî¨j·FëNÈt«?jGM25ýÐÂÞ¬ô¼Í{Gͱá«;1`ÍÌ_ë.ÑÜö–¦†LS!¶Ç ÉbÎï§Vh¬Ì2Eá¦&ž]g„¡.Y»Þðl7eúÔ…¦™”[%ßóOTÔWÃþk© F¥²íe×#B;%Úå ›jyŠ™ÿÒ²}(49^mä‡CB̤´$‰c=„ˆÄ§! þW”¯Ë�ã5|¿IvMzƒ¢"‚d] T%kg4joÐ]òœZ® ±{°*45¾›6±×#J{Dÿí£B-˜I©qÑšò¢Ö½ÈÌ{LD%!˜ù'€+ÒÙŠ�ÍÄžmµP&³Ÿêþ)GÈ…1“´Aq7!wÅußLÁvFyÒ:amëù1 £1 ù�Òc+p†»öwß豟Èì×þ¶�&LˆD0!Á„H"LˆD0!Á„H"vBØ>ññÛü‚Š©ÚY•93)·TÌÅÛñnñqmþêÿh�ÒiŒù ›Ž‰ûOÿëY«Ý Fp䃿òÚ{Q¾`Ùâ»reV=ý]½SjÔ¶TŸ7‹ü¼¹§Gû[¤(nÃJgþt¤¸¢JØÇ¤IEND®B`‚ukui-biometric-auth/images/VoicePrint/06.png0000664000175000017500000000236715167732630017673 0ustar fengfeng‰PNG  IHDRbb«¥¾IDATxœí�íYã8Çgxî;t�í t€¯î*`¯è€\ä*[lñU@¶¼ÀVðß%Šqü’hdaÏïyò(/öHÑ?ÒŒ%Y!ò0p `-�®¬h¢Xõ¨'W¯·f‡ Þ÷0Xå-ò÷O¯'ÔÛ}ÕØƒ÷áÀ €«�¾Ûhp%u»öêûÁÿÐq3pY'ƒâ¸òû¸ÉöóCài[÷^7º`SÀ\êþ•€ˆˆ™yè‚MWÿgCÄ(é%„tc/hŠƒ�ãpn»Ãq³J ü&ŽþÄÂàBŒ�{­ãÍZFw‚ áubX7Õ!Äð‹‰ÑM!æÒ=ÀS(»cÅâ�ç°?¢{ÒöØÐ¨ÿj÷.’RËÄèv#»6ÏÑ‚ö ßRÒ¿”ó1šÀn|j²sÚÉ:*+6‘&D"¨ �Ý`¡™ÏÐn’Êù|z´…È$Ý(çóéÑâRÒB9£ Øš©4°kˆîXøš&D"˜‰`B$‚ ‘&D"h ñHDàV9£ ™r+:lºtHªËkl­Ó€HËpÃ/ ÇÝ ¼ãòA¡ s±½m[ì?h•=(•–QÛMyKp‚W–¿Ö*´m±¿>¥ìÑ¢&fþAD yy+ßÏBÔð•™ÿ“§—�N�¨B˜£>Lì :·àì½ÏI^ÿü±¾]Êþ‡Fæu…©¼µDyWêfþ?p^ç´ëú6Ìü+°ý9•sñïâ÷‚ Þ"êD`æ‰è+å Y^ŠÝœt|ÑRl/[ŽëE”!\„þuމ>¢�t!¯O‹ö³kÚ a!kÚ]Ó³÷¼W¤Ô/Éœþɺ,ñiA‘²?2óO"ý®©�tÉÌ+Ø_È#S°�yö5XÑ÷BM OÝ ?ë–ZÐìš ïyðnilÄ_-lí€zøj"tÃ$‚ ‘&D"´ �~[U¯åáv(t‹?£&ò]ô°—U^÷9wÒ´…¯nÇ€Gfþ§é@Í çä]¾ít"o3$“$žZ ©rÐGÈ…šx>tœ†&gíZó]”éÓÔ5e’æúÅ8š\ÒBÁvAºß='o ®V™€ß¶Åœ3«ù$fþFDßíï•ýP×äDØXä‡CBd’&ÛÆF[‹0!"ñÁGÈ„ÿ!PÕðH:ÎpCº{€Ü‘,0 i´ÎYg’ª¶ñ=Áý�„ÚATì«ü8뺦ÎWÓF8öZ„[�JDÄÌ߇(Ð\wP(Øö»2 œí¢é =!˜ù'€ ò–y¤€¦¯ŠÐ•u²ýÁGHÁ4�´QCÌEÈ](¨ôMÑÎ;éú½M%5 ãhò¥m3p†ÛúwwôØ_dƒ«[N“&D"˜‰`B$‚ ‘&D"˜‰`B$‚ ‘[!l Ÿøøu~F»¡álˆÂLœLÒüŒvãç¶½[|\�oü?íloÖh ÜÑÓ1soú·g­¶Á‘þêàÎf(÷-=–Õ@ßkp*•Ú—ú=bQîo÷t„ÁÉþ)v ÷á åî7[~‡=³¦‹éµIEND®B`‚ukui-biometric-auth/images/VoicePrint/12.png0000664000175000017500000000236315167732630017664 0ustar fengfeng‰PNG  IHDRbb«¥ºIDATxœí�ïUÛ0Åßãô;l6�N@;AèÐ B'€N:t‚¤�N€™:Áí‡<ÅŠqü'Ñ“…ý~çp”çJѵôdIqˆ<Œ\XÈ_Sæ4PÌ[Ô“«×+£]‚³‚E^#þdð|@½ÍŠb·Þ‹ Sç}¶Þà\êváÕ÷­ÿ¢cÚqYƒâ8÷û¸Áöó]àaS÷^7îº`CÀXêþ™€ˆˆ™¹ë‚ WÿG]ÄXÓÊéÆžP56öÃ…íÇ� càW ôÇ1ÊÙW6õßÔyÓ1€ /Ú;Cfõï6ÊØËˆ‚ÀÛ—÷OÖ:Ús°žÐXL€Ä· ˜"v쵎WkÍ j„'ḛ̂nª!*Fˆð“™ÑM#ÆÒ=ÀC(ݾâñŒÀë ØžÑ½©Ý74꿘ÁÌ�¤Ô21š�|f×Ö9jОô»“ô‹r>FÈç§»¦� ¡Ge}ÅÖ#ÁŒHU#�Ofšùôíq"i¦œÏ‡GÛˆ‰¤+å|><ÚFœIš)çcTÛ3•v Ѿ&‚‘fD"˜‰`F$‚‘ÚFܸRÎǨB†ÜŽ[.í’âöÛëÔ!Ò2ÜtÇSË÷.ä/x‹’“d`Z[ô]ÙÓ™â)´ŒÆ•êí� ¾õßßZ[ôµ_•Ž6jbæ¿Dt#O¯cåûQˆ:|eæŸòð¬òÀÕ Ô»‰}Aç6œ½*¤;ÜvQ­ þ.v|ÒȨ,ã¿îJŽÓz�;cæ—ÀùSÞ®˜ù_`}W¡{—]½E”™ÀÌ?J½#¢%]*ãL´—¤Ÿœöå¾QZ„púLì1bD&éM„¼>,ÚÌ.(7†¬hwM�Þã­‘€‘BPQÞOß+èO‰è”ÖAùWHmí®)“ôŽ™¿^;UÈï”Ö]à�’þ¥h_†V3BÎN·ÃϺ¥4»¦Ì{|ð\߉1|µakÔ‡¯fB3ló@"˜‰`F$B­hw«j·Fëî6�é¿?TŽšdjú¦…Þ¤ð¼Í{MÝðÕÝ1àž™¿U(¦¹u†%)L1ô™¦F,ë„dsÀçC 4TvÆ™¢pS�»Ž3ÂP¬]kx´‹2}ªº¦‰¤K¥¼5æŸÞ(/¯†þª�£ÔYlß´ˆÐ™mbІ¦ZœbæïZÚ»º&gÂÊF>qØeÄDR Ò‘¨kfD$ÞÅYðw½‚÷ã\»|´W¤{_§�í+P¬�hÔÖ iº ¿ÿ(ê¬]Ö55¾š6±Õ"äjú”ˆˆ™wQ L$Í´ïi}"j­µO$Ýt“[F0ó €ÒÙŠ”ÝA…ö © ÛËÊþ.FH3Hwò¾,%Í´ý) œ¶m'2ŒV0ä7JëVà 6õï¾Ñc?‘Ù ®þm;M"˜‰`F$‚‘fD"˜‰`F$‚‘fD"lŒ°[øÄǯó#ʧj']fàL$]Q¾\g·w‹�«ó•ÿ£}€Ý›5¦^½�Ü?ý¯gÍ7/Á‘îÕ÷¬xÀm‹ïÊ™wô¹:§P©m¹Ý%zŽõÝŠÛ2Øß"E~cá6< p/Øÿ´eâ%cIEND®B`‚ukui-biometric-auth/images/VoicePrint/04.png0000664000175000017500000000235715167732630017670 0ustar fengfeng‰PNG  IHDRbb«¥¶IDATxœí�íYÛ0Çïxú6À¸Ð  ÐN:t‚¤@'H:tÜ € þýàS¢Ç/‰NVìû=OåÅ9�õ�t²$+D&n,äÑ–�³åäÊõÀd›Áiƒe^#Ÿ2x٣ܦecwÞ‡ W.z:·ÁàBÊvá•÷�ÿ¡ãªg_Gƒâ¸ð۸Ѷó}àaUö^wÖ·ccÀ™”ý 3sߎ�WþG};btBš±'Ôõƒ�Ýpa»Åq“RøUýq ?‡ÊªüÛ !_:péE{'È´ùÛF; Q20Áæåý“ÕŽîì-„gèLD€Äëw ˜bìØ«¯V3ÚTϨÚ©–¨!†ŸLŒöh q&Í<„²;T|!^x>›#º—!m �ò/g0u=)µLŒv`=²kó húÝKúE9£¬Ç§F;§� ¡{eCÅæ#Á„HU!°Ì5óÚ5âDÒ\9ŸƒG[ˆLÒgå|m!Î%Í•ó1ꀭ™J»†h�u_Á„H"LˆD0!Á„Hm!æDDn”ó1ê�‰!·¢Ã¦Kû¤¼¼ÆÖ:õˆÔ 7Üñ¤`ÿ Å�šw¡m‹ý…<¿V—jFÐò–î,BÚõì;Ôn?ˆÖkbæ¿Dt+/¿ÅÊ÷PˆÚ}eæŸòô¼öÀU ÔÛ‰}A眽¹7¼ö7ø–š±›ë{÷öýS§š¨˜“¸¯<°Ù΄ˆN‰ˆ˜ùÏžnUÙwš3ó¿À¶k}W¯U"0ó�Í]ÑR8Û× ¶¯©Æ÷(5B8aæ÷ˆù1bD.ém„¼íf—´º¬5h7M�Þó·­G•�Àv-/ç �óŠŠÀ™3ó¯À¶W¾w‰…ÚBäTœð=3ïð½SZ7eK" *•‰í BЦ﭅Pkšä—áVøY³Ô€f�Ƚ筛¥±£ûjÝÖ¨w_M„vØâ�D0!Á„H„F!Ðm«j7·ëvÈuݵ½&÷5Üv°—•^wùî¨i꾺æÌüµî@ÍÍ3,IahbÈ´bÙdH|Þס±²5FÈ…šxÜvœ†º`íjã]”éS×4e’.õÝøÀ›—¯Æ8Õs) ‰ï{k*…�e/«±»O»¡o:Éwµ½“ïÛš&'³õ|â°MˆLR Ò‘hª&D$>Ä™ð?¡b>÷o|—j™“nç!“4W°=§ß«‚u&irµAâ•ZÌÒX=èÙ®õ½ªij}5m„c£F”ÖgþŽäC&©FŸ~NÅJëZ$óžïņÌüÀ ‰1è³9ØÓö;óýCŒ� R Òƒ'æ"dMr*š ­�Ò–^>†a¨Ã�ÿ(mš�3tX•¿»£Çþ"³\ùÛršD0!Á„H"LˆD0!Á„H"LˆDX a[øÄÇ/ó#Zñf}83r2I—G´÷íÝâãÊüÙÿÓ>`»8(vætLÜ›þíY³ÕFpä‡?óÊ{Z>à®Ã½ref=�Wï” µ+ÕûԢاîaƒ£ý/R¬7îÂJûþY¥,ºkŽIEND®B`‚ukui-biometric-auth/images/VoicePrint/02.png0000664000175000017500000000234615167732630017664 0ustar fengfeng‰PNG  IHDRbb«¥­IDATxœí�áuÚ0Çïòú=l@6H6À� í¡$�:édƒ¤@'H:Aœ ÒNðïNX8`lÐɾß{î²í‚õ —R÷¯ DDÌÌm¬�¸ú?k» ÆŠFBH7öŒªq°qÎm×8oX¿‹£?�Qή²®ÿºBÈ—Î\{ÞÞ 2Ùÿmc Q20Äæåý³µŽæ-„gèRD€ø7 ˜bìÜkïÖ2êTϨú©š¨!†ŸMŒúh q)Ý<†²ÛU|!^x=›3º×!mw �ú/g0q#)µLŒz ˜ÙµuŽ=hOúÝKúE9£ óS½]ÓN†Ð£²®bë‰`B$‚ª(&sÍ|º€v‹Hš+çsòh ‘Iú¢œÏÉ£-Ä•¤¹r>F°˜©4°kˆúØð5LˆD0!Á„H"LˆDÐâ�ˆÀ­r>F²0ä":l¹´MÊá5ëÔ"Ò2ÜtÇsÃï.ä|šÅž‹Ð¶Å¾ZÙ¦Ô2jwS^|TðÛ�½�•i˜&e�6jbæ?D4•�w±ò=¢_™ù§¼½ª<±‡DÂõnb_й€³¿ÇRö ±܉c3.x]öO¡3Ú‘yÙÞo9Ç*gæ·Àù‰è‚ˆˆ™‡´-ö�.»z‹Ø&3ÿØrêR^c…bŒ=û8ÛãC Di€™ÿEÌ龜á#rI§ò:Y´Ì®©†¬hwMOÞû�‘€¡’SËÇû7´rúËÐN_»kÊ%½g毥c ù]Ъ œ*Ù‹í,´a5!ä¿ÓEøY·´Í®)÷Þ}×ub _mØZõ᫉P H"LˆDØ+šmUíÖhÝn¹nñ»Cå¨I½§ ìe¥ÏM¾Ûkö _ÝŽÌü­êDÍ­3,IaŠ¡ËÔb¹Ï�|>¶@}e§��) 75ñ´ë<# UÎÚµ†'»(Ó§ªkÊ$]*å­1ÿô—ŠòjØw“˜yhÃ[…�°—u‹�)ÑÚ§hØTóSÌü]Ëö®®É‰ðb#Ÿ8ì"“Ôœt$öµ"|„,øh,¼¯ “4W°ý@zƒ¢eßæ¬�Ѩ­A#ϳýFDj¾.DÙ·uMµ¯¦�pl´ˆRŒè¯6 Ô€LR�-ˆîhÕ=k]‹dÞ{"* ÁÌo¤Šå®LÍ7Ê,Ň²ðrbL'mPÜ äCYJªÑMä¤ë �m '2ŒF0ä¥ûVà Öõïîè±Gd¶ƒ« §I"LˆD0!Á„H"LˆD0!Á„H„µ¶…O|ü:?£bª6k£0='“tyFÅr�mïWç/þCûÛ›5Xí°éº?ú·gÍ׌àÈ?þÜ«ïIù„Yƒ{åÊÌ[ú]­SªÔ¦Ìvaµ[qSzû,R 7᥽ÿÝéµá.ä#IEND®B`‚ukui-biometric-auth/images/VoicePrint/01.png0000664000175000017500000000234215167732630017657 0ustar fengfeng‰PNG  IHDRbb«¥©IDATxœí�áuÚ0Çïòú=l$„N�v‚Ð ’N@:éÐ H'€N2Aœ ’LðïŸ@8`ìD' û~ïñD‚}:ôG:Y’e"}×òªÊ”: €i�rråz  ¿ÏฆÁ"/‘¿2xúD¹�‹Æ&Þ‡ W.ún­À…”íÂ+ï‰ÿ¡ãªa_;ƒâ¸ð۸ζóM`¾.{¯�;kÚ±®àLÊþ‰€ˆˆ™¹iǺˆ+ÿ“¦1rj !ÍØÊúÁÆÇpa»ÂqýBøEýi ?Ûʺü« !'�¸ô¢½d|ølc¢` �íËû«õù´ž¡3C¬\ƒ`Bˆ±S¯v¼XͨNP!<£N k¦*¢"„~01ª£)Ä™4O0e·­øBG�¶CIWÊù=ÚBœKš)çc”[3•v Që¾&‚ ‘&D"˜‰`B$‚ ‘ÚB̈ˆ\+çc”!CnE‡M—6Iqy�­uj©n¸ã¡ä¸+äw\N”üXÈ+xíÔö=…š±³ ¼%8 %Áo#ø¬ïÑzMÌüHD·òçM¬|�…¨ÝWfþ-oÏKì Q…°@½ŸØtnÁÙk�“4c¶×éßö›íJ}ÿ:ã=Îç$î�ß•:`æ ù¹͘ù9°í> ˆˆBú®^#v‰ÀÌ¿ˆhDDK¥l—ò)Øyöƒ¥F=f~‹˜ßQ#Fd’ÞFÈëhÑ^`vI!¬ËZ‚vÓtッÕSª‚\¡(ÊÛî“ĉiªh7M™¤wÌü]Áþˆò&o¤`{ ¶ol¿CMùE¹~Ö,@³iʼ÷Á›¥¶£ûjÝÖ ¨w_M„jØâ�D0!Á„H„ƒB ÞVÕnNØí6�éºßJ{MÈïk¸­aoXø»Î¹�æP÷Õí0cæeŠhnâg)ç� h3U…X2$‹¾~Ö¡®²7FÈ…š¸ßwœ†²`íjý]”éSÖ4 %]ê»ñaV…4$¯ñ»ïB–½¬kD,gêÂÌ?mG�yûš&'ÂÊz>qØ'ÄPÒdkCÛ8T#LˆH¼‹2áߣ|øQ1ïéᤙ‚í)ø½+X%U­ {Tâ�ÆêA϶Šß»š¦ÊWÓF8¶jDa]çß&ÚÃŒò†ÆÜ÷Št·3º¡¼©/õ}Kf~Ð##”›±7"ÒlÊ*ÅÙw1BÓ ÒÆb.B®BFy¤µãÙÒË'4éún‚!Ï(=4gè°.wG�="³\ùÛršD0!Á„H"LˆD0!Á„H"LˆDX a[øÄÇ/óÚ ›p¦ã %]žÐfüܶw‹�+ó•ÿÐ>Àöf�ò]1}÷Oÿö¬éú#8òßzå=.0©q¯\‘iCß«q …Z—Ý{Ä"ßßnþƒ�})6 ×aŽÂþ�ÿ5‹±?”Á)IEND®B`‚ukui-biometric-auth/images/VoicePrint/13.png0000664000175000017500000000235115167732630017662 0ustar fengfeng‰PNG  IHDRbb«¥°IDATxœí�áUÛ0Çïxý„ ¸ÐN�:AèÐ B'€N@:é˜  üû�S,LâXX'+öýÞã9ûtÑÝÉ’¬y˜8p/?m™ÓH0¨'W¯ç&› Î ÖyNüù³Àc‡z›Õ�]yoÞ8pÜÓg,Ž¥nï½ú¾òßtœöìëhAÇ~Œmœï ·«º÷bÜ´oÇÆ€©Ôý#3sߎ�Wÿ{};b¼$„„±4õƒ��áÒv‹ó&µ>ð³$úý~•Uý·B.Úpâe{'ÈlûÕÆ:>$DÍÀooï¬u„ÓYÏÐTD€äëM1¶ïµŽgkí‰*„gÔ‰aaª%*Bˆá£=šBL%<Àm,»CÅâ‘çðvD÷$¦í¡¡Qÿõf®'¥VˆÑT#»6ϱíA¿k9~Q.ÇhÕøÔhç´³!v¯l¨Ø|D&˜™ *ªÀR³œ! Ý"äX*—³óh QÈq©\ÎΣ-Ä‘KårŒ&`k¦òÀî!ÚcÝ×L0!2Á„È"LˆL0!2A[ˆ""çÊåMÈÄ�[ÑaÓ¥}R_^ck�zDZ†îxèhkŠêyåèC'¨žú¼R°½ò=¶íP':‡©Úš©è� {Ë€¢W–ï{ý½d½&fþKD—òëEªrw…¤ÝWfþ)/�O!I…°D½™Ô7tnÁÙKlà rǽØVyL퓆Ñ:k’ÓõÚß_ç*tÉÌÿ"û4!¢C""fþÙö>Uá·•ïê-b�Ìü£åå ùÑÈ)gžýØQ ïIZ„pû¿zH¤È¥/”µ³h/0;¡Jë²6 šî¼×{Jr§}HD …ÄyL²¾* 7…Øw½¨N¾k‡¦RŽ×Ìüµá¼3z ]…‚…ؾT°Mží¢‹5!¤{èVøYXÚ‚fh*½×Ñoà†FŠî«u[[ Þ}5Úa‹2Á„È"¶ �°­ªÝ\²Ûm Ôu84öšdrþ2À^Qû=äÚQ³­ûêv ¸aæoM'Šhnža!×éñë|�ªaÙ¢gFN!ÇÅUãî¶½[z\�/ý/íloÖdàu7MÇÄýÑ\¸p9Ðo-.%o×^~/ý×Ç:DÇ¥_ÇM¶ž eÞ{uÜ|èÀ¦€¹äý 3óÐ�M—ÿ'CbôBª±'4õƒ�ÏášíÇÍ*}à7ièOcÄ9VÊüï*„|éÀ•×Ú;Aíß6êø”3ìžÞ?YéèÏÁBx†æ"¤ ±np‚ !ÆN½Òñf%£;A…ðŒ:1¬šêˆŠbøÉÄ莦s©žà!”ݱâ ñ‚Àó Øѽ i{lhäÕÁÂõ¤ÔœÝÀvd׿9ZÐô»“ôe?FØŽOMvN;B÷ÊÆŠÍG$‚ ‘ªB`;˜kúÚ%âLÒ\ÙÏÑ£-D&é³²Ÿ£G[ˆ Ise?F°5Si`çݱîk"˜‰`B$‚ ‘&D"˜‰ -Ä=€e?F21äVtØté�T—רZ§‘’á†;žz~w‰â*Ì¥B\×b{Ú¶Øw±§STJFçÀ°½6xfyK~T†a¼Ø[/[ˆÖkbæßDt+/Äò{,Dí¾2óOyzÑxà‰*„5Ôû‰}B眽jÈ[[ü²±m‡£Üf㋆£:Ç•·îjŽ™S1Çý.íIHÿ§$Õ!3ÿÒ¶Ø?8vu!êD`æ¿k½£bŽ{CD_‡q!v‰ˆ4.ì?8ö(%B8cæÿ"ú;*b´¹¤·|-Ú Ì®h+„uYЮš½ç;=%3f~ íÐëE݇¶/#çD”3ó?!mkWM¹¤wÌü­òÙ¹’Ï[yhØÿ.¶¿‡6¬&ŠMSÜ ?«–ZЬšrïùÁ'pc'F÷Õº­Pレݰʼn`B$‚ ‘­B ßVÕky¸ÝrÝðÇCc¯I†wo{ØË*¯û|wÒ´u_ÝŽ÷ÌügÓ�"š›gØ�ÂØé*ĦÍ�Lˆ„žG˜ {Û¢pC�ûŽ3ÂÐÔX»Òðh'eú4UM™¤%ßZãOEûÏ•4µBÈd{Y"B;%*Û »jí3ÿ¥e{_ÕäDx¶žOö ‘Ij�t$ÚJ„ ‰m„LøŸQ1/«R�ïá‡øÕjd3»Žƒc¯k¬3I£–MÑ¥û|…ŸgÿàØëª¦ÎgÓF8vJ„œMŸ1ó¯!êA&i®`ûžtÿˆ™¤åùÈŽÌü àŒô–ºCc1±gû•ˆÔºíu±h#¤>�ÙHwògQV ¢ZÛ(Øu¸˜sE†1Br�Ò¶8C‡2ÿÝ=v‹ÌapùoËiÁ„H"LˆD0!Á„H"LˆD0!¡¶ð‰�Ÿç'´Άfâd’nNh;fnÛ»ÅÇåù³Ó> ¥ÝGŠ63÷¦yÖªüÀŽüñW^~/ª,{\+We5ÐïœJ¦ö¥~/[÷¡~ø„ÁÉÞ‹Û�…ûðo??"¢ÿ%Q¯ù>F%ÿIEND®B`‚ukui-biometric-auth/images/VoicePrint/11.png0000664000175000017500000000236315167732630017663 0ustar fengfeng‰PNG  IHDRbb«¥ºIDATxœí�ÝuÛ8…g|öÝê@é@éÀÜ ¼[�³8H©@Nr*°·1X©ÀLÎVp÷Ab(þÈ"ç;‡’E †¸@ˆÈÀÀ=€­]ÙÐD°éQN®\ïÌO\ö0Xå-òõ'€×w”Û²jlí}¸pàf k-n¤l·^y¯ýwû:DÇ�߯M¶� O‡²÷Ú¸ÅÐŽM )ûW""fæ¡›"®ü¯†vÄØÓKiÆ^ÐÔ6ÎÃ…íçÍ+}à7 ô×1ü+‡òï*„|éÀ­í� Ëöouœ%DÅÀÇ·÷/V;úón!F(ǧ&;§� ¡{ecÅæ#Á„HU!PšùŒí1“´PÎçâÑ"“t§œÏÅ£-ÄGI å|Œ&`k¦ÒÀî!ºcÝ×D0!Á„H"LˆD0!A[ˆG""÷ÊùMÈÄ�[ÑaÓ¥CR]^ck�Dj†îxi8o�ý—k%?¶rrñ|O»æWjF­³({Ý*ùàþè²çûY�(Dë51ó"ZÉÛϱò½¢v_™ù«¼üØxâ‰*„êÓľ¡s Î~õù’f쀷N7´m±ß)vü¡‘y�3Õ‹|Àþ©Ô™ÄŽÐù¹`\0óÏÀ¶´Ÿ‹ÿÒwõQ'3!¢OTÖ�Ðär|R°ý ¶ƒú¥F3fþ/b~EŒQHºŠ�×Å¢½Àì–J!¬ËÚ€vÓôì½îÕSê‚×É™ù{`Û7$ë²$¦E|t� í¦©�ô�™ÿV°¿’#S°�yö5XÑ÷FM鞺~Ö,µ Ù4ÞëàÍÒØˆÑ}µnkÔ»¯&B7lñ@"˜‰`B$B«è·Uµ›v» ºî�‡Æ^“ ù®zØË*ïû|wÒ´u_ÝŽ�ÌüOÓ‰"šÎÉ»}7Úé*DÞfH&Iþ|¯CSådŒ�! 74ñ|ê<# MÁÚÕ†g»)Ó§©iÊ$ÍõÝ8›\ÒBÁvAº×ž“7W+„,{9ÔEgÞ3«Å$fþFDßíù~ªir"ì¬ç‡SBd’&[ÆF[�0!"ñ[Œ� ÿíg_üåñHzBg’ ¶?“,0 i´.Xg’ªÖ‰=*ñ'ôB‚Šm•ꦩóÝ´Ž£!wÓˆˆ˜ùß!:�Js ìHgˆÃù^4�t$3ÿ0#o™G hÆ*5¼)û-FˆcšAÚ¨!æ"ä.ì*ihrIµš8"› 3Œ0ä7JÛfà åïžè±ŸÈWþ¶œ&LˆD0!Á„H"LˆD0!Á„H"BØ>ññËüŠÊ¡álg&N&i~Eå8ºmïWæ;ÿGû€Ôwhî¼rŸ»?ú�gmÁ‘ü�WÞËê ëÏÊUÙ t]ƒS)Ô¾Ôïo‹ýþvOgœìo‘¢ÜX¸O¨ì=û?§Ê±U“`ÔTIEND®B`‚ukui-biometric-auth/images/VoicePrint/15.png0000664000175000017500000000237715167732630017674 0ustar fengfeng‰PNG  IHDRbb«¥ÆIDATxœí�ïYã8Ægxö;t:à«€Û `+`¯‚pÀU®¸ ÈU@¶¼°WÁ{<Š…ñßD#+öüž‡G qFc½‘4–d™ÈÀÀ-€ùëËšf €õ€rråz `Ñdp5À`•÷ÈçŸ Þ(·UÕØ½÷á €k—#�Ûdp)eûâ•÷½ÿ¡ãzd_gƒâ¸ôÛ¸Ù¶ócàiWö^·Û±¹`)eÿÆ@DÄÌ<¶csÄ•ÿÉØŽƒ„�fìmq°±®ÛîqÜ¢¿KGÃÏ©²+ÿ¾BÈ—N\y½½dÕým£Ž½„¨Xàãåý«ÕŽá,„gh)"@ú ƒL1vêÕŽw«ý *„gÔ‰aÍTOT„ï&F4…XJóO¡ìN_ˆ7žOÀÇÝ«�¶§†FùW3X¹HJ-£(Gvmž£íA¿IWÎÇhåøÔlç´“!tT6Ul>"LˆDPå`®™ÏЮg’æÊù=ÚBd’n•ó9z´…¸�4WÎÇh¶f* ì¢?¾&‚ ‘&D"˜‰`B$‚ ‘ÚB<¸UÎÇhC&†ÜŠ›.“êò[ë4"R3ÜpÇ«üo‰ò¾ãàC žíà5Ñ÷=´mu*5㺲ö)ø­Äžíà· ø¾‡²-jbæDt'o¿ÇÊ÷Xˆ¾2ó_òò¢õÀU먛‰}Açœýj:À[ª©2|®Üw8ßwâ_B;SGM¡>Ô¸Ÿí%sã93ÿ eWlŸRÙŒn™ù¿Ðö�MõQ'3ÿ0‹"ÚÑM@›Ž ±½!�~mg3J�ÎBÿ¢¦DŒ>"—ô.B^G‹ö³+*…°�µí¦éÙ{Ý)õA®¾3*:忱Uc{Aeó¨Ðé_Ñ9µø®Ý4å’>0ó×meT4o7Ú©ã\lßÉëÐÜP‡ïjBȯ̭ð³f©ͦ)÷^Ô,Í�á«…­=P_M„~Øâ�D0!Á„H„N!0l«j7OìvÈuÝŸ­Q“ 1ß °—UÞùî¬é _ÝŽ�Ìü­í@ÍÍ3lHa¨`ÊôbÓeHüv¨Cs¥±��! 74ñÜtœ†¶ÎÚÕ†g»(Ó§­iÊ$Ýè»Ñ‹œ _4nþEåyjŒ‹m+é'j…�Ió]�ìÔ^È8~Ðy϶jÿÆÌtÓÔ49¶ùÄ¡IˆLÒ$jÃèª&D$>õ2áïlýˆïÒ`¾“ø«`{Kºû‰ìlÖuÖ.㣨 š? ÛÿU¶ODõMSï«i#j„\MŸ1ó?c8DÅ �Eû™¤¹‚íG*||-òAfþ àŒt–”ôBÂeµ�™™5›š½}ÿÔGH»u �ô¤ˆ¹¹Šö°‚³�+Øö}7 #8 yFi× œ¡Ã®üÝ=öˆÌqpåoËiÁ„H"LˆD0!Á„H"LˆD0!a'„má¿ÌO¨ÎÍÆpfæd’nN¨\I`Û»ÅÇ•ùÖh`{³Fœޅû§{Öz÷�ù᯽ò^U¸p¯\•õHç5:•BÊ}“ÑK»e¶Ï"E¹±ðžPÙëö° ¾o³ARIEND®B`‚ukui-biometric-auth/images/VoicePrint/18.png0000664000175000017500000000235315167732630017671 0ustar fengfeng‰PNG  IHDRbb«¥²IDATxœí�áUÛ0Çïxý„ ÂI' ÐN� é¡„N�€t˜  üû!§XqcÇÆ:Y±ï÷O ±Oý-é,É ‘€€k�òW—% ËåäÊõÀ¨Ìà¬�Á"o‘¿2xiQn³¢±…÷á#€+“޾[o0‘²}ôÊ{áè¸êØ×Á ‚8&~7Øv¾+ÜoËÞkãÆ];64Œ¥ì_ˆˆ˜™»vlˆ¸ò?éÚcC#!¤{BUl| ×m×8nTˆ�ߤ£?�ág_Ù–]!ä¤S—^oï™>ÛØÇ‡„(a÷öþÉjGsZ á‹�>ÄÂàBŒ�zµãÍjF}‚ áubX3U!Äð“‰QM!ÆÒ<À}(»}Åâ�ç°;¢{ÒvßÐ(ÿb3I©ebÔùÈ®Ís@{ÐïVÒ/ÊùU Ÿìœv2„ŽÊúŠÍG$‚ ‘ªB Ì4óéÚ5âLÒL9Ÿ£G[ˆ©¤kå|Žm!.$Í”ó1ª€­™J»‡¨�…¯‰`B$‚ ‘&D"˜‰`B$‚¶wDD®•ó1ª�‰!·¢Ã¦K»¤¸¼ÆÖ:uˆÔ 7ÜñÔÒÖùóÊÁ‡N<ÛÁk°ï{hÛM�hÝLÖLÙ³üQß÷âgÑ¢&f~&¢¹¼½‰•ï±5|eæŸòò¢òÀUë¨Ë‰}C眽‡6ì-ñTv×ì;ˆˆ>i-²§pn÷¸{Î)åMØš™ÿöiL›9õŒ™_Ûnì»z�Ø'3ÿ¨qê­äO£O¹Û_l7ö=J�ÎB_Õ}"F‘I:��×Ñ¢½Àì’r!,d­@»izð^—FJ^$r§ÐqNh³¾*cæ_�m�(ïcZù®-DFDç´é ¿W7—tEDA… �s±TÚ|·¹¼^Q ßÕš&¹ZÜ ?k– Y#2ïuð¸¾#|µ°µê᫉P[<�&D"˜‰pP4ÛªÚÍ÷ºÝ2]÷ûCeÔ$CÅóö¦…÷MÎ4‡ÂW·cÀ3«:PDsó +R®è3u…X2$‹>·uh¨”ö2Dá†&ÊŽ3ÂPÕY»Úð`7eúT5MSIWúnlóÐ“ÊľÆ#ÆïÈ÷½BÈä÷¶F´É ַ̬ÈDèáog;X¿XÖ49ÖùÄ¡Lˆ©¤ÖIGâP�0!"ñ_!þnáÕs|—¶¬Iw/�’ï©`»±ïû:kg ÓÚ !óEûjÙG|ß×4Õ¾›6±S#änúœˆˆ™wáP îH÷â™Jšiß‚™_œ‘ˆqLH˜­j3³Z3I´§��ö­ËNz�Ä\„Š`à %8Û™‚mßwÃ0JaÈo”š�3tØ–¿{¢Ç~"³\ùÛršD0!Á„H"LˆD0!Á„H"LˆDØ a[øÄÇ/óʇe§]83p¦’®N(_e`Û»ÅÇ•ùÚÿÑ>Àöf�€+¯ÜGîŸþãYËíFpäÂ_–îˆ`ÑàY¹"ËŽ¾Wç µ)‹2£lv+nÊ`‹ùÆÂM¸GaÏÚèØ¶¬×BŒ-IEND®B`‚ukui-biometric-auth/images/VoicePrint/05.png0000664000175000017500000000235715167732630017671 0ustar fengfeng‰PNG  IHDRbb«¥¶IDATxœí�áuÚ0Çïòú=Ù€n@6ˆ;AÚ h'H6 � é¤$�wèq&H:Á¿8�pmcƒNø~ï噀9ú£ÓY’‘€€sùkËŒ €Y‡zrõz`TgpÚÁ`™·ÈŸ?¼PoÓ²±{ïÅ9€ €«ž>ÛÉàJêvîÕ÷½ÿ¢cÒ³¯ƒAq\ù1n°q¾/<­ëÞ‹qã¾ÆR÷/ DDÌÌ};6D\ýŸõ툱¢“Æhʃ�ýpÝv‹óF¥øM:úó~ž*ëúo+„¼éÀµ×Û;A¦»ßmT±—%#l_Þ/¬utç`!È8~åX~ ûjý[ßëB“ai™Oê„Èä˜Dk»Z„ ‰ÿú™ð¿ ÕüjÐ[JÜ’,0S°½¤Hû‰TuÖ®à£h š_IÛƒ.$¨£*4µ¾š6±Õ"äjú#3ÿêÃ!Ú¸PV(Ø~¤=¿À[B0ó+€ 1ú@;(‡²W"Ú+Ýÿ¯��Š8†Nú¤ˆ¹¹Š\ŽZ‘Nz']ß cà0ä7JwÍÀ:¬ëßÝÑc?‘Ù®þm9M"˜‰`B$‚ ‘&D"˜‰`B$‚ ‘&D"¬…°-|âã×ùm†s³>œ8™ó3ÚŒÛÛönñqu¾ô´°½Y£`âÕûÈ=éßž5[¿`G¾ø3¯¾§åî;Ü+WfÖÓçê�R¥vå¾ÎèV»we°¿EŠÍÆÂ]xBi¿Ø�‘µX \IEND®B`‚ukui-biometric-auth/images/VoicePrint/08.png0000664000175000017500000000236415167732630017672 0ustar fengfeng‰PNG  IHDRbb«¥»IDATxœí�áUÛ0Çïxý¤„ p' �€vºAèÐ ÒN� é¤àN�àß9ÅŠIl‰èlžß{y Ä>]ô·t²$+D&®,äÊœF €yD9¹r½0Ùgpa°ÎsÇß?<Pn³º±[ïÀ+=}·ÁàBÊvá•÷­ÿ¡ãªg_Gƒâ¸ð۸Ѷó}à~Sö^7íÛ±±`*eÿÄ@DÄÌÜ·ccÄ•ÿIߎk¢„�fìMý`ãm¸°pܤÖ~–@Ú…ŸCeSþ¡BÈI§.½hŸmìâMBÔ L°}{ÿhµ#žƒ…ð MEH ±npÉ„c§^íx¶šNR!<£N k¦QB ?šáh 1•æ îSÙ*¾OH<Ÿ€íÝË”¶‡†Fù×3˜¹ž”Z&F¨Fvmž£íA¿;I?*çc4�j|j´sÚÙ�ºW6Tl>"LˆLPÕ`©™ÏЮg’–Êù=ÚB’®”ó9z´…8—´TÎÇh¶f*ì"ë¾f‚ ‘ &D&˜™`Bd‚ ‘ ÚBü "p­œ�Ñ„L ¹6]Ú'õå5¶Ö©G¤f¸áŽÇöòJ>t‚õ¶ �,¥šï1N$i¦¼5SÉAFõèmòG jë½¶|ï¬×Ä̈èFþüÚU¾ÇB§ÝWfþ.oÏ!� a�z?]ßйg/© ûíojÛb_-v½Ó0ZgGáÜí<ðõy. •Ìü7±OSZÏ©¿HüJiû”ªæwÅÌÿÚÎQ¯»D`æo�§/åõ9¡K?ÄvÐEÉ9U¾ÅÃNj„preŒ•.bD)éMy-Ú Ì.©º¬ h7MÞû½=%¯'²dæß)�€_EĦûI|×nšJIï˜ùSÃq7ò*|(<û8ÛÅ!FÔ„ÀzÓ·ÂÏš¥4›¦Ò{ŸünhtÑ}µnkêÝW! [<� &D&˜™Ð*ⶪvó±n·�R×ýáÐØk’¡â›{Eíï˜sGM[÷Õíðƒ™¿4(¢¹!奜“taÈ„ ±l3$“+uh¬ì�2Dá†&ög¤¡)X»Úð`7eú45M…¤K}76y” ¶KÒýÎvyˆ‘�BÈä÷¦F’A̬[˜ù'ýT´ŸÄ÷}M“ae=ŸnØ'D!©éŽh«&DG¼Š2áFëE]I^½�BÒRÁöW’f ¶W¹É®`í ô^R/$¨ÙV»È¤»åû®¦)ønÚHÇV��»é÷DDÌü«‡Ào4pMY©a|Kfþ àŒDŒcâ-ÍA¤}Õxù*FÈê;H�Ž.!§d)©V�‡H§ z!]ß c 0ä7JÛfà 6åïžè±ŸÈìWþ¶œ&LˆL0!2Á„È"LˆL0!2Á„È"6BØ>Ýã—ù UòEÎŒœBÒå Uãï¶½[÷¸2_ù?Úwð¦‡F8®¼rŸ¸ú�gÍ7É‘ î•÷¬~Àmijruæ=}¯Þ©j,·ûŒ^`½[q,£ý-RT Çp�Ú¾¯ÿù­•ë) IEND®B`‚ukui-biometric-auth/images/VoicePrint/09.png0000664000175000017500000000233515167732630017671 0ustar fengfeng‰PNG  IHDRbb«¥¤IDATxœí�íUÛ0†¯8ý6„ âN@7€N@;Aè°AÒ  $�€0fèoø*Nü]Y±ïsNŽòá\)÷µ®dIVˆLÜXó£)K)–-üdýz `ZfpÑÂ`‘÷À¿?¼á·EÑØ½óáÀ5€yO¿m°˜³o׎¿ïÝ-×=—u4° –¹ãFçûÀãÎ÷NŒ›õ]°±`ƾ5@DdŒ1}lŒXÿŸõ]%£•ÆžQÕVºa›íÇM }àwnè'!Ê9Tvþo*iàÊií­ ‹úo+‡è$DÁÀŸ/v´çh!C3܆h7¸Þ„`c§v¼kÍhŽW!£V S ‚ ?«Í‘bÆá }Ù*®¯ð<Ÿ€Ï#ºW>m ÿ3XØž”X&J3��ìêìÎÙæýö/äË>¥qo5å‹�Õq d<<°Þ΄òY¿­1æßQÛ·ošcÞ<۞ё1æoñsñqHcÌ¯Žæ.‰hÃ�ËÊ#»amßؾqìï¤F0ç¾Ïà!¢�H9½ �×É"½ÀìŠr!$BÉ`�MOÎó�Ò£ pÃvÃ/W ç5e gjŒùíÙv§²K ‘RöƒŒ1?[|ï‚òP¶!"¯BP樄m{‚:–],4ñ™aWøiXªA²F¤ÎóÆai¬„è¾j·µâÝW¡ºx TˆHP!"¡V´ÛªzÍ»Û@*[üáPÙkB6Y~×Â^RxÝæ»£¦®ûjw Xc¾WÈ¢Ùy† M ™¦Blê ñ Çh¬”¶š_M+þøT# ë3ÿ*CÂi*`{EÙ %5gžpê?L"Ûùþ¤nQÂý{mÇáØéÁr²$î°‚Ö¶. R” ð”ÖÍÀ)2ìüo{ú™ý`ý¯Ëi"A…ˆ"TˆHP!"A…ˆ"TˆHP!"a'„ná×çg”ñ&}fä$œnÎ(ŸæÓíÝÂc}¾uÿ´нYƒàÚñûÔ¾éÞžµÜ} x‡Oü¥ãïEñ€û÷ÊYöô»z§àÔ¶Ü—�#Û­¸-£ý/Rä ·á…!ÿ¹†ÖŒ*vÛ,IEND®B`‚ukui-biometric-auth/images/VoicePrint/10.png0000664000175000017500000000237715167732630017667 0ustar fengfeng‰PNG  IHDRbb«¥ÆIDATxœí�íYÛ0Çïxú6„ H'€ h' � t‚Ð ’N�€tè˜  üûÁ§XÇ/‰NVìû=OåÅ9]ô�¤³$ËD&®<È£-K)–ÊÉ•ë5€É6ƒó˼FþýÉày�r›—�-¼\8ïé· çR¶^y/üW=û:DÇ¹ßÆ�¶�ï w›²÷Ú¸iߎ� S)ûg""fæ¾#®ü�úvÄÈé$„4c�¨‹ƒ�ÝpÝv‹ã&¥øU:úã~•Mù·B¾t àÂëí� óæoUì$DÉÀïOï­vtgo!F°5Si`çí±ð5LˆD0!Á„H"LˆDÐbEDàZ9£™r+:lº´OÊËkl­S�HÍpÃ�òÞäºc¥<b?xMô|_„²ù)”¡:˜ùÀ%­‰èL 甊ÑY ÎÄþZÁö)ö=ZÔÄ̉èF^~‹•ï¡5|eæŸòô¬öÀU먷û„Î-8{Ûv€·TSeøÜ[“|‹ Ï÷ÎH”κ¢Po+ÜÍö”ò¹ñ7釂�üÊÙS""fþÒ¶Ø?fæDjD•Ìü#`·”GFÁÄõø"¶× ¶‰¼¾2J�NœúÆGbô™¤7ò:X´˜]P!„…¬5h7M÷Þó­‘R¼³ñŒ™íc«Âö„òþ€ˆhÅÌ/�í7ú®-D&Ü2ó÷=m}¡bÈ"¨”ûx#Ï×DTjá»ZÓ$ÿ2·ÂÏš¥4kDæ=ß«Y1ÂW [[ ¾ší°Å‰`B$‚ ‘�B ÛVÕòp» dºî‡Ú¨I†˜o:Ø›•^wùî¨i _ÝŽ+fþZw ˆæ†¢×¤0T0dÚ ±n2$“2Ÿ÷uh¬lí#dˆÂ MÜo;ÎC]gíjý�”éS×4Í$]ë»ÑЧR’7*~§Æ¸X£ï•BȲ—M�ìÔNF¯³­Ú¿µñ}[ÓäDx²È'Û„˜IšDmM5„ˆÄ‡>B&üO(Ÿ_ º`K‰o$ Ìl¯H7XÙtÞU�õLÒƒ¨ šéÕúHÿ´ ªij}6m„ã]�(­õü݇C¤ßÌ$Õ8YQî{çfò�reÏ ‰}¡9¾˜Ø³½³ïúi·¡“1!—É(ND’)ØÎ(÷Ývf3 r�Ò¦8C‡Mù»+zì™ýàÊß–Ó$‚ ‘&D"˜‰`B$‚ ‘&D"˜‰`B$ÂFÛÂ'>~™Q1=ëÙ‘3“t}DŘºmïWæOþMû ±#¤Q�ì”阸7ý˳–›ŒàÈé•÷¼|À¢Ãµre–=ý®Þ)jWª÷�E~ê» Žö^¤(6îÂJ{ þ8B‘À§UÝ€IEND®B`‚ukui-biometric-auth/images/VoicePrint/14.png0000664000175000017500000000240715167732630017665 0ustar fengfeng‰PNG  IHDRbb«¥ÎIDATxœí�Ýuã6…g|ònw í@îÀLÞ¼©À› ¤T §i+°·+X©ÀÜ ìTpóÀ�Óü•0 DÎwŽ(‹ q €‘€€{Ïòו5MëåäÊõÀ¬ÎࢇÁ2o‘¯?¼žPn‹²±•÷æ3€;7]Ûhp#eûì•÷ÊÓq7°¯“AqÜømÜdÛù¡ð¸/{¯�›íØÔ0—²e "bfÚ±)âÊÿbhGŒ‚^BH3ö‚¦~°q.lw8oVê¿I ¿ŒáçXÙ—W!äC—n½hïY´Ú¨â(!Jføx{ÿbµ£?' áš‹�bÝàBŒ]zµãÍjFw‚ áubX3Õ!Äð‹‰ÑM!æÒ<Àc(»cÅâ�çðqD÷6¤í±¡Qþå ®'¥–‰Ñ Fvmž£íA¿I¿*çc4�ÃøÔdç´“!t¯l¬Ø|D"˜‰ *€¹f>c@»F\Iš+çsöh ‘IºSÎçìÑâZÒ\9£ Øš©4°{ˆîX÷5LˆD0!Á„H"LˆDÐbCDà^9£ ™r+:lºtHÊËkl­Ó€HÍpÃ/ öï Ï0‡¶-öWbÿüku©f½ oéŽÊp �ãª=~­×ÄÌÿÑR^~�•ï¹µûÊÌËáuã‰$ª¨ë‰}C眽»xkdƒ·¿b‡ãäí2~ áPñPyb»�K’f�™ÿ9Õ¯ ûs*æÙß%¦…´=#¢/DÕ¾« Q%3ÿu¤¹k"ÚʱÆúT̳o‰è÷À¶¿Ñ¡³òÉ÷(5B¸bæÿ"æwVĈ¹¤Ëy�-Ú Ìné „uYÐnšž¼ã÷Ú³*ðzQfþÎ¥bH„ŠÀ™3ó�À¶gTÄ¢¾k ‘SqÁÌügÏÏ.%ÝQP!¨(¨Ll‚Šë]Êñ–:ú®Ö4É7íð³f©Í‘{ǽš¥)£ûjÝÖ¨w_M„nØâ�D0!Á„H„V!Ðo«êgùs» äºî�‡Æ^“ /{ØËJ¯û|vÒ´u_ÝŽfþ£éDÍÍ3lIahbÌtbÛfH&RB�áO†Ú!Cnhâ©î<# MÁÚÕ†'»)Ó§©iÊ$Ýê»Q‰ËWcœjWJCòNGø^)„LÒïkÄIn 3«Å›#†äûØ>*VÖ5MN„�õ|âP'D&©éH´Õ"Ÿb„Lø_Q1Ÿt‘Uvôùî=$ßI˜)ØÞPCǧ*Xg’&W¤|…Ÿg_í‹'±¶6ÞV5M�ï¦�p|¨¥õ™?#ù�Iš+ØÞ�î*“ôäû‘B0ó/W$bÄ@c1±g»±9`?˜ïŸb„´Ã©éÑs²&9é6A®éÉó0 cC~£´mÎÐa_þî‰û‰ÌapåoËiÁ„H"LˆD0!Á„H"LˆD0!a/„má¿Ì/è0|œ áÌÄÉ$Ý^Ða¬Ý¶w‹�+ó�ÿ£}Á7=4êA±3§cæþé?žµÞ¿aG¾øk¯¼åV=ž•+³èº§T¨}YÕ½A±[q_&û[¤8l,܇G”öüî žÉ»@pIEND®B`‚ukui-biometric-auth/images/Iris.gif0000664000175000017500000005671515167732630016261 0ustar fengfengGIF89a  æ2¦ìn®üüüâãåÚÛÝu޲…Ó÷wÌ÷œ­Æ.SŠMl›¢ÒÿÊñþSŽ ‘åiÅõóýÿ¸Å×äùÿìûÿPÉ÷ÂîýÛöÿ“äýÒóþp¯×Z½ô»ëýÕÜç+“ͦí�¢¾¢áú‡Ô©äûH¹ô´éü xÓÚùvØú[Œ¼ÌÍÑb½ë%›èS¦Ó©¹Ï‚Îû.v«ùþÿBªêšÞúS¶ïK˜ÈÇÑßL²îHwªdÓù0…»–ÁÕ6dš�Áí,£Û»ñþkœËÄÅÊÜùÿªìþ»ØèxÁçÒí÷2½ô�ÐÿãèïÔåì éý›Ñÿa�ÔÕØ‰Èç°çü¦ÔêÕöþðô÷kÁæ€àü™É÷ƒµÜ¦ÉÚ™Íç¶ßðëóöÜðø¿â÷Œ×øµåöåíòÈÞê³ÏÛžÖï«Þóáð÷y¡Â”×ó‡Ðñëõøc~§£çúR­Þñô÷šÚõ±îþððñèèêôôõÐÑÕøøøÈÉÎììîJ„ºÂÉ>°ñ¼ÊÐÂçùkÍöDÁÂÇÿÿÿÿÿÿ!ÿ NETSCAPE2.0!ÿ XMP DataXMP ÿþýüûúùø÷öõôóòñðïîíìëêéèçæåäãâáàßÞÝÜÛÚÙØ×ÖÕÔÓÒÑÐÏÎÍÌËÊÉÈÇÆÅÄÃÂÁÀ¿¾½¼»º¹¸·¶µ´³²±°¯®­¬«ª©¨§¦¥¤£¢¡ Ÿž�œ›š™˜—–•”“’‘��Ž�Œ‹Š‰ˆ‡†…„ƒ‚�€~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!  !ù ,  ÿ€~‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬šq­¯­²’qt}u«u}t±³À‡p·}Æ«ÆÆ½sÁÏs@ËË@«ÓÔÆr¹Ï¬oÊÙÔܧ»áËtݧoMæË)Ψs)ïÆ@éë¢qîïÍfÕ+fNŸ:~œ€3'¿ZØÂéC¨i@ÄlÞP$Àâ;97Nz#ç�/‘„†Äx%#…ïš„tYÎÅj3izs/\Šœ:Sz G ePA 8ª(š9:¿t ø—­‰Q¦ˆÞ¬Ì·Tgœ›}€ŒÃº&Ñ«á0DKVQ�­}ÿR°}–4\×¶�ô¤$j·…ç€â}T—¯ßYSÃÉ™;¸Q�›@³2K YcK_³‰ VãeLs¶n–Õ™šÃϘôj>| °±Ó¨SïÍÇš”ë>°cËÖÌTáe¹uï¦&—]¸àÂAß”c*såäžœ/³,J5µ&Ð?½ 7öUcų{RËwÞ'òÕj«ŠóæM�öêe¹NJº1ɤ¼�3 ‰°ÔÈ!¼aÞd³õq'¥³ )o ` >ò5àñ…2ÇMJò[ÌA8@ƒ–(‘¢RÎ9½E²ay¡ s[…)èŸ –DpÊw nB"r™ÔC"@(¾·ˆÿ{þgb pth‰f‚ž1ØuÒ�MxIuŒW6ñ´XÉvf²>N9À˜ùP‡™”ÌG.ÓDwšù $W™I-ø #å&Fâ%��¼xÎ% ÒÁ¨"„šO›ôôÐ>eC$$C}úH¥š�ÔÍ@¥ÉJ!Ni‹%õX ǤëÍh&äMÌPÄ�¦*B#úQXè`Ò ­ Ìqä6ƒ(“¡¦˜eYGp=ûÙ‡qå¶P_Q³ MáX…—$ê:È•á#ÀJ~ñš�¨"½q“¸„  ²¤H'i!”é‰ïdóñéh\ÿ’re–…ÄA"ð>G‚¿²·Ƨÿ à>'’}@|úÛÅÝXÖ\þ�‰)0öY{H£ÄòtŠdœÏÉ­)O&¥mÝÔl€—ò·”Q œø4‘÷"è…ý� ¿éå+j~É&2ty"uNÓ£ˆÌËéT)NI ¥sUÉB:?¨ì›�K£PszYy–޶$¤/ƒìÞ0{âú¾Ž —;®µ¿“.${©žðE×w/$TI. ÿå¥wßHaJ7:›ù”¸Î¾"õ½ÈŒÕƒHK5í7ø~^ë¯÷£œ ]ý$ jÈ�#�»ÄwRà?¤4ow ð"Qí!0ûcÄßþ¾NP‚écDax þ+�“ØËÚ$A? úoEe£ص ‚�h›‰‰—ñ"&Ô�a*‘¼°t[;ÌG$pÄß5‡n;Ó2bø¥$âc…„ †Ø ¦ä"D 7a3+šC|…( ÑÅE4È‹„™-®Ò/3fƒŠŠP#'f´ßL¯…A#!æð @Bv¤Ðà¡ÇÞMŒ-Ý% ‰DJ�Ü„tBè‹uŠÿ€�°ä'•ÉMüF0×1¥C)Êê­Ñ¥ÜUB˜:U‚Ò­t%#—ñJH ‡ŠÛj`"(ÉÊ\šè•±aÔ"ò'þQŠÚ¨¤1�YÌ>x§l±a/<&"GÓ Ç¤˜È‰ßP 0‚\„éˆ#…3Mް×3/q7oâ;aD9Ï÷N|¤ÓcÔdD$‰×åÓy¥ÕúiÀ8Q•Òº¨ÑKCTðÁch6ØÙˆ‹fB‡¸UDùÀF‰¡ÿôCüŠ4›”úl¤“XÑ<ñÁi²iTøÃ„}¶‰(zM5­Š—KžMO:½ˆQ!³ŸF"{¾ÔhXüW—"+ÿYj"¬æÔG,„“Šg.SZD¼aF©™XhE}HPFØÇ˜3¥))A­2"P Cp"QS;6®{±ê¹<@¾äõ ±çÒÂyØ�Lpì]=Õ(ŠzȘM¬ ) Š@Y0q“�™¡æ"q•q�Do¹« Ógî¬T&±Ž:"4@+ÅB—º°ž�|2Wi÷ æ1C™’0nŒz¥Š¢pµ»%¨b[’i‹#Qª™WnJƒB)È=MƒQ×Ð+Ê=^"î&Ù«¶ç½ï}wE"»F‡{-úÎkS˜Ca•³²ø/ Gœˆ&ÿ„ ˜ŠŒýq!"ØèÙÅö]ªƒ0ÁÔ¢ÃÏȻɰçWëÞÙÃD@Ð!áû^þÀIè>¶´7\î„l¥×‰°³Þq{5Ú¡x+¸ÏÔí\¢è óžìEñ¡‚Ûð®^�ä4ëH@‘µ?¸*˜ôî¹ ˆ@ª8ç­eP<ŽpÁN10"£¼}4õ$.¾Ü—O"1Ù¹£[fsGœ4µš °“£r*·[¥îyÑñm%Å$+Eú'°%äžooÅë Ýh¬îÑF‘dºNf$u�E½Ùù™fü] µV<^�‹Îctë<ÆÉUy:)�¸õËxãAA²bæŽ^}wþd0uœšÌWAH“è�ÕzµKŸ¶¯ƒòaáÔF¢‘'»£fË•F©cy”£rE®Í0®C7U„wD %v¦Ä�¼©è«†¹^8=þ%)»pvýhU)˼¿í¹�ž{ðä:ù�¨ÇïÑ‘ÅCÿúØÏ¾ö·Ïýîc?!ù ,•ÿ€‚ƒ„…†‡ˆ‰Š„0�Ž�‘’“ŽŽ‹—˜™š›œ™�’¡¢¡¥¦§¨£¢“��¯°±¯� ¢¨AA»¼½¾¿»A·£’®²ÈÉš´�¶¦º¼QÒÔÔ ×ØÙÚØÕÕÒQ¼Â§«�ÇÊçÈÌÎ¥ÑQÕÚñòòõö÷óùÚÝÒÁã‘Ì¡¸F3RìvMÃ�mÞ½ $"F|B±¢E‹%â›—�Z? ÿÊÁ H²Ðq)´†�^=‰EÈ” ¢¦Í›8mΜIQ£=yÜ0|4JdÉswîÔp¦kaË ö&>ÙyS†Õ«&²jÝÊõªUœ<ŸDü/(8�¥Š¶:+©Ò ¦ÿV2dàR*M›XµvÙË׀߿€ýòåÛõkMžc땽&œ8µZØnr«4î´§/IL½›×D_À.\Mº´é¡]&¬Õ0™=/ö¸+-@4’1QNÂî2Ýx/)r–¡· èÓ’+_Î|¹éÐY»†�x¶ÐÚÄBѹ“ûå;¼å^q3^âž�ûMºùð5ÈŸO_>|÷¥U�.ã°±$ÈÆX?DM�wÝ BY I4åÎxP•7UMVéõ{0§Â|3tè¡ †¢‡Χsù ÖEV†Q uŽÙv ‚¹}ž;s‘§ÙpY©g†Ëm¨Á‡!Æ`ä‘H")bÿ‰ö97š~{±Øßk±m0ÛY2ÒÈÖw`8˜#TqÖ£z@&'$‘6 Àšl¶Ùf’!vؤr¤E'¥b ÈÀu�¡q`2•T¢E„FÁCT°§4E„¡„&P æP;É5Fˆ^ƒ¬Ž*¡„°ë+¯¼æŠëF´kĨFàÁ¼²zÀ꽄�ï¾øâ;ï¿{àîÀF¨Kº8d ,Š+¸ÈÒuŶQÌA´–0¢±‚Ü„Ò(Ãü‚c7E”\ò5z‘²,·¬0Ç,óÌ1·ì¸œÏbyÎYˆS ZHP&• !ù ,–ÿ€‚ƒ„…†‡ˆ‰Š„~�Ž��‘‘‹”•–—˜™—’œ�žŸ~𢣤£ §¨©�¥¬­™ª°±±®´´²·¸°µ»›¹�0ÀÁÃÄÅÆÁÁ¾«¼Ì…o²ÂÅÓÔÓרÙÚÕÔÆÀ¹Íµ}}r¨ÀÒÔÚAAðñòóôðAìÕÅàªâ¥ä}|J7l¶wñ¢(ÄÀ�!ƒ‡#J„ذ¡Â(ñîeë6Œß§8þ2 ȉ Ák £4”X¡¥K—bÊœù²¦ÄŠ ímœ@Ì£¤9!-�„ FAk(á-ÄñåÌ $¢F}BµªU«R¥Ò|‘aN ;;Âà$ EŸ ˆFö!êÈ(¤íÿ”:„3¦Ôª"òæÁ·¯ß¿}õꥪU¦Kоb›&6RÙ³h ©eëÖ໥t+ÈœúD°_ C›Mº´éРÿ~ÕpKÄÁ^cü ÒcÈh'û©<›\¦ êrÞÛW4é.È“XμùòäÉO§æ;¸uÌ×cÔHÛããÈ“yû^˜Ù.‰ÎÄ�›PÞÜ…‹ðãËŸÀ½‹æÑIO‘—ðuì^Á3Oµ52¸•ÂIŽD€QpY@^p-ÙEUz2×E{óíqÀ †(âˆ!Îçsùíןu&&`>Žåƒj ä #žÜPG%¥pB…^q®·árïÅGâÿ*¨ Á“PFùd“*,)ß}¤(u"°FÂÙå´XG�¼¡VuœbH(ƒ°)9ƒô†Ò„Až×_ Ç\’Šèä“3*¨ „J¨ ‚BY¥ˆW>×ÅhÓ­øe‹ÛòÍXpŒ$È�ТÅ[ãÍUç� ä¹ÞžJ†øç …Æàê«°Âjh¢S2 –ÈAº%þm`l~Ù_¼%§„*=TáTé�†’©2 h ­ÆÐà +t¶ÜrÛ¶Èzè µ–Šºrɘ ¸È]G‘ë#�š Ù¬‘Чê´6�m%,ðÀ¼í·h¹ćkº¼¶F©lÝ•‚ Ç0䡱Æ5\yøàƒB¡†¤|Tœàò{à°ÇÔ<ÂÍ#à�‡¿+8‚@íóÐÛúüóÑB'íÁÒK€PG]óÔ8T]µË,S¡²J”ì†Èaº#AsLà¥Èr1 h”­±ÇG¡¬Èn�,×(§œµË.[�ÃÔ9ÐC‚{Ѓá¬�¸='íxÐLG.¹D 5FLM�ßXg½u×BÔ 6 ¹3D¨kœÄÙhcÙë…¤pì»!ù ,•ÿ€‚ƒ„…†‡ˆ‰Šƒ~�Ž��‘‘‹”•–—˜™–’œ�žŸ~𢣤¢ §¨©�¥¬­˜ª°±±®´®²·¸°µ»›¹¾¿§¼Â„À‘0ÇÈÊËÌÍÈÈūö¾ÉÌØÙØÜÝÞßÚÙÍǿӤ·Ç×ÙßAAñòóôõñAíÚÌå²ç—°Ô)c× ž¼(1(TÈ ¡Ã‡.\ˆ0Š<|ÞÄ)ë‡ê%T r;e!Ä (S¦ÜÀ²¥K•0!NDx/ã„e?yD ÆÀm#ã%ÄðP¥Ë $’&}´©S§J•¾TùP!M 67µ³�€N>!u'”¡Ã•,•6Á–-ˆ·pÿãÊ…Û¶-S©-SJÄpµ6­:»Æ‘– ¼¡g+´\ú¤n\�#›˜L¹²åÈ�åÚ}’4/ʽ±rûK®ÓÎ>oŒýìV–(´ŒÝ•L¹‹í)*X°è�£·ïºULqaÛöåÌoívfù¹!_‹Içt´Rá ¬&NK¢±lÚ&ŠOYC£ÃŸΫ?”¾}Ž,fL1P¼2rlï2on5Þ蛥M2Ê$}X Ö‰…ÝHÚ½†RZL}'Cm]0Cy”�a†%tèᇠ†¨¡†ð­q}Æ™p_~ËñÇ—ú¸U$uX _qòG$sa#s8r]P%¹ö RÞÍ6aÿx]ä¦!‡"F)å”Ò`b}*Ê�œœ‘°Ÿs4ùµ‘$MØØÇž`RXv%5tdw�½Ym*tð$•†ÐÁž1ôéç {†žw@ŠÈ±è¥‹ÐýG ]­É Yo& œ&LÁzSêÙC 6„ê稤‚jC *%‡Ò@D“%ªßü…æ(¤ )� >¸Ôw&ÀBè± bŸÎê©~àì³ÐF;ª¨=t0¨ˆšå–œ}ÉÀ‹Ñm”«‚D©’ß�AC±Ævˆ¬ Ì ,³}>»Â½øæ›/´~.+o vz¸!»®ÊÚ£¢IG 2MDy¤à‚AhW�º>¸!„j(qÁÇPAÅkìiíÉz®ÐÃ#àár´ú: ³Ì!8 hÍ5Ï<³xàóÏ`Ð=½‚*S€'œ 2 +¡ÄÆn` æ;~M�Ä\#ñÌ1|½5ÄHhãNÅQ¸‰± !µÇt1 1|úiŸxŒ@ÁÞ{³<‚Fàa„Ðí¾‡ë¬8Ï@7îóЀGyFPN¹ËJ;ýtÔS Á¶Õ ôFÔÀu5h…L !ù ,•ÿ€‚ƒ„…†‡ˆ‰Šƒ~�Ž��‘‘‹”•–—˜™–’œ�žŸ~𢣤¢ §¨©�¥¬­˜ª°±±®´®²·¸°µ»›¹¾¿§¼Â„À‘0ÇÈÊËÌÍÈÈūö¾ÉÌØÙØÜÝÞßÚÙÍǿӤ·Ç×ÙßAAWWee(77/øøõ:aEñâi'A³r²Î]‚¥N»nðF‰rÅÊ�L0Ùȱ£ÇŒL^ (£Êĉz§ !*…”P5|ÈMb ²è¸ø±§ÏŸLr”±¢'N”TröÌå'˜‡NÁp¸­f¼‰80À’áЯ`?Š$ª•ÁÑ(ñVNh Tbžÿ¦B¨êîjÖ²NP| € ß4X° B¸°`9rð]ì÷ç‹ c*”=›véZrm=½í$÷!<¬ÊVÀBëǾ‹Î@D†k°cËž}† Ä©ù6îøâ‡˜ ’µ­\ðrfIP9užÐÍnhÀ½tõø'7�5DbwÙÎÝ€÷ïà½sç›ÈšÒ¹us|9¸Y”*™bF®ÐÕæXEWóãG¾Õý…� Ý�ç‚ $¨à‚ p  àu— ©UçŸLü�pÁ g�e-ÑgJ#rôabt Ü\ÌÕ”tÀ�Aùu��]Èà<àã�@ù#ƒ~·Ý¸å¶žÿ'h}X\ˆž p¢‰pLÉ@`)ÉrVÝô\Œ?иXh‚ ù€ *h çœtÊ § n.¡G®¡˜’!eÐd‡(ucÜ't\)‡ˆ•t†ßMZE÷C_~¥FÃÛ}Çf�@Æ)ç  †j褎j¨sâ ¤žâuq / ¦^8i”I�xÌ[ŽºxpV˜ÆØ ,À¦Âž›vú)¨¥Æàì³ÐB[*ªv®šàžg¨pFèF©_VØŠ«”LÁ˜XðbPäðŸ_/¬[DPÂmú詨£B À¿,°´¦ÎPí� Naov&8A¡z½°¡phÅ×ÿLSUeW¤t„ZfÌKD |•°§o.Û¯³¯àòË0Ã𳤂zð¬A2_À&Ã{„·¢"9£<ÓÐ2U1‘V>øà†B\ÀBd�õ 't�ôÐÃËFŒ0‚FàaÄ¿à�+ÀíÀÜtÏ‚!Ü}wÝ|;ðö߀£màAÁá`� öâbïq�J!„Qk5Ñ;JÔÔ3(mÍ}ܼsP @ƒé4Ð�OH®†f&ØÉ™zwB‚'ì¡û?jà©Ê£Ž`ƒÙÄ›]vÙ‡'�ø×ÌïaÃЫ@ÅôTo² öC”û@ñåjÉ·9ç�!ù ,"•ÿ€‚ƒ„…†‡ˆ‰Šƒ~�Ž��‘‘‹”•–—˜™–’œ�žŸ~𢣤¢ œ5 ®¯ «5l§�¥¸¹˜¶�5-­ |ÂÃÄÅÄ i¼“ºÏ¹Í�H­Æ×ØÙ|±-µÒ�Ðá›Ò5ÁÚèéÅ Ýß¡âñŒÒiçÚvv 7É55aþ…YU憂|ùÒ)@€ä�¼gßj¸' !Â}eZ„™ÀQ‚Ç� =Nð˜$L™7,ª$–  3iIIcƒ`•´´2Äc� ‚ J´hÐ † @±£Aœ6„s/$e¨têÏ QÂb;–�Ù³hÓž%K6¬…":ÿP0áêTe00šU¥d Œ$rÒm€BG²i+(^¼xƒãÇ�KNK6Ë�ƒëÚQЂ_[{�‚B’2v27¸¡#qcÈ$bÇ~B»¶mÛ²eGf|6‹•ªì@0ÁsÞO¡ }" a–¬™™üÈböõÙµEh×¢»÷ïà½oßN[÷ãÅ ²”ùœxéÏž’wbÎq‚ަt•aPÁ‰dz=1Þw2h  &¨à‚yOÄö˜¡]…(ÄØÿ»Y°�…؈qh&Q¢¤Ø/Q`YÄ(ã$t§ ƒ<úØÅšlàæ›pºÉ&›A¹ „Ú‰ æ �a°cI�b#  Eâ•«Ôe]7Ñâ—‚UðGŒˆq£ ¦iB›pºà †*ê¨xêœtúh'>ᄘ?æ'‡\±h#Xù‰>¤hGê­逯½#˜‚ £š]t:ê< í´ÔV;í¨ž¾™êª"°cc¼Öç¬N&� | ¥@ø€¤å†«µöÚcc4d*C�k b€ „*í Òª ‚ $¬ð«`í¢žjÀ¶2€ÐÆÿ ö2AÃlâ2à§b/•qkëÚI ZÞD_�Í[ ·Älƾü¾ù)¨Õª ð <÷lÃÏ@ÿÜsÏ ;LmÄrvÑ£ŽDÄ £$lб_ŠmÆ­ °¡Ö)C¯uÄÖ(1�Íͺys´Óê¬�Ï@Ç ÷ÜtÓ4Ñ -m¨¯¹teÓ`$Çô©˜“CÜš@1 ZW !,ØórGÙ¼ÀoÚk·�0Ü6Ô½B!”B ¨—¾Ø-ô y ª¶=6moN .uáW-A ÖÅG¡¥áë’ÇÛ2�>aFÙ±)çüù ?ÏÍú ¥£î½÷§§Â÷ê­Ë 4ϱï jß=³àGN=ëKœ+%-|B‘\*•±Ã/xÁ ÆÀøÀ n‚x�Ra ˆ`p@A XЂ#È Œ€#°Îð€V0B˜ð„(4aRÈBˆð…0Ü  eˆAôà†<Á ¨ÀÃ.PBpƒ‰pƒÜàˆVè{ ²¿?ìÏ!@@Ê@Å2lA*‰¡\ H¯ x1fPƒ²tt�éQáM'Õ öÀÆ=LKk¨[bÐÔ±Žvd��0‚ ú‘‚€Ì¡yÈÃ)4ì Th@. W¨"ÃP“ˆ<ñ�!ù ,.•ÿ€‚ƒ„…†‡ˆ‰Šƒ~�Ž��‘‘‹”•–—˜™–’œ�žŸ~𢣤¤ ¨©©¥­®™lެ||-ª¸¹Ž-´Hޝ±ŽH ´´5ºÌ©5É| Å�ÃÕ˜µ§�l зÍߟ-Ði‘¬Öç…´ ’Щ0òóõö÷øóó©ï’³èª%û3푸d Ñ»7¡¡Ã†"JœHñ¡C|äEJ-Û¤^µŠZ��¤cÉh�ÁÐ!E A‚X˜I³¦Í›3ƒ¼”ðð -Èh)è„dH‘— )�ÒI��§ ’¸”(“f”«²feÀµ«×¯]µj½…¦Î‰Ã<µÃ烧Fÿ‘R‚Æ'¡$y-ÖÚ¹"Ñj­_+ÄÅL¨¤·F,!@”ðc7=¥»6¼Úµˆë×AhßνûvìØ[Ï><8,»$áé;# H5†/¹ÌOò©A¸8·ÂUðaÖO€Ç� hÂ�&¨`�vÞª‘'W70š5ôÛ#³\&WI§Ü7A_D�BL0ñ‡©‘ÐZvÛˆ`4Öx ä c<æÐ� 5Ö¸`ƒÚ…¡a`‘âÿ QÖYº×ˆòMˆØVY¤˜"-£Œ&ÔhÀ™gºð %pH ‚PBD¸àš‰ ‘ \'žax‰Âm3Eå{�XF (–ѲC–Ê�Q‰qõƒ—/¸(¦vÎØž. ê¨%”jꩨšúã¨؉¦ž|úI‚^>Ç¡²·¡Ðå–*&I²�RZp&éh[1PA­ÀB§ev!ˆ.ü1ê 2CªÜrû#¶°zgž4H¤Ÿ9x™A\aàX†»F-v�¢ˆܤT¬r[VªlVx€œÊ0#š¡Š .¶*hàp §†ÐÁ ÿÅ!tÃÂáŽ:n¹&œ›¦Þê®Pú&ÏÌˇl�2l2iì+©%&ë )@ÁÐ~šæµà6¬Á HÛÐCÄ7íô !dŒj«°°Çg‚Ü`x9Æ%Ÿœ«†0‚D¾BQ© ¾Ð`ó±XõWÁ"ìijÒ8´Â ;Œô 6C +œúôáPK­ê U_-ê«æHC×Ld€$»·>ièo‚Ì,TÌ—À€¯^°´¥ÑÍ�ÚDð@y =êà:|4à6à�G [œxÔ!8 üðïàÆÀG½#4?‚íØî!ý'œ@® ®Ó †n¸±�˜Ÿ åÛo0`GP}±ò!úütÃðïÐ[DA\Å•>t/„ü_pŽè€ ª‡ƒRà€lžŒ€‡ZÌð€V0AâÏ Þ‰ÇAxÀƒ ¡<°À.�ì� {P=*¸Ðü‚Ü€?®\%&AøÀ Þ·€Á'ú  P€"àí±ÇT¨"“(Á e(ƒ² �é´@brƒÎ��.zÑ‹*èbU@Æ2šQDðŸ/ „ ¨á�2”a÷ÜðE/˜‡,(;‹¡,Ò‚”¡ˆXI!ù ,4–ÿ€‚ƒ„…†‡ˆ‰Š„~�Ž��‘‘‹”•–—˜™—’œ�žŸ~𢣤£l ¨©ªŽl¥®¯™|²H«¶·œ5²|°½¾�»|¸ÅÆ~»´À¾Í–�­»iÇԶѳ�ÎÚ…’ɲ §¶0ãäæçèéää·µ“Û½�HÂ-�åèûüûÿ ìÇ/„qžHë$¯Ô'o|<§�Ÿ@ A‚Xظ‘K7B6¹ÅŽƒ\”ÐÂFºvqøÔ¨z»jÀ8g FŽQ‚b:4K™ ˜(]ÊT)Š,D‰�’rà¾s0Ê*ªf%TÉìØÙÑóÐ(D¨U[¡mÛ¦pÿãÒ€âv­Ú¨A7ª¸/ŒX;|¤ òŠHð§� þê0»Q(»n+l˜<™ ,q37ý!‚ò†ÈìÍk ‚b¼ôD¸P8N;!Lh12iã¡�ÛR¶Lâ‰oÀE @<@kÖØxð@CŒʼn3!ND„oÞžëÞÅ�WGmÌ­æÔúÏkH±-¢¨ý7[É•{? .„}2òO‰ÞAƒÿÿv]q4ÜÜu$P¦èQ[`°ÞA vž#éMPBÁ€[ñýVß}ùÉ`‰&t¡" Åý1€0úC Ò`B‰÷„e †ÆÀz#Y±×UÁ É/×`Iÿ†Y…wJ½ Û–Íœ}%¢¨btÙ¥ ÐHc#”iæ™3Œ`ƒ€ÑÑЊ7Ê�ãu“µe…R  @UiŠÇš0Ë„‚$Rh¥$z²ih–P(,õCe"biâ‰*zi˜dšé,”ài6à!ê¨x„ª¦š=x*& ]nyb~sò8S£mô‘F’'L3‘G†òÁ¢‰ rÛc/,EDoWJJ)—_jzsÔ27ƒª%�ªí¶`[Â¸ÐªŠ¯Ê ‚Ž–%«pG_~r‚À®½:rH¡ÂpUHzM ¥–Lýæ,¥^b:mµ*ü7ÃÂØàðÃC,j·Ø> ©ÿ¸�§}ÁѰ”ÛQ5dxã Ò½‹«/!ü.ê^˜)•C³ùí¦Ô&¬ÁÂ3Øà³ Ø® ôÐCGüð Øö`ñÅã–Ë1 ޶uמ·’œÈÉ»ðšD :“8‰Ö{?,EÈ“Vz©¦9ûÇóÏ1ÄM±§D×]7Ä!`«µšzùæÆ 8±TŸùÈ�CŠ—H dÍÁ!eðñ×4‚¬“è¢cX ű�6´šîA­Â=‡ŠG  Âê!8àú믯à€Ýª³NæÌí¡û'œ�ñ›Ã—Ãn¸±�†‹|«x;­‰‰•À…´�Àõ (ðEEÿ”Z>øP¼ÀJ” ¤¿Gï'àà>ðÃ_¦FàA¿Ãà�+ð{ë`ë;ØyÀûK`�àú9�~ñƒz@Áœ€ ¼ÀÊ'!¸!|j JFö"¡ „a(ÌÈÁ† À…€óbÃ$#(‚v¨»|Dñ©’ˆš…˜Á H¢—¨DdÀ‰*ˆ¢¥8…*vAƒ¼€¶ØÁïƒVà¡áÜ%2–�HX�AÀFäa�!ù ,:šÿ€‚ƒ„…†‡ˆ‰Š‡~�Ž��‘‘‹”•–—˜™š’�žŸ ~›£¤¥£¡ H ­|¯ ¨ ¦¶·›´Ÿª ¯¾¿¾±HºŸ¸ÆÇ‚°ÄžÀÍÎË‘5¾lÈØ–�¾-Ò‘ÎâÀqߎܯœ¢Ùí„�é| ç�0övùv7(VK–ðøqCŸ>y³Îµ¨É2Ii|e„‹'hÔx%_ƒ(Žˆ9ÒŠ Ú)3ãE{¡ØüÖС©N2}EƒdÏåÆ ‚ Ä‚…20qáâHÓ§"›²@™¤P ?]„ñO65}Z¨ÌOÏŒ¯5j!Š[ pÿá2x¡” ¦xóâ=�CiRQعŠU#F˜dù¤)VÛ§¾Ê *”í[¹ 23¨À¹s& sMº4i,@«þÁ .·F 5 !‰_¡+BµCßÊ,GÁœ¹s… È‘“XNBŒêDßs€:uÓ*TƒvÒYsë×�-\�Ð;ßNƺ �²HÆc k‡cðÞ99ó'øEè×D€ÿ< à€øÀ <7Frt—\°‰‡BJv´ÁV`¥'ˆ'A QIÝp™fœÙGB~ûõן ,¶`Ä(ãŒ1¸Æ‹,à÷ÄrÉ9ø]H}TV/e˜^'¦%Aÿ� Í·Y‰,‡¢Š ´h•&t¡e¼Hã—`vð¢ýí·# =Vð !E†ðàR@¨É0êD^hQíµo¨@>ÿ‘F> $ÀAí. Ÿ[™ùàƒøBP‚»Ð�v€ Û;H�6°QF0 <à 6ï‚Ë �ò4¨A *�‚¡ChDð„t`qЃöàTˆá. @!Á þËŒ[ˆ"›ÂÐæ"5ØAý€€ñwû*’¿�†(ƒ¦x'§>~Z޶¸E"p‘‹þÈ2@Æ2š1*@#UÀÆ6ª` oœÂº0C%\@ x´¡ ŇC'LQ^xxC”ñdE+K¼C‘!ù ,@šÿ€‚ƒ„…†‡ˆ‰Š‡~�|�|‚VV ƒ‘‘‹œ�žŸ ¡¢„�¥¦¦š—¬­U š�§¥£·¸¹·µ¼¼‘vU­Ã—?±š´½§ºÌÍ¢ÊмÇ|?ÄÄU7²ÉÑËÎÞßÛÜâ‘7ÖÖ?vÈâ§H’ßð¡Óììî�vçÖVê‘ôõ�¦Åˆ¨M•ÁX¸ÐŽC;K"JœHq¿H Ø$L³ÉAx§jDRP�!„“''¨\9ÁNƒ—GbÊœIóÈ’ í|8¹PܯYÝ>êò)Ü©…(!°”À´i� ,py ÓÅ«XkÎDA5Á–I{†ÙKè(e"}0…4¥Ê¦ÿ Fµ¥.†»w­4`Âä…‹¿€ L„ U+‚À•°eO‘�H–5û š‚H5Ú®„;×î] AW=ú_&4¨^ͺõÀ9 ÷Å[7ªâ¦*Qöã�ò"n—ÖØÌ´s”Ï¡IWØÀœ9 Nxp`Ï�{¬kw½ZÅi&c*„fp·¶¸-Âèí›Q49�F=Ža<éæÏI<Ù/¢?‘@Ãhà�šÆWÍ‘ZyQD%ÁKñ´ž2í‘¢PJ½•gÉ-çœ~O‘�"€ "Sä €Ä(ãŒ4"øÀ¢¶ßs Žö Qöcð4Y†*5Áÿ„TÑ'Úh#ò'‚.˜Ã•U¾€ 4véåŒk˜ƒŠý‰ð�ÌùHÞ TÝ–b™2�&ùST5PPnðÜeª(ƒ–„XB3Œ è¢Œ2š¨#ÌhË&È ÃŠýí˜fiBFx‘F&D$£’ŠDB~À dSQ½Ä×}~J)¨ &˜Ph%äškxŒ`ïx+¬°6àaC£Š&úb]Ôj)¦f¢ù]y‚ 'ª~ !�& ÂŽªJ 2߉¨_+ZZ+³†âªë®=;ì¼ôÖ{ìºp€Ì6[é¥ dúÜw üd„¸…š9‘]  €»dqv1ð]ÿ¬€ÎZ« ]`€ ¸â @$w°Á òÊ,·ìò¼6„ « ¯y̬³gZ.hÔºYäB¡@Ƈ?ñ‘žH̪“Ÿ6 )‚ .Ç|À»óº¼ò \wíõÉZ£Œ‡Ì¹®±š 6ûûlÀ« dµ¹ÁŠÓ|ÀÆ4 °Á‰ÄÓuœh±ñåºR¯Û±Õª½‹²Ö_7îx×.“] ®VµÚ—š_lÊs„nòôIÑý‘ÊCi0¤z[«>õ7Ÿ>là†4¼ðB \`Ÿà{v{H�„`<Ø4îÀ 4ïüóÐ7ï�¬àAõÆ;£tOÁ8ì�ƒÞï'<B!ÐpÁJ¨!„nøàƒx+VXª×`GA,HûK@ À:·,Éu{’ŸÜ %(á4(™ ȇƒ âÀ{ÝS”ªÇÁëyðzÑ{^´Âè}Ѓ4‚ Wh v¯0Äà ¨@Ãõ±O ð‹Ÿ@…§Ü†HoJ˜€Ô ‚ -ø€@¹ buP,àIZ€´` Jb qš†èÀ‹W£ÇF\AhL£×ÈÆ4ŽBu顟”.R1 @¼_R£ª(Â@ TDÀ ·?!ù ,F–ÿ€‚ƒ„…†‡ˆ‰Š…~��|�| “”•–‹˜™š›œ�žŽ ¡Ž‘’–¦—¤ ž¬­®­¢±±H¤§¶”‘l²�¯¿À�½Ã¢-‘;··µÈ¬%±¼ˆˆAêÁï×À,SfÀ±kÃ9Öx°xÏÛ{rã¾ýØ1b/¬YS¶øïŽ0ž�f4 ǸA¯^¡:â54²Ó`ñ »÷ïà˧�ã°“ ªW>ü² @IGMŽwy¾‹ý€Ie:ƒêèm@ ‡0žh à‚ 6¸àx9ÀDN<1`€ê±WYX`d}V�6SWàÔÓ©‡Þ€O¥&~ÈËGƒp€/̈ð;�¿ýÌ­L¼°ì¤ /ìÂb—°B¨O¼ÂÒL7½BÒwPtwŒy‚PžaçU'œ{ª¼Hˤ Pˆ1‘$ÀÁ!6ß ˜jVV€Ø–]:«°C/ö€Ô݆�´Ó€Î4ÅEwðc cM§Œ†�‘çÉ—!ùa"~@J‡ ÐOœ‡¡¿¥ÝDýYéÃn¡F/”�&P¡ð ´ëÖ ÆÂî!< ¸+8 üðÄ/¼x¼!0gR =à°´«BÛ_à½j!„Ò>ø ®ep9µ™EhÀ9ç)Á@Èçîs¾Ã`„.:é:—ïFêJP‚÷XÐ�΀v8H ¦'½2á�ÈC^ò<@A OxÍkÞ‹Á zÀ| �À@#ôà„x Vè½ p|äók¢0ºÌH i¸ßýn0ŸÏ""ZP‡ÏñˆP©I‚Ø‚¨ï‰‰ Z@E´à XÌbupxñ‹` £u°Ë0À2h¬a %†X a{b¡B}háBDÀ¤`ˆ@!ù ,L•ÿ€‚ƒ„…†‡ˆ‰Š„~~|�| ”•–—”‹š›œ�žŸž�‚H�¥�‘ U˜¬­¨’¢ ²³´ ¥¥ ‘ ¼ ‘‘V­Ã—V»·ÈµÊË¡ÈÈÀÐÑ?ÄÔ”<ÀÎÙŽÌÜËÚÙÑá7«ÕÕØßÎ’Ýëœ�èéá‘7Kõö÷øùK—v‘lï·°±ÈèÀF�úe@ÁÅ�*G–™H±¢Å‹ïí°Ã±Œƒ~ n#è­°Ú`À€ÀGŽcº82³&͘_4h`'Ì„ -!¨ÉIZÎtAªqKeËŸ$Hݱ³‘š.²jÝʵ«×¬4ÿT"µ,Ô–C‘¤úv´“6¥|ÿ<®„µ¬ x£ÜØÉ$C×€ L8ðÖ L$Æ€!J¼AìþdY£èÚjú–†Çu¥âµà˜1(˜¨¦QXðž¯cï™ »vkª™ü©pú4cÇxí†yùçcf͆ÐÁøð²ŒÔ yM÷®@±ê<ØÎ½»÷ïà¹ïy‘ûdžóÔyûnüØB™�vʪ 9£ls'è°³é(Ò1@Ýy�@ªÀDx< ÁƒF(aƒ v7CpÆOH`z½5†BUÎM&[ÈáÇÒO„QÕ Ò¥wž�Š Ä<öèãƒäÂ�6ŠÐ! ªwƒÿX „a�T&ÒwKŠÈä•hUýqÚ€’ðD‘CÊ  –Àã3Œ æšl¶¹¦# à–”’ÇD„‰tÒKk·� [,µÕˆ'>uÖÙ†0ƒ*p Ä_ËÀ‚‚äСپ½l¯ÚƒäL�°ÑÙÎÅѵ,iAs™æ9`ú·Ò�q§‚ ãV‚â¬àÀïÀû^5ãÙÆ0Ãã�s×uÉvæ�aGú9ocõF)H ¿DR€Û‰¨ä½J$�ÀõäƒñÜÝ ø ¾B¡„œ‘C˜{ {à�?üSÀ¦©¾žð€Làï<À@Á�Fˆ FпþÕ¯~886x�¾OnpƒúNã˜È\áä#_‚ò=•Ìì{,!CR¸ƒ„!ApÌiÔ烺ï} Ág@…ûÝHÄAý7Áöî‰Xà ¢¨À2ðŠXô€´(ÁRÀÜbz€‡ûm�ƒTE8ÂÆXá7¸up´|Oø€?€OÜa�w�E öHÈDà�ˆLä!PH=Ö@„$€,€PH9l"!ù ,Q•ÿ€‚ƒ„…†‡ˆ‰Š‡ �Ž��‘ ‹”•–—˜™š|ˆ’žŸ�|£~𧍩§~¬­££ ±²Ž;¯5­¸¦ª»¼—¹¿ ¯V³Äžµ£¿Ê½Ì½ÊÏ ÂÅÓŽV¯|ÏËœÍÜ–¤Ù¿¯(ÔÔ(¯ à¹5èºÝ¯ê¸¯;‘KûüýþÿüãC¯«¯ à‚Ç W‹Wi ²âÀÇŽÅ*þŽhÜȱ£Ç�ûŽð°h Å�*¸�!ª_ìF¥{v‚M4°ÓàÇG�.Ž*ô§F ’&˜ÀtÂM'Euë™K_Ï®áªi³©„¯�&}!Ô…Ù³hÓª]ëâ@Ò¤?ÿ,ûµéÍ¨×Ø€»J \0ª0º2¥k¡p”(W0QLí�Ç�#Kž Ù, &˜™dÁÀùpá¹`™B¨a‘Oƒ|Õ+@òÃ௅-æÌ 6ƒ™™< |`Oïß{‚û>YEn’ÛfÐ9Ja°eHˆª.5!u�[XlpCBôm'¯°aƒ“Ü9¨_Ͼ½û÷¸3c!Q¾üxÛÍ-Üx«Ã)T”{¥–M`8M�Ä[ Ex $W $ÛÉB“*bi­sØbê”PsÀ̸µÐñ‚ÃI ð×òz­ØÌàø°ÿ’-9Ì6Tnƒãª­dËvq€‘¤H_ÃÌ-W]`$`Ç+ 6Ƨ$Ù¡šê®êF²`¬óB¶ã�ÛÃð6¿\ì¿È—9Ì2ƒå˜k 9Û44­•E—ÎÎ}¥I2±‘ÉäIä“ÿì þ /èP�ð»!„J(qÁýT°ÐÁþ‡¤€ ~53Ôì€H B‚2ð� T`=àXð‚0B�ÀA#Œ€#X�:°‚àà(¤‚ ïw�ú Á nðAØGÃ2È(Sw) þ Cݤ)[( Ù—øù†ô« À¿=¡Pü_èA#à�ƒ€´¸tQ‚`œ`/HF Áì Œ@ôÀ�ˆb UHºP ,È�spá�¡±KÉg�BÂC|†D !ù ,W•ÿ€‚ƒ„…†‡ˆ‰Š… �Ž��‘Ž‹”•–—˜™š|œ’Ÿ Ÿœœ~~š©ª«©§®§£�¡³³±|¯¹¨¬¼½—ºº¤;´Å‘U¤|À̾ÎÎÌÀ5É?ÆÖ (ÉHѺ±Ïß—¤¸Ü¹ ¤vU×´VÉiä¹â°àôƒ°¤ ï¯É7ŽK H0à‚ÉLé;¥€T‹\õ ½B’Œ�>oØÙhçÀ# CŠI2¤FŽe ¨ÄHŽ"©mÝ"ªbÖ�ÓC]UªœÀL‚@Ü( ÒÅ£H�’Ì´ÁŽ-$ðä©KWð‘“ù+ZVNîüäÜÉ3jÔ ,èhÚ pÿãÊ�;÷S&@™ ‰’ÖB³Q§ê„Q“‚w\)µ<—ÂTÀ}£DÁ@™�&˜3³8À¹³çÏ�׼Ȍ٠ƒÓ”)KNû×ì0íÀDœØÐE(ÍFžŒáôé À+d �9‹{$_¾ç�òÖä ÎÄʆ Á�ûf š¯ (‚¦Y ƒvmAä`ìltGZÞÛƒ_ß@¢þ"˜äÀ?@Ž5< à€3H×_úe ÂOÔGÂ|Øi‡z4u…T�·Õyã䢞cem�PVôö[óÙ÷„,ŠgÐpàŒ4ÖÈ_N¼¨c‹ Ö7_p ”1¢{ß–¡UÌHq^ÿ'¯|XVTi•ÑfÈG ²¨#2ti—S¼`ã˜ýý×Å—hv)ÃŽ,6øàc�Vâj­QeUy®p0JbÉ<ääºI†A¤epåŠZréå—]4jÀ£Ì�CPZ‚ —fúÇ¥t°Æ.@j@£g¦¹æ‹m>ñGfUNè�‘+�Ò‚83½“F2|´b “ýöCfŒ�è‹‹šà(¤.€¦Â”àì³Ïæà© ‚¤¤~Ù¥ŽgÈ¡«iÁ �0É,³, ±A.•¨ïUÆp^ä‡ :.z¬Év6à¿*h ÂÀ¬ÁÁLí¿Îuê¨�j+ä7úø-ÿw«™µnv�rع®`" G  ¯ '^GÂpý!š] ë/ÀÏ`óÍ6ä¬sÎ7ߌðÂzöpÄk èÄ‚>J¨š_aüÄQz&C…Bò§òŠÓñ÷™1?Ú/t¬Î:Ç öÚl³½³Ï ÿëð£øõ‡/ 6x�ÒQH ÔF hQÛ‡eØÑÔ z¤l‹uóGƒÌœ•}0Ú6° Àå˜gžyÛ:ÛwМ@1fœÚæ›Úé^SdƒÔ;­ÕPhMß° °pàüÎü€Ù6çl9+¿ÂñÈ'�<ækw>Ãç ÓPBS˜°-ÞnFˆfA1¡ƒ�¯§‚ÑÖøãWåØY“añÂú9¼à–J\ ?ôŸpBø‡ÐüS0Âÿ#Àƒ3§<ð€!p@¨À:Ðð€'#TÐ4‚Wà€P Ä�ýN@?*\@9H¡ ±P�ÓH¦5²Ó`È÷:~H'�‘@‚ dA…*d� â'¿ ”p=èA’øÁþñoF€"0XAxÀŠÈóÈENð‹4‚2ˆAô@‚Fè_EHB*ì�Jì :À5¸ÁxÄØa8•#‘g|�!ù ,]•ÿ€‚ƒ„…†‡ˆ‰Š… �Ž��‘Ž‹”•–—˜™˜~œ |Ÿ|’£¤� |œ«š­®¯­«²œ§ ¢¥¹�7¨ s³À~°ÃÄ›ÁÁ-¨|7<º£U¼  ÇÕÅר|HÕÇɨv?Î� Ê-ÜÁ¨Øì— èÁÊ| ?UÎ;õçò³nÉjG�Ð@iÿ€E(÷ÉŽC;72TYB±¢• 7Ê=´cÏ_BNlPEVðZ06 ùx<£%„—/“¤Ùè°�Í›8s>¼f˜0[Vû€ÐZIW܈~J0Ë%LŸ>%H•$ÌŽœX³ÚÜ¡ÃB�©`¡þ Ã’”+�­$%<Oÿ£N b¡®…(x1èÕqƒI&€ ŒÂŠÞÃðF±û5¬OÚû¸–­¼l™Ön^½ B‡®@šô+9 þóÊ—Ò°E‡FŒ·nã! ¶€ T^åDŸâ±|I&�›? Âº´ëî»í®›®¢��%áæ‚Æ"û/䔯/I;휗|(Á#þÅÄ PTàí"€€ïÿ°,”Ëå¹誂»3„,² $—L²È"»«‚®ôngÈP¦ýzÑ'`7•!Õc-µ§°A�Â_3‘Á”W¨°¬a.º¸~¬ÁÈ%Ç`õÕXcmrÊñòz % KŒdÒL/¨6Ä�æýÃorÖ$^õ ö # Sl µºíRmÖnøá‡g]rÈ]ãzÀa;ÝÙ2ƒà«=nêfÁ•Á%—“øA‘v`0ÁB€²š@«Gø $À ³¯`ûí¸ßnøÕ‹ÏÐøÌ@C½“› Ã4¸*Äš.¶s�­´ÔyTŸG óED{2àƒn¸!„ðÐÁùè÷`ìã@Áûï�0‚ôa¸x ¿ôïÿ!p@Àÿ�ûK êÇ@#ÀÏ=ˆ {0ƒPáT‚„¾ï…& ÛkŒj`½<$¡`Ò{›ôþ Xï„/‘KQ5ˆ�9xAv¸Cȃ4æ‚Àˆ{H¢®Þ%8ŒÀ‰ò‹¢æG�À~íkß ¶xô}ÈAY`!˜±ƒœ ^¶¤$”Є)ìY !ù ,c•ÿ€‚ƒ„…†‡ˆ‰Š†|�|ƒ ‘’ƒvŽ�‹™š›œ�ž�~¡¢¡H–—§¨©| £®~Ÿ±²³±¯¶¢5 ª»Ž -·À¡´ÃÄžÁÇ~ ¼¨i¿ÈÀ¦ÅÓÔŽlÐÁH-˪ -ØÙ·—¢Ô離l¦|ãñòÙÝ«¶êø„¶—5ó0BH° Á€Çñsä/Z>bâ€ÕKq”À‚2jÌ(¡£Ç� 7j4 +ºÁCöp˜”`5.ÁˆQ#H A‚XØÉ³§ÏŸ;ƒÜ”°±àÄŠ·ÚajÉÉZ+`øØ™Ú¦G�<£hÅÀ•+ƒ¯`ÊÛµ«Ö(<…~,3uj “Àÿj¸[ÊtÑ©ga T0µA‚!²Fé*¶‚áÇ7(^̱c±eµZÐÑ rƒ2  ŦÀ©?­êÅaî»—z!ØLÂÄ2=^Á"f¼�„mÛOrëÞ½ûöíÆˆ¿b€Òºò 3—„Q£^£kèDrÅÆ¹`8vÄz¥2&e$V|[·ˆóçA¨_Ͼýzôèsÿ^ìå»ý,$#ï8� [;—|p�h¶HáY[v4€Nl…V|gÅb¸={2d¨¡ vèá‡fØ^|O�ðƒ}L@QYùítÅ ˜ÀS¯h‹^ôeÙCÄvØNT˜ÞzvØÅ‘H äÿ’L*‰$’ ЍÞyHH‚b†�Å –UfG,7`K¯¤–Ñ0vùGx†‘G‚…CiB’LºàÂxæ©çžØé“Pv(¥ˆ –c ð]—;¦ c‚" }TÚG Áè¥�E àŠÔ–[œ2ÙE�|> êª¬¶Êêžv.¨” œ÷Ä'¢ø]EìÄ_˜%“‚¥}p:Äö1À�i·Ó`:¼ +!‘¥šðG(yçx>PÈ*”«Á¹è¦{n¹®> çŸÌ*fÐÀ´7@Á@~hy,¤· �ì²®|b¦G ö•¹Úwod;ç’w†Ëªÿ èΠñÆ6tìqÇoŒ® ­¾ëd&ao,3qo:ø°â¾-ª•@ÒÜQƒ>V°9|ÇòÐ9¬qª·y^|.ÇÇàôÓPCý±È뾊çŸkä0ôÖdP"–3·¸ßÍ¢™9ÁÎ[}Õ&nhÍ5Ë4¸k1¹KkÜôÓä­÷Þ{Gí±ÆU¯ªB%¼À k´aë•d¹/Z6C]šžÏjû,jzk¼ðvá°@2ÝØmÔy¯À ¬·îºëz?ý÷ ç®ÑC ¸^øÐk˜1o­%^é8Wýõo,ÑÄAÌ3ŸNA(Ì€>¸á†J(qÁöPAÅ àã0B¶=¬P~ë¬àA‘·x ¿Ôoý!8Bþùßï?ýó  h �8H Àç=*p/{B°õ¾…œ€! t°$‡�?$O/)hóÈ`¹œDOzâ¡Þ¬w=!¨A JÁ²–ƒ„ †6´av¸†ì¡UébZÇF`ƒñˆF�ûðÇ¿ýí¯!è@TÀ@ïu�{€ "èêù€,ZÉ §D˜‡lðƒ!ù ,i–ÿ€‚ƒ„…†‡ˆ‰Š…~�Ž��‘‘‹”•–—˜™—’œ�žŸ~𢣤£ §¨©Ž¥¬­£|°ª³´�°±�®»»�¸µÃ©-¸|’¼Ë•l²‘H ¸ lÄÖ�Ò° ŸÌÞ…|Áœ5Ç©0èéëìíîéé�lÚ| Hò·áßËÇ Ï‘Æø´ˆ¤®Ý„ƒJXȰ¡Ã„ÝA@÷á˜0N~ÛÇJ×±mmÕðƒÎ B‡‚±À²¥Ë—0YA)!a ;vZ ‹ÄAÁÇp¾8nz”í§9G%×�d¸²e”§¢Fe@µªÕ«U¥J}¥åÌ…aÊD\I¾~!W ¥$‰MšŸ ÿ(UÈÐi©W+èÝ»wƒß¿€ù ¾ªõ©Ì†[ÊàĉëC5Nk}Š m1NWÚ�Z•/à $B‡~Bº´iÓ¢Eæk5êS.?Èn°øÝ"C‹b;³e¿ÐÁ™j_¿¢K‹X¾„óçУ?gΜ´ê¿{`AÁ$¸ìW’ÅÝI÷?I0æNrÃ{&/¬èý;ú uè2òë7Á¿¿ÿÿúå]uOˆfÅ L$¨à{V°Ä�xAY'éA@—,造‚ þñƒ¤5÷Ü~ýua≤¨âŠ)žx"€:ç pØaz¸ÖÕWîÉ„ÍUT0�Á6&øGÿ´A¢ (®è‚ Tiå•X0¥ +¾h,¼À˜€$dàEv ¸æ`M�5‰(’ÐÇ�w€ž… y—qóY‘C‚c:fkœÑ…”Y>àè£�F )–TªÐA†fʤ’à—^T¹iÁB=Fb'ž}èYÞy�@ª}¼ñH…t±tW‘ Ìš}D`š©¡9аÆU⨠Èj ì²Ì*‹ì£*¬ÑC%PBµ¿Ò@„ Î-×é§„j؃r:R¬t°ª&´ú‰«®$„èœ gÐ˜éµø–B1¬±ì lÃÀ,p Ó†�ïÂ×ÐA¢]𣷡mjÿ›ìHjœè˜×®f·Šœ}"Ì+]¨@Cµ 3Œoûö1Ôls +ô°B »ìòÃShÙbÄ&Ll¸â¾) æ ‰!T"�&âÉP.j@•kPëóÖ\w}-¿*x+ݳbWÉ¥es ÂÙž^ìæÆHÜq»ðTÈÎIä!z¤WåÃén!„J\à:Tœ û 8ÔNÁí·�0‚¼ó>³À; üðÄÂðÇ?¼ï<ð½Goî·×^ûì°»~ëB¸áÆé\qié¤'‘P;� ÒyAr úûaDÔÆ�îƒ÷© ¡ÆþJ€ =”T€œNpÙíá€{x@›%°‚Ù#€ w7 T�zÕ³ÞõfwØQA{®c�Tç=ûU% _D±c}‚;ukui-biometric-auth/images/icon/0000775000175000017500000000000015167732630015576 5ustar fengfengukui-biometric-auth/images/icon/FingerPrint.png0000664000175000017500000000152015167732630020531 0ustar fengfeng‰PNG  IHDRÄé…cIDATH‰•Ö[ˆVUðßÑñj:L1^šÌ²AJ�23š2‹P¨°‡ §�"›‡®AEIAÒå¡0ºPRtaÊ Q‘N¡�•�==h>ôÒUôßÃÙÓ|3~~³àÀ>k¯½þg­½Ö�JI2²\ˆµ8sÑ�I#føðvâ{¨ªjŒ¿±ocA¦áQœ�7ð)¾Á‘Ó%èÇzœ„�88¤©$‘dj’3˺ñ™QžŽqú¥Iæ6d¡­HFd²:U}¸sJ4ÁoØ‹Øÿ¿Ó D"ÉÊ$»“\ž¤'É…ã¾~M’­Iv&Ù<¢ŸH$ëðŒú^žÃ|\�ÕèÀŸØ…ÁÝ ¦` ªªÛé˸CxËKZ¾Åßè*º‹ð1³XTUÕ%í¤«3É©%ük’,åzO’þ&å|u’¾$ ’œV àºã#Ô K’|–d~’ÕI¾HÒ�äÚ$$y+Éë `Û à²$»Æû›Ô D}™¿ã Ôú+f«‹à^ü…íÅ~?.P3Âí‚,VÓœ‚ݘ‡Ô•tnÄŒ¼'ûí‚ìUóÕLLWwý]Xª.–-,W÷ÇÑröÐxg­@ÞV÷ÁËx¿|ñÙø'`Fûešš‘áßvAºð„šÂÆ�ø\ÝåýF™x%†K#¾ŽñÙÑäÜP¼Wt[°·©Sw©:MÃXe4]SÛ™‰ÇËz�”õíø¨è6á±¢?lôâ[ø+I&'™ÝнINO2«¼ß�dSÃþâÒKç5cáV ÊZSm(ÉŠ¢ß˜d_R ’\_ôI~J²¥]�IÞIòR’; et$¹?Éžâ|dz~�äÕ$s IC+­r–šðÎ(6 ±AÝo³“ñ%~ÁVœ‹'±}"?Ô•t1¾*Î7¨K¸R—qOqü:Ñ‹=UUqJÝ¢Îo€é£~¤ö¾&®^r·ú�Ú©V� ¶©KßýH¨½êVµã?н#òz£NM’²zPízÄâEïŠ:å|®Ièô¿+©¶�@k<ßÎ?ÖÀ¬:€…Àß9É\`zxn}�™À«€ÀoÀ݈= ”�à<° ¸P Ú ì¾ÊI†7€«˜ ¼ Öß× Eú£�À à °ø9âíÀSÀÅœ$·¼è}à/àOàƒ:K’ÛËÀjà{`*°ø4”’ñ³À~àwà}  ØžÄo„O抜³ñõ¯Éö9³è€êyõÝx^¤®+tÍ2Ø=uU{EÝœ<¢UÛónQO©KÐõÍÉ«mvÄJê¦xÙÿ±zX-oÐY(¸E}!ÆSÕ�ê5HÎ&9Ÿ«¯ê|¨nhÆ+ ›YŠÍ˜ ̪³éåzÝÖ|[º�^à™$xãÓ ŠäíÚDv®®$±fàkà³°3 múà20!Æû€#5î]1<‘�> "S„Íéú­QOª­Ñ GÔç"Ö¢®U¯„PG&¹_ªóbó&Ùé¾ ì––©–U·#òfE�ÖàÍF©_X­kEï \ý_¢Çaÿ§-3²?ŽIEND®B`‚ukui-biometric-auth/images/icon/Other.png0000664000175000017500000000037415167732630017371 0ustar fengfeng‰PNG  IHDRÄé…cÃIDATH‰íÖ1JÄ@àoB"¸…�,*fOä�,ÄF°ð–Á3x;k‹uÁÖ5ð[$°V6aÀ"? <¦xßóà•$/x5æ7æ¥ÇíT¯p"Éc•Î*ÉSƒã™/ÿ+k5ØUDìJ’5¶•�§%I¥þ‡4Õ…ù—H‹+t�Ï’úø­5Ž~©ˆ Ë0.H]ä²bÿ}ƒûŠÈ|UDöØ·Æf3]xŸÙ¸ÃùTopV’<;,[\ÏDzÜý¿³>uc«GNãIEND®B`‚ukui-biometric-auth/images/icon/VoicePrint.png0000664000175000017500000000074215167732630020371 0ustar fengfeng‰PNG  IHDRÄé…c©IDATH‰ÝÕ1hAÆñŸ1b &äEDÒ(j: m-´Q!…ba;AÄN0•�$­•µ ‚h!¢ÚXˆv"˜€"#´Ÿa,n–Çí‹„œ…,ÜÞ|7ÿ�Ù½;þED=GĵˆËî­ËÈx‹èà¶UI=¦#âYDŒ´QI­x�sëUH^b²mÈ~¶ Ù€h²ݶ!‹Ø×6ä¾à¢ªu½šÂ©Ur_À®~�_XÀ±‚ç`DùžTµ}²ÙƒÓ˜ÁJvÿvboèjߊ3éúSò])AŽâ¦ùxªèlZù·4ïf×ãÆù,ÏF|/Aöã^6ŸÃ6¼U½?ƒYìG\Çg|ìMV›÷âHJÐIe?iðõSÑS.c OU›9‡÷™oÅê*z±;%žVõ·I£ª¾7}"ÅFK�z3—û`_1�¡žU§ggÓb;M�eÜê :e]¼ÆlI !ìH±ÇØ„çÙs¿ÑYë�h&".EÄöˆ˜*xîGÄDDÿ›SÓ¤¥Ô…%Ü.xÞ©öéîZ!4ÓrÝT½õÿFv*¥º"¬EIEND®B`‚ukui-biometric-auth/images/icon/Face.png0000664000175000017500000000155215167732630017145 0ustar fengfeng‰PNG  IHDRÄé…c1IDATH‰•Ö[ˆ–Uàç·q<§„©•¤hI˜¤åŒ±ƒ‘”” ]tQA¤D`w•Þ$AÝEYARIV&eE‡É̂Ԥ”Ȧ̷‹½'?ÿùGÇ›o³÷Úëð®w¯ýµ4$‰6™‚;1#Ñ]×OCöb-v´„V«5p1IsÌOòA’uI®M2²mz’Ç’ìKrKÛ^§€8ŸdK’å�µ I¦5æ“êü†$ß'Y0˜“®Îî,Æ—x¾B3×ã ¼„Ë1½î¿†Óñ6Wè~ÁV…ã@kxŸ£=ø—a^ÇŘ��˜Œ±øªê®Äg¸ùD5™›ä½$³’¬Jòh’V’…IzªÎØ S+É’$“L­{›“,;\-<„WðMÍ`7R³x·êý�#˜Z3ëªÐŒ¯ß½M£ÃÚœLV¨º ËpS5´³p&æãBœ�E˜Y¡\ƒƒx+šFÛ3�}øob~«FfVÃgá¦á0>Á§x«ÚØ]ÔI†cL#ím؉kðjC÷GìÇ·Ud]ÓŽP»“C8[�è_œW#ž¢Ðt¸R·£˜XÇáªsÞ©ç�³Ûîd¥Rä/0—àOŒ®ŽwÕH¯{Ôb÷Ôl)Ð=¬ÀÛÛÉÉl¬Æª &âüPÏü�=Ø^�ö*õ„÷ñ!nÃã dW–Ôù~œ£`ÝU³ØS¿?ãkÇ.ó”† ìGƒkž«F6*lº_iýìj)õºÿ(´^Š0W!ÈL<Ño´S[éçü.…–£ðn¬ÐôG¹ß)õë®ÎîR`^…Ciõ$Ù™dF£õϪóaI–6t¬ÏœSé°®F¿HÁ{¹Ò]ŸU.Û•Ê ß‹[ëúÎN†Ú ß”¿p·Bësñ†Bß+”VHém÷(]wý l“N¯[’Û“<™dDãuì®Û¸$Û97¤Lú¥K!H_ÍŽrO*0PzÜ r2'£pŸòÊu’JC¼wÁiKw^’�“<=uÌ©oüŠSù‘¸:ÉúJßGNâ \•äí$›’¬Mù»ù¿´_Æ5X€-xYaÍPe4®Sºñ¥ØÞjµVÃR\»Q|pIEND®B`‚ukui-biometric-auth/images/icon/FingerVein.png0000664000175000017500000000112015167732630020332 0ustar fengfeng‰PNG  IHDRÄé…cIDATH‰­ÕMˆŽQðß;ŒaIjb²P¾ËÇJJÙ‘4“XØX*Y�”¤‘�-iÆÇNÉd¡„DM’² „”­ò5ÊŒFMŽÅ½SÏÌû¼Ï¼oüëö<çÜçþÿ÷ÜsÏyj "ŠæNô¢mÙ÷ßqï'>¬Õju\õžz‘‹Ø„Ǹ‡ÑìïÆlÆ% 4iˆˆh‹ˆ¾ˆè�ˆy¡ÁXÏ"âà”è›9w*È‹£;"žGÄŠVEîGÄêѬlw4:WʸÚÊœñ®`·ã8–6øþ&æ—MÌœF¤ˆÑ<ÖæQà ~æùo…÷I¨Š¤,‹¿p [±7°·0_zµª")ÛÀ8à\¶×àwÇ´"eø*àÞ6³¨ê¸Êð;ZåkUdÛ¥›Ô›}sq6‹·*RœëÆ>œÀ.|À)ñèÀKéš×¡*'ÃXœ‰>e¡x•#š“ÅaŸ1»ÕHàÞHE8ˆ¾<·«p =X’ýã|õˆˆÓÑ•[Æœˆx�Ù~ÛJZKWÕq�HÇ$ïv¡”àAœÁ‹²½•5›øÆÃü܂ΊµM‹1Œ.<Á©(K“ü/"7¤«Kªø›&WþÂJÜ•úUKh¶w-Ç2¬ÇI©÷K8-š�dƒTáWq¯q^ª—iQɬÂû#Œa?á²”—©ë;Z)þåÆòóVÁ÷£dMiƒü ”z ‘(ût�IEND®B`‚ukui-biometric-auth/images/FingerPrint.gif0000664000175000017500000006105315167732630017571 0ustar fengfengGIF89a  æáâä0r©‰Õø•Ûùüüüêêìóýÿ°ÉÝ‘åýÚÛÝëûÿãùÿvËõ\›�äÌñþÛöÿQË÷kÅóŠÏÓôþf¨ §îÂîý}Ê»ëý)“ÎÀÔå`’¼v»i®Õ¡áúP§Ö©äû�³Ñ6£è´éü«ÔèvÙúC«ê\¼ñPˆ¶T·îÆñþùþÿc¿ïÄÅÊ&˜ä ¾×/†¼M²íeÓù¹ñþàêòÐß뀩Ê7ŸÚÜùÿ#¥éÌÍѰçü8Æ÷G˜È„Èè7¹ñtÀä–ÇÙ©ìþŸêþ!¹ô‚ºÚjÁç›ÎæÕëõÐÑÕF¾ñpžÃÔ÷ÿ:±íšÕï~º@}¯n°‚àü,°ï¬àõÄÓÚl§âòùt¯c¡^ Úäíêïò�ä¾àï~Èâ·Ýï�­Ç€ž¹Ðö°ïþ™¶ÎÀè÷ìõù åû p¯®ïU°ß¿ÄɺÈζåøððñðõùøøøÈÉÎôôõÔÕØÌöÿŒ°Í g¢ãèí�ÐîÉâïR•ÁÂÇÿÿÿÿÿÿ!ÿ NETSCAPE2.0!ÿ XMP DataXMP ÿþýüûúùø÷öõôóòñðïîíìëêéèçæåäãâáàßÞÝÜÛÚÙØ×ÖÕÔÓÒÑÐÏÎÍÌËÊÉÈÇÆÅÄÃÂÁÀ¿¾½¼»º¹¸·¶µ´³²±°¯®­¬«ª©¨§¦¥¤£¢¡ Ÿž�œ›š™˜—–•”“’‘��Ž�Œ‹Š‰ˆ‡†…„ƒ‚�€~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!  !ù ,  ÿ€}‚ƒ„…††J~Š‹Œ�Ž��‘’“”••‡˜™š›š‰–Ÿ ¡¢£Œœ¦§¨}ž¤¬­® ©±²„«¯¶··Jº»¼½¾º;ƒ.„¸ÅÆÇÈŽpƒJÄÉÏÐÑ Ë‚ÍƒÒØÙÚ~ÔªÎÛàá·ÝÖ‚âçè£äßéíî�ë×ïóôñæô“tp ¿½ øÁ¡ƒÏ’½>íK0gV¡9á$„ÇŒÝ;”s¸I ‰¹U”çc�ae¹¨S€@Áƒî (A©iŽG�prêܹ�Ÿ’†›V‚|󜜛v$(0”œ ‚erÀe»¢ÛhÌ4ç£ÕcÐDT VlZÇÒ* g�@ÿ Í)+î,4ŒR yü*îh\B šf³ûŒ€ZˆméÉT ág˜Ñ�˜V� ¾ƒGÞCëÂÅä�ŠÔéÓØ±f„ÚØ‚~Ô²îéÕ°¡=ŽMÛÕìÚ¸EÝÎÍ»�] z7’““Ÿñãá$Î\ÑÓ:Oí¨ó±ym8£Sê°Ü:>9ÙµcRÚÝ»ãà‹ÔÚ¡$ rãºL)ùlkC‘2[Jð�…ê SU}ÑEÈ‹ È€¯È@^…P…�· ÞP‚Ý‚×!sQˆ‹Ñ©’á3pˆeHzŠ……ì0¢4•B•Фè'`;Z!’"��a;”‡Ž?îÐ�’Ðñÿi  }H2Ââ s¼HÉ[ýüÓL�b!¥E)åX;ìØ#T?žâQkŸØ¸ ˜ ‚ž%„'ÞRŸL)ÈœH*˜%(ž ™äX|ªèç ‰Br” }ÌA]r<@KR‡•‹ÈñW£õÑ�(%1F¸”™g2„‰†>B$!Pz'Ǩ“ÀuK¶” Š’¼:H¬ÍÙYÇ$àÉÅ`1¤Ùa$†"$s‹ª2 ‡‹L²†XÛˆ¨ÌPèçe’t3H¨"ûã­2B!œò¦$°ŠD&c»`¹©™H¹�.œò­ÂìH@ÏÂé‡5až30£�B@W¾=õÞqL\Iÿ3Ã6\ å:Òï)+q' ›OrÒ¾�è)KW÷ jÉ6&Ü+¤¨¸ ·/üq™tî9ñqþh"!%âæ広ðüIu–Ðq)&UR!¼<>LeËÛ"‡L‡´ë£0-«è&Ê¡í t®& ‚ %³vÛ°¸27òuú³pô*mÜ<ÆUË#þ�6(6º¶y“퇛Fkcµ #Ù웑Dù]Ø’ ‰¸y3×ïfN~/(ÿåÔq#qål£àŠNõؾi¤ÖT7mÁr°Ëãçfæ>ߌh•f‹Š32Gg}¨Î0�q¯ˆ�kon¯Ðµ+ÒÖ0.Dâ» ‡óÖ ¸� -ÿ°_Êâ|#øE^ã½Ùh4ô)«G(É.yþ"ÖäÜMôÒDµÿ�ˆKÌô±>TÏ;�D\Š—›ïIbQàkÄÇV j�Íd$y„û(Ô¯÷-Ïw»ß¶Ö3‰~YI| $P9¨ª�gGt`ˆ2`%‰~��&Ý£�³´GˆÓ=¢é‚_å~' U�6û WÒX³G´0ä¨á­Ó¯ËylŠ¡è†Ÿ‡EuQI‰Õ¨� ‹HÄG`dZn¡e$aG£>+”D=6Œ–Eщƒ°MG®¦œ¤#ʱEFÜÑM `å¸Hïà�‘‚ÈТX·ˆCÚ.�ƒl$$ÂÓ¹Õ´±ÿ�tc¡ˆIFl/{ŠŒ¤)g�O.‚Ÿ_!+YJF„Ò·|ĽãJç,ñЬ¤È(¨ÉFô2^eleÙE?ä…S–lDx€uL?ìÒ:¼�‡óF0J ×4æ2�É$ƒAP—ã*a-ÎRŒS‚ÉŒ’è@•—Úu0í\D5óI# i{}(?‘Lwnœñ¤6·*Rb ~˜&$ª¹(ö1çQ$Äãø(‘HbªòÕŒf}J%ˆ³yÑ2äD‘"X®Ñ›”dN‰2eRFl�¹ÓFTõ´æq*!¨s:—®Gq§Ì¡J#‘MïØ‰§ ôŽÏ|b»æÜ’@rÈS\Yb`~þ4Šr¸à¾úõUòü#àøêtOÖ˜Êðf ;qˆÒÖƒý@‡ï–ó¡ŽD¡juˆ¥°—G•e†ƒw¦Îon·@º `A›­<ÉUnmœh4‘B8Ae·›2²0ŠGØJ`Ô³ìM¥2¼’žXoÊeÛ¼ò”¶‚6'´‹oOl¯þª'7ö¤)…á%Ó°M¡˜’‚'Ýüè˳} =ô‹ˆ„84¼0)Š•çC¯ØÉ-iœ!�&BMúÑz ‘›]€Ý*ÃÖJ¦Ìk 'qhÓ˜T0�jd90©öq¶²*»‚Ȇ´uz´™l¢ .Sààhn”™nç .. ÿÈ –åCv§V�(Dí/m`bѪIŸ+7=MÀzuº4+®­ qb:` ©gA;bzÏ@òä’*:]îƒæälÜhXFü�‡ªbkq�;6Ù†ÉÂÃ�æà«™°Gö—9ˆ[§Ì�XÅ ;[¦àÖ~7hìJ=Ãö»&ßFÆñ¡²ºå¢E †ÆÊçQÀ czó™ÇÌÝÑæd$ÜÞíØy:ÜJêdüûªÉ9>òâòhDz²W:=ìsVÔ %•¹ÔYžrcçâ·z¬Ñ!ö±G½ßf§GÙÓ®ò­³�ìnûÙ !ww¬½îÓÚ²Þõ.žC4wÅ}<-ä.øÂÿýÁ…üá ¬¥Æ÷‚�!ù ,—ÿ€‚ƒ„…†, Œ ”+$$<¼ŽçG8YïDÆ’Û:!› #`JïÒèQ‹†p;re\s̨\r*¢à2 äÐDvXB e AÄ…d8Å&th F bK”ĉ@P¡¢,êàÅ‹/: ãŒ3b@ã�X�£<ò¸Æ�k!d=Y䈀bý‡N‘á…C QÆ„+Ø`X:" RÁ0÷‡H„Èœ‚d*³ ƒZ:‚%–<è&„VZ™K.ÖYÆ�Få…fè§“Mnèç“|ê)å�uRYe•V¾¹f–Zž¹L™bÖ…Ü¥˜fªé¦œvzŒ ˆpà Q”jê©¥Ž Ã5xêê«®Ú B ðaë­¸æªë­Qp ‚ °+,2~„šB»&«l² ¤ðë°Ðë ,kíµÉâqC ~Dë-¦0¤€-Q¨ºÁ¹è¦»Á£¦ŸLpñí¼÷ÔÀ²ÊÀÄ\ZäZ€ôlH³æ»o¯ü.³Lk0!�!ù ,—ÿ€‚ƒ„…†~‰Š‹Œ�Ž��‘’“”�‡—˜™š†•��, ¡£¤¥¦¡¡žª‹›­®˜}J«�¢¦ ·¸¹º»¼¦£ ³’¯Ã­}ƲÁ ¥º ÍÍ99ÒÓÔÕÖÒ9Îͺ§,Á¬ÄáœÉ,¤¹ÎÑÓMìíïðñòòííMÔÙθ¥ÀÁâÿ«”�ÂåL�»x+^XÈðB†‡#6d˜0a¼zÓò-Ø÷Ë›§á<•x«™A W0Œ˜�„K—véå†à`ß�¢ñÅÕt ¦dlŒ9 e&RÆH%T0}æ`–d°Áe—î½à矀ê§{_†y™fYØJ2¹"�orà”s>´`WŽ&A{>NðÂ#œê¨‚–úé¨#¼Pa§lˆ(@¢ƒõ—¦šd©è&H¨dNI94Ñ„*Ñ@CCa,ÈN1… ÌÎàlKPáÅ´ÔV«Ãµ×Vë…Üvëí·à:`Á¸ä–kîEô nìFଳÌ*;²Æ1D®`‡M@£Q.ü„òGmp—«®$Å ¾þºoEKC hÃ’SHá¡È" ¯²Ì†l»ÎJÐîÉìöÁº*Ÿü¬¶Ójà3tl,öÞ[¾ù껯¯þjpÀ¨ )'àÁÇÒLó Dí Q4Ý4ÔRgý V/ÍA ZS]óqCØhg¢ôÒQl�ö?0¬½4Øo×=È |àá¶Ýp/}6ßvÇC€ƒTC „.H !ù ,—"ÿ€‚ƒ„…†‡ˆ‰Šƒ~�Ž��‘‘‹”•–—˜™˜’œ�žŸ~𢣤¤ §¨©�¥¬­šª°±±®´µ²·¸°µ»›¹¾¿§¼Â†ÀÅÆŸÃ»ÇË̒ɬÍÑÒŽÏ™Ó�,ÙÚÜÝÞßÚÚ×�Õ–ËÛß ê_%F7Q1ñóòõï0%Iê ßÜÙÌåËæmŸº Âñ`‹Ã‡¶Dœ(±âÇ1| ƒÐ ?oÿ|$v‹ 7ƒä€Ð·š aÊœI³¦Í j4†��#å‚} Yà)(–IûRBX aáM™R¢J�J•êÓ Y<|¡À´gGuÝB¦"ªŠE·¤ ˜6¡@Áé̪Qÿ¡Ä`"È�»xóþB×G ¸Qgf}ÖëÒ”@ ˆ5ò”Ù“ ®„°–ƒ0> T,%FÝ!B‡ø@º´éÓ¤C?ùBg)byð 0Ó¯w*õë1ÒÈ*—²¥}ƃΞƒ 8= ¹óçУ/_NLkÎP¡edf@¡ àÁ�›vØé‘Ÿ¢ ª©'D+í´Ôžª‚ª¬2à§}�¡u!Pzè•Yž—#ù:™†;›Í¹ "œÌÖù¬ ÓŽ ï¾üö;´¥¦ŠÂªG–èªÎ•6븷֖빊¥ ™˜ìQ8iÿhô ï²ÍŽŠo´ý¾ òÈ$�ܯ´¤ ¼gÁÚœpj´ c–‹¢KJ8áYM4a‡Œ4ÐPÆD§‘L¡´ L›0ÃÓD õT/„NP¡µ\ëàÅׄ-öØd‹ýõÙ^è°ÆÚZSÄÛ@,ÑÃRKýôÓM+�4DAtA¯`‡MäàUxâ……ómü�³o�dxσÿ¼BÐB=DßG#­ôÒMßýtÝSW ÷Ûm¯­úÚ¬aÁë°¿^Äì´ÑÃí¸“ÁÝy¾wßNƒŒƒ÷løá•Mu4ÚÊÜÀDÔWO} 7Üp@ Îwï½ÑGуä—oþùåGÁ Ü{ïþ0~À�è×oÿùx0aÃûü³BÀô»ŸÈ#ÿyštvƒÏ• 0�z ;¶ …¿€L¸paÀ€›�Mëõ(P>7XL4·•V,0°(PÛ70á /ˆ}!ƒéÓ¨I� š0ⱌìI�%¦S�•O±ˆYÔkg ŸWŒF��„qã<’+_¾üøñÔ«W <¶qѦ’é厴;ïæ|ý,\ôéãÊC¨Wÿ¡½û÷ðݯ_ŸüùiÑ­P»öº�ÛÑl×HwôžX VÞy$$7_|D(á„V8@|Ðǃq÷]�ß_ŠAПMè“%ÝÕ‚ã=°`q òÀÞ{ `ã�8æ¨ã�ÂG‡¦y(�~ Õv¿Ð¡Äÿ%)È"yæÁ(ãŒíM˜#Xf‰8à Á_† f—lH�%8Røžzõ)$‘!ùßd†4¹" ºeŒTZyã™ *``衈&Šè8”yfš®†$ùaœ ø—Ýdv.𤞥7%�þ™e  HpÂ—Š¶êj¢Œ¶À@–�^Ø›@¾ù™’8çT�~*œi|ºçç©�J ì …¾êì³€‰Â¬Xòé­“rˆŸ`(––¦›,žÀ½Ø`Ÿ¥ €,#(Û¯N0Á /Œ`ï½öÒûB³ÎNpµhÚ(¡|mfà!·EЍ©Gã&¸ r3Jh*ªÌbpÿ (¨Ào´õâëñÇ#œ òûÆû/­ Œí†–rëm¯%Šë�§äBIì¨U012l¬ÂÏ/Ú1¾úmôÐöŠ|¸:(«œ!¥¬¯ ³RSM3‡Õ„zÒ`Ü!¤a6N!€ &�‘¬(è0�sÏ­ƒNŒà…#è ¯¼àÀà„>¸ˆ#®Ãâ‹S¸á‡/Á ”ÏÀ6ÛSL�Àæi1Äe”Aƒ‡vØÑX½úgÛÖúÁ:Q½�ÕÄ× Ñ@CèŸAD›#�ù—›@¹:$ž8K¡¼T4OãÅ'îÀãÓWo�d¯}ökt_D÷¬~Ò÷kôÁù“S~ùï½ëþ¹è¶—n:X±%ÓÖuÂúþLmU Ra€H@P`/ô fÇÀÙÙ�ò+kjw4vXAíðƒ,¨¡Pƒ…@?µŒ()ýÃÎöG§Cˆ@#´HA\è„Î"i!Oâ�[àá:4D¨Q <Ì0ˆÜà‚,jÁ„"±0°avòDglÀ†?¼„ ÖÁ„P„‚ 7؀хÖâUtÆl…12"àÀ¯Q‹eˆàˆŠƒ-80™@!ù ,•"ÿ€‚ƒ„…†‡ˆ‰Šƒ~�Ž��‘‘‹”•–—˜™–’œ�žŸ~𢣤¢ §¨©Ž¥¬­¢xª²³ž„¡®¸­Žqq´¿ÀŽ5½�¹Æ›ÁÉʧÇͶËÐѵήÒÖ×’Ô¤ØÜÝ«ÚÈÞœ7LQèéè)775â“à‹ñŽ,,åQZ|üýþÿý¢0�¯Þ¼CØî±0À�¡)®l™H±¢Å‹¯0ÙÓð¶ƒÏ”Ýkh@�I“  É‚±¥Ë–W8|1IÒ€Çe ƒ�tx2å‚F 5R¡¨Q£1b€0‚¤©Ó¦Fð€ëº‘æØk¥óÌg½FÞ{„’y†Ú/•ΊªÀ*Ȁà ×ló {kj¸ È*À´.æר®Žð†ÌÓ°rÆÇ)!�'̲ü¯«p 7wí5Â<±óû3PÔª�ºì~çàÇkŠ¢�B5õ”CMØ 4”1€# ø-x¡�^èÁ 4Á�!9TP�¸d®ùæœwÞ¹X ú謱F¨D¬³Þ8kè ;&˜0Åí‚>Äeð½‚v4‘Ãð´©i›BÁÎM7I'½9|oxç ü A@ƒõ|P†ßC„ðwà .ÀÞÌÙz‘í-Ì` ì³/�ãð7ÞC­÷º—#®xíµßŽ»àP�8l¯w¾ûððö<Ÿô 1Qž36à�Ø€"À@ðÀ„ ¶""Àap DÄ! þ`°>Ø€~4À ‹°A ðâ@á?¢�EøA„ý€Á Kq Qh¡?p€ylˆýÀCÑ ò£7¢(`À�1,‚‚¼�¥D Ä~x‘Še£G±*"à@ äÈ�«7 ãû ÄqŠk ¤ Q‡ƒ!ù ,•ÿ€~‚ƒ„…†‡ˆ‰Š…7Q |‘’“”’QL05‹›œ�žŸ ¡„0)x•§¨”xL6¢®¯°±Š¦©¶·|x­²½¾¿„"ƒ0©Q—0ÉÊÉ07Ž�¶0ÀÔÕŸ0¦Ó‚µ| —q qŽ©xÚÖéê~´’ á~7¹0ð²Ъèëü±6Q•nŠCÏÚ§ðlèÇPÔ�|’8Ôãça¥(šjTd#@%7V„˜ëÀÆ“…D�LÒ‹—0 ÈœI³&L˜ŠFRJ1e¿8)T™ŒYS�Ñ£H“*]ZSæËAqNÂÓÒ§º'1Á"3邯_sä€@¶¬Ù³hÉæû5iÍÿì³ZÍF¾-W�;¶l €?\â‡1+^ Â’3�71»ìQ,A' £ Œ…�|¶ˆÞ’"É¿‚^ÁúÍ1¤ÈžM»vÙÔøðPe…ê‘ËV^ dt$,8Çò,ÆhÑLšü¥ð›õ…ë2T ⣶÷ïà¥@ñðæúÖª—-¡å9,O•{bnÀ¨‘çŒT7Ÿ=‰ÿO€ÐAmhà�žOô—ÁuèØY<—‚N%'"ôíµÀ}„¨F ¬€]vÿñÀC!<áC‚B¡laã�6q8hã€Rh ÿõ¡oœCÿ£¥°€QNmHsG}�!иĉ)®Â ŒPà€¤©æšlªÉ>ÂÂ,I‚‘¬�áC–[øÐ†ÄÇ•’…D–¹5è ^~ æl@‘à8AÆ¥—2 é¦œjŠé§—²1A‚P´f�DfwÝKfÉFI¡VB@Ájd©FƒŒzùè0ç�°Ñ©È&«ì²ÊrŠ© èÁ�ÖY䃭†hY±Š­§ÙJ�!J±+£,>&°(`` L ˶`o (ä«ï¾úÞÛ²›¢0*±AP{jvfÀª®pû$ 6.Y€­„ÿlA¨èèºÀ pD�ðÂ{B²öê«ÂÉ'Ë òÊ,£|r¿ö&«é îȰÕ"ü_Pdé“­e ¯3±¸%b÷¾‚ ìi²rhðoÉ( Ìò \wíõ×-«3ÉÔ\àOW«" `Èf„o€q;tÑé]±‰,ÚôÓj’�Õ"K€oÖ)Ëàõˆ'®øâ#x½òË(ÄŒ,ð‚|3Î ‚ç 4BCÌ­S—4ŠM¯Û7 ÐŒ� XÞõâ/Ônûí¶/ÞµÊ�ÿ‹l»5· @Ú§& ¡çÏýÊM7Ñ´WÒÙÁ 4”1Äõi¤�StoÂ÷&Ì ¾ÿ”¯K,„NPá¾ðëàÅüÔoÿýøÛ?ÿþ^è°Æÿî£H…ùQ¡|åŸøÀ×½í!€D¸^¨·;Ø¡ b±ÌQlÂ]©’X¢gÁéQ¯ Öµ·½îµ|ßS øX¾ô-�8䟼`�úð‡(‚‡X„ñˆFD ؽ)8‚œ XcAéˆe8H¡Ib—ð‚rÀ…-�‚=ˆ¢ &‘’5j ¹t"Œb¼Å9ªÂ‘4À j¤F² 3 “@ œqà�‡dB)l’MÀ �xÌ£/’¤@ ôàà .À€ – e%+ÉIŽp ”cÈÃI!ù ,&•ÿ€~‚ƒ„…†‡ˆ„" |��)5‰’“”„q7ŒŽ|)q•žŸ ¡‡q)š|x¢ª•q¦x‘«²³ 5¦L�´»…™� 0¼ÃÄ6¿§©ª67LQÏÐÑL7º ¤¦"ÄÛ²¦œ×·¦åæ )"±ž0¦ÜðŸíšLŸq0¥æúû�x"Ö“6ã0žABó «TƒÉ1~ÍAbˆGSŠƒ%äÓÀCWûð¤¸!bƒÉ“'™qˆÂ/…ÇIqX:º˜ÑàÆŽ”â0ч‡É�uŸlˆ�Y.Ì|�ÞÕä¶AÎI"*¾bbƒ…U²jÝÊõêU4"Èi³0QLzK‰Åùõ4‘ ¤ŽÿÀÀ¢ ®Ý»xóæÕz€¨£( ù-›vÖ Gm YÍz@Ë–Ç�”X�ƒr˜3kÞÌså ((ò>6XEGlƒÀ…EÍKægqV»%LoQcB Àƒ?N¼¸qãÁƒ7Ñlıi[WŠ#•Ï�Ø»60±mÀnh#j¶TïãLñè/¨_!ƒû÷ðÙ¯G�¾8ð/>tO¶«uµ7>„a§ V·ÕZf¿!1^¼­°|� ¡„I'�dªé¦œnú¦ÌyéBùIþù$Ÿj⡈ ¢è•�n©ž{z¨Ñ�•þxi¨À’±)Äv@ì±È‹�±A°¢Ò$�GVñƒzõŠ¡†Æ:ë�hÉeŽOt E¦GŒ -ì’ÁÉÆ+¯¼°!A»ÐJK¤¨�c¨*(·& ø-£á:úÀ¸òðA çf™Á¶û.ÿdŒ,›8t|ÂÇ «9Á¼ÄjÐø{陞« îìáªÚÖÁµ.Ü% a‚°)„jñ»gÜB ($­ÂÒ*ÈàôÓPË Â #Œ<ï §,j-KÅzb;ËUæê”ᜰÎ;Sךâ 4»}BÒ(0 5È|÷ ²Ó#h /¿«õlh*…GÆì! l{vMjË8.…<…¦Ì]·Ñ2{BÓ2ð=Â騧®ú}¿�¬ -m8»¡"®8!äéøØe‹¦@·iˆ°¸mûˆƒ¦0 ÝDKptèǾ²ê/ToýõÖ«2±/${á(Ó>§ÿ›ê‘'Ìbº­ïÀÏâ•WÂ_Ö„:Ó á!¤¡?00ÁÿÀÆ2�¤-á€^p€ð‚è@ÖKà HÁ zá‚| @*8@8à#@˜p^ ¦€€¦�CBÊ@ƒ€ÙÁMÈ�ÙJÔŸ÷Mɇ\ñŽ›0?ôЀ3Œ!ˆ�†" p^ЀL`‚΀„$\‚0è…z‘ Ü"�@&0�p€ÖÈÆ5®a Eˆ£{@G:b‘„:X×`‚)øÑ‰KŒ! �xCêð3¾s•¡¼R›ÕƇ@äÊVJ …Jj¡x‰hšcÉRm‡¾!¢(çG�BÞ�>F¼ „;´’~àÉ‚P¶OæÀ–TÃô¢HI.’Ž\ QR@³ü" ÅüÄIl�LOÆn`Í/h+Y4Å/AH8Ò…Jtáb†KT[•C¨M%AG”˜Qwæÿ˜Ø‚Áª©xèÕ›#„¿€ ná‹ZÈV‚W�]MíÂs±(Mzlqh¼×ï_!(ˆý ´éÓ¨Q#ñQ¡µë- 䨻ïSx¬¢˜»\®)–+UìÜ„t 5jJ¬X~¡¹ó ¢KŸþÜyP\Wx3šàÙz¡ºê‹r#«Õ}ª€CU-g §pzù5R¤¨ �„ÿ<(à€þ÷_tAäçAsË™6Úw)ŒõdçYæ ?ëÝ¥À%TU�õ9]1ä—ß!¤˜â,¶èâ‹-ª¨"Oøð Ô]Ð`h¢=CUWHõTZüH=JÅÿ1¸sÐõGB€>˜(Å. å–\véå0~0#þIÇà ¥!ÑUÔ&$dErCˆsæ#H^ üE�š®é%€<¬x„ —$ªè¢Œ6ª¨—.¡�?�‰ct:®‚k‚€'È�¢ÇÌzxêI_“HáCªØâ…ªÁ¢dÔj+ 䪫 ¼¶�ë­·.º%±v€b^zÁj¸æa„çdo!Bê†yBÐãjšøD€+²¸%±bp«®¹J ®º-Œ0ðÆ«A ë¢ l¢ «AŒÈ–™`kjp­´CV;ȵz™ZÚ T™Ÿካ¥ùŠÿº®Ën Ÿðn¼ Çû k,�®¶+`²˜¢¥PäW<þE0µÕ"œí¶ ¿a%ŠO,8Ä;ërŒÂÒ*ÈPtÈP}ÂÒ$—¬.º¨ŒÃ–üò�`~j a³½Ù”Q:+Ì0t˜ëB×*À+ƒJ£À« '¼õß ã ¯T[}2(Xœ(×.óÐ�‰Aˆ-šÍfÓ”¶¶ô­Íj‰ù±ñÁ–ŠÖÊ€ò¶À4¯2ÈàwÔ¼0Âë#¼ð1È/¤>¸ K®¼±¸–1‚`¢:–FÙn¼ „4å”’y·ðŸ<À+„Žkº³Ÿ€º '8Ñ·ÿ “ßú è{�þú�ß>:ŒàÄüNȰ„ KP�Á»#üj‚S€–È…X…G4(ž�g¶º8ï�Ì;3Ä%å  M°Ãh@ƒ2 � D$ �x&˜� g�F` @ð‚ ½*ØP8Ô�vÈÃö°}>ì¡`�"q H,BŽØƒ&öÀ…P!r�)LA„ ÂÊÀÁØa�}�›Þ*ç5o‚|Lcò¢dá Y0BåƒÁ:‚ xôÀr–ÃÁ>�GТ AHH@˜€"i‚C2‹€B$CÐÇ..ÇȲð¬&„±L/´£mì‚Æ²¬ E" 0ƒ!’¢ED�VH„d`0]¤À•PD~ùKRÌÁ•‡¨€9E˜˜¹LÄ2‹©�@!ù ,9•ÿ€~‚ƒ„…†‡ˆ‚5 || 0‰†�“”•–•x05‘…6 6œ¢£¤¥¥q”¥”)7°³³7)©—�›œ0ŒŽ¡¦ÂÃĈL”�Å£50)¿–ɉ”xqÊרœ”ÚÖÙ~—7½”Qàéàqx“œž ê57퓼‘"”åêýÄã�à;ä)`´t0ñ•‚R0EM›$"*Uk¤ø&êb#<CFŠ2 ]$€�Š”¸o¥KA­J”pÒB—¢D™yèXÀ�/!’ÔeñYŠB,’*5À´)­=M™*Ujè†CDqžu 1& …PjÁU�Ù³g“ °¥m[-ÿö E•i’s4' ä ±a££HYØu»Eˆ‚ˆçÈ¡1„1ÚV ¼er&CÈ‘ñÙnù@MjÈ&|ûÅÁ˜´)Znc8nB¡¶í7ÔTØÍ»wï,%ضÝDswÚr0•tMG©ÕékÀµÙÄÎTÞ�ä�wï+ÂWñ!¥¼ùóèϹp!|øïÂk#™¬†³gæLµLR½®-F\·ÀlµùÀ›ì±—Á‚‘^y>üÀÄ<¡AzA�@ƒ$ØÞ óíVŽ%f[üÕŸ2‚%AØŒA@ß­ †yzd ! q^@ÁÆid‘?@dÿå“îÈàRìæ�w¶•¸aX�¶â(‚1¥€±ÙV£‚?˜O>i$Kv0AÔiç�u 0AœüpämFi^ ì½_q‘µe˜T_&æY ø ™g^° †ä•‘xÂÙ„*ꨤ  AœPpçŸ!˜×Á† ~ˆ%“mÁÁøyÙ¨� A¼!±‚‚:òødœ?ÜI*8à@Ƴd0 ­´lœ0­´Ñî‰A€**žœZÞQÆúaˆdÁ}Œ6Ú+b�}ѱ<²Â?, Å£Bíµ,°'`€Á ÜÂc0�¿dŒ:À©@‚hÿ{Â’8Ô™4Æ‚PeWRPg¹²É�Y½B¦Rx°r×yR¼³´bÛŒ‚Ùh£}Âæ›3lð œož¹Î>Ï0µ.«ªw‘óà�y>`ù4È"‹„¸É4ƒy?¸ù��¢Ì- bß tá� üò4<ÁòÊsîùÁ<£@³ÀÇ˪�{§Y^ +`98ÿí¾Ò»‰Óø€î¼sý;¿¡’±­ÁGH0öå#ý/ôÿÂôðß  ·ÏÉ l>Øü:1Õ‰uÞ“Î>á4†]å+ÆT¦Rªå  v°Ã°h@ƒ2 aD˜€ '0…šà…&˜� #à/8À KX€à'PA¢tPà ñˆÍC¢mxD¬á‰TˆâkXÃ%DàŠ2”! 5à h`  ËP„ÇMh‚}@†Ÿ¦lÐpoì ¤°˜4†0<$,¡½H„4 à�h¡ u è ‹3¸b€@D/¬a‡�Œb×PC Xò’˜Ì¤ŠÀÉ"ôàN“Ÿ|ⱘE¶PÍòˆ Æ!”‘„+a³Fº¸q*þ€.ß‘ˆ.ì’—…¸Ã.·‚3C"8°Ë‡Â»L�"ñK„$!ù ,B•ÿ€~‚ƒ„…†‡…Q|‹ˆ‚q ‹|)Žˆ—6•‡7’|™‡�’�𤥦§ƒ�5•’ q¥q"�| ¬¥5�QŽ0¯º¨Ãħ)’”޼’0¤ж¶L±¤œ’Ÿ‡x’LÅÝÞ �­’¾Ê"‘ÑéxØŽq)"Œ¿¯ßôßð‹•Ë‹â‡5®é2+¥êV%t|šÕ[ˆªÖ"ã%3,‡~‚@뤰RAOŽ˜ cH’Ô>>Â!ÄH¨b'<"¨²¡­ÓMq$ÝPÖIfÉŸ-%åst@Dñ±DÇá¢ì‘«ä´#ЫÇFäà 颮¦6òÁãÓм�¢®ªõS“ÏÒBÿ£bÁ�‹»òê…C¯^,NùŒB´1e¡�G×þõ ý“ˆT¥ 6é¨ÓCD ¥„GQ4rWòØ‹¤MB2UFйÓ"@ž|jÊI±çÍ›Dq%t` ¥‹ ™äƒèÕÒ¡W�6L*È*‚†ò9óÙQ>o…<tÄUë·¶jÿEÔÇ¢n]xñnƝ] oŠ,«[{m/^²‹·é–Ç_HžL9Æã-F(k.qùFߺ~³5|ø-iASEÐÌár–9 Èž=ÛòãMhÓæüØÃÍJdQxQéãwƒ_Þ²gÁ‚زÕT˜‚‚õسc�1½íÙ­SèƒvçF.søLœÐÜiÇI&_-Ùö–òMÄ?øÑÝû…ÿþ—Á€R(…à ä…'ž—ùö›dy�ö hÅg yMæ\vgDv+¬p�B1 ,²ÈË/(Œ/¶Ø¢�1XâtçÁlÎM¨^f¨a1â%Ùÿ‡²5B9 8`2‚•W~ å–tàe\n‰å‚Ðâ€ö8�ˆä„QlqÒ‘­$I“4q�Yt'…Odà"!Q —?l9À¢Œ2úe�FúA_‚ð–5²a ìØ&¹A°€}Ð�©$éá²]÷CŸ2J „†°¥_BÁ¨¼öÚ+_bàë°€ð%„²�f§+`g>\†Ä�¦žŠ*!ª.É*Ö•ÄÚÁY*JÆ£ ðJÆ»ð’ÁÀ¼*``ïóÎﻸz„’Û� Ô˜ ´möØÛ„~mË­’ 8'[ÓÅ*…ÿO(º«À^J o¾ H òÈ8Ø‹�#§,Á¼&c¯¯plé•<°˜`‰jVàÁy ›ºm·ƒ;žŸ±‚�¬–»òÊØ«AÈ)· u (T­�É8T­õÔ-œ`òÓú¾Ë«Ìb†P3 æü£¨=k‹ÄA_WqÑz �4¼W›|‚Rk­ÂßË CË'.à€O ÷Èù¾{B¥‹–}vjƒ ÁyfÐß^Ç �jø„­vàî» xmòT£¸á2œ û „Ën{á2ÐnrÕR3Î_âpäZš]³Vàç²µýö��Sð€‰JkºI €zê-cp‚ë*~ûÿä�Ðòå§‚ù&¿ð7ï-�loðʨädƒ´¹aŽ­ÛÏÐÖ_8ä­/ åTúOjE pÿùpèVˆëA>I (ØË·¯[sXà·oà-ZÆàêgm#ÇnãÅÍäÎ×± ’h9œb�ç9 ˆ-ÚÇa#¤S 9<˜°ß‘,ØêŠ\p2“,Àöõ¼ Æá-B(þ ¸ñ3’W(a¼ùƒ3Y”'�Ã3àÀ7��M2íl-9н—÷h F”WˆQ|…û ðã_ÈàAŠ}(òg�Áƒr5+47×má�g|mç:|tô]<¹}Å—g£5!\qé)'ÅúåG‡òÀÃPØ'…"¦ÈÇU¨a"ùÉçÞþ%çÁh¼%ÖCb¡^ |&š…·B&Úçÿ )†à¤“DùTÙÁRf9eöuð�ˆ vXc<0 h*PÂüôÌ�å-¶_ø�¤>@©å€„•€è¡@(Y> f}öùpÁŒfRКkÅbn¢á„ ˆVçGΗAl$É%Q"š¨° VN@F¬¸ €ƒ•p¨–!ü`b úM`¥MdºEÚ-Æ]§uI§¨E’zg$<‚‹R,h®d„n ´b`n ¤«.dÌjå ·ÆŠèƒr©˜1kf ƒk_= ­eÒRHgµ¥æ§‡tI(-à*.ë2p‚ÿ¹Ÿ ÁÆs<ÆHÀîĸPo|àäŠ$Ä8£r[@�fÀÐ~d¨ÛYÅlÄPb·Ý.zëÄêv¬ÂÇ �€ÂÒL3=È8t¬®¸°aeÊQ®ü¡Ëê¡ 0§=Úl°p%ÄÞÚ#SœnÇ- pÒPË`÷ÝwãòK·à7ÇS“au•*¥Ö-_ ž¥T·WÀK%6Î"‡vÐVBÁÑooì÷ÒOƒŒÁ#œ`úé¨Ó�Á2¨ Óoœ.„’èáøÚ—\¥h>¶[“SkíåWok¸E{¾´ë*È ú #D/ýôÒ;`î¦ßízß-nn•·Þžuÿ+º\ãŽ79Jb o­ ÄÏFüGüh¬Èwþ9 ®Û} ˜À  7ÀЀ# ôNg·í¡ {Ó€5ÀX‰Oe,ÛϤÎç5ß­ÏSeù‘´öš&ØÁî¡AÊ0„!�ˆá¦`‚Îà†3ˆ€#°„á‡@ ‚u@Dxáˆ^p€—ÈÄ&:ш¢-°†*áŠE BzÀÅì08¬á §C¼p+¤�{ìÐÐT'M¾ƒ\W,ÂË`Tr*aLxB÷‰€T! [èÂ4²Œ2c iCÎ@_\‚€èE.FÀ‹_t¤ f` á“& c_xƦ�k<áÛøF86k;eñC !ù ,^•ÿ€‚ƒ„…†‡ˆ‰Š„~�Ž�…�’~‹•–—˜™š™�…5““7|£ Ž£|  ›¬­®¬ 5 ¨¥¦�)¨"¶´¦‘¯ÀÁš¶�Q¨|Ä�qÇ6¦qx¨É ¢¤“ÂØÙÊ�"ÇQÛ~Ý£x¶Õ©å¨7ÄÙì—à�0Ç|ÎÊйϳ£ê¦æû¶í ½“dn”®mLP5ˆÃO!Æú”mà°Ý@I5pãnb:|m‰ãјGŠ�*¶ºø(NÁQ%•ÙÈÇÏÃI G-4‰êOk�TºcÙ¨Æ š!'±Xºt�–c{ H�*5ɱ,~òñi˪ׄ."jC„1y5,¥*U�[·Fÿ¶È•+ä­]·QæjÁ¢€­Ô¥~NrµuÌ—X�ïj¸%Z}|í.˜<9GŽ01æÊ5¡³gÏF*Ì5’ƒòä»JôÌJ¬°áÂdF ðøØ\{(çøÜ„‚o!1*®ÆÈƒãÈ‘‡žÅ·ó&ŸK/£—*`I®ÿÞÆ¬¶æ+F’@ØÝÛwò+–KY/%Æ“ ðãË÷Á^Šž +ò¯Hîœͧ¹5ÕuÙ½¦Ò;òh¶…FœAyÉåwÁ„òAÁžl|ÀÆv¸!}Rø@ˆòM8a~Ç W�g”½õkàˆ ´É¥ELƃæ·‚‰ñ�H‡!€ E èñÁÿ’L6é$>„ å” )ß*>à‹ ¸hÀuÊÀB”RS}QB ìA�èQ߈NB“O 0À�xæ™'è9€“KRÉ UÔWŠZRöõå˜aBÚ m¹5YglþxÁ›Cò ¥“~ ꨤ’ÊFðYªŸNJY_ðá·_¢�I'à—0JšR+”ðÖ¥kRࣛpNÙdž¥ @ƲÌ2àì³ H€`€³Ø’ªç’t°ƒÆ*k¢‹øl‰ôjé˜ Ûæ¦túé’ÈŠJ† ÍB+Á¾üö;Á´Ó¶À/´Ø’¡í t 0’! JB¬ˆ*Ú™¹_¢Kˆÿº Û£¦oz:'“xŽº,Ó¢m¿-¤Ü ,·|ÀÖ¢ ²Àý>Ë¬È +̆”C¼Ÿowé( ÿ�±Æîþر§ ‡¬ì²h³Ê-«`µÕ2d-ÃËO ÃÕ*´¬òÀÎÞœpÎ À3‰''qi·.ÛÑìûnÇó~àt³(ü 3(\­õÖ'^¸ßÓŽ`øàV‹M³e/ÛmÎHêÑp¸àç¶ŒÆ}ÝíÞ]ìÇN?-0'Ž5á…�àúëˆc0ÁëŠ/žõ 2°œ2Ùd0 å OÂ<œù¬o }®PG‡Þ&Þë=€È½·ØgÿuÖ†Ó> à¿àÀÿã;þ Þ·þ'„-3ïd Âüô{‚ø#QBÛZíù+L `¯|•±ôÆ¢ H0„¤á�ÀDe‚ 2`@� Ø`¸ŒÀ át@ÂðyÁ|H!ùRÈÂzá…/$a Iè Øp 8Œ€# �«¡à@b‚†4aC(Ch�;Ø¡ ¶ºÕ€(7AP‘-’±Lœ˜*‰D0"Æ8…2Vp)[‚ pˆC °q 6æHʆ-t¡NhXà�€äŠ@HBöà�‡Üá— Ã#Dà0Áƈ"Q‰ \�¡h™yé^EL)ÑAÅ+ú¥¨Le l`7¸ò•°´š*c™ZZæAMÈå`!ôò\ÔÏ hp&NHÈDæ6™Ë\ŽÇ–¥IÂ`éÜÅQ~Á®¨X4Lä¡›àÜD !ù ,g•ÿ€~‚ƒ„…†‡ˆ…57 |Ž�7‰„6��6ˆ5�|‘’�Q’~6�¡¦§¨©…6"Qš�x§"¯0‰®Ž q¡žŽ ¡šªÂè57Qx¯š7»¡6¸�¶ˆ0š"¦½|¿’ÁÄÞÞÐËã|5¦ѹӇհ§£¹¦Ýßõ©qä¯x"Ρîš.%â i*z‰Ú[È-_ çT)ËÕÌÁr©2ÜøM\®(L`$vƒO&Oqà�*ž#Ž0ëÙØÐoa5ñ#†ïQʘ@ƒÂ¬†‡�*MF…*]*¬F¥MÃ<òÁôjÌ8²±ØÊՀׯ^Õ%1À•k¨’�¬ªõÆõ€-{ÿ¼*˜K·n]$[òn1b—.د[e²¶¶p¢­``á WK’ rä€@¹²å/jôư\9äÏv¿¢}”"§a¦ˆåÒ…&†Þ-^#À„ær†,¾>¯Ü„ÂYð¶[ o|g "ÈÂ<1žP0ÈC‚ fà A ·B{@‚|¯9@#݇J~ªA6ýQðÀ@QÁƒR€@‚„!ä˜ã<òx„ÙÁ=ö¨ct0ÿ$hÞÙÙV‚»�ˆ\,˜h ŠÎ) "eµ½h„4ŠC:Éãl¶BvD›t²É#q>‘ジ]va€` *àU–Z‚â~ÌvxC™âuÀ‘kÖ)À¦œª§¥œ†ê ĉÃFîÙçwP®PŘæ•ÅsЍ–‹ÎlîFi¥—~@§¨dk,pb ì 4묱В�ç8€)�{NÈj«À]€D@V+Y¸¦¸e½ÎHi°!,›¡Bël³h ì½8H ï¾üJ0/|Šm©j“æE9ÛpáÒj(¹†å ]£ø«ÿ èÑ&§òÒ˯ Ü«,(”l²É-¤ÜB¿ö*+ä Xk'¶!Lˆ0·³Q&î÷Z%ñ¹?àëƒ1`<ç°ë,¿)—<‚Èʾ ÃÔTO­ÂÕW£œ²2@äÀ L³ÍOnÜpž�XU?ƒéâ Û}w㎙°©ÒKÐ4 *È€ƒ/ø'nøá…W�uÉ)Ë8<ÂäAÈ|mÍÚ&l[ÎáªÍ¶¹nc·‚to|7KëÛBÉWùë/à0Âì´×^ûáT/Þ4¼ó©Ah|yÍ7›MÚŠ!eå§ë¹ýÙ!ºÜ<ä˜F¦'�ºÇ«³Þ÷ #@þÂêøä—O¾擯ƒ´;á¾2,¡Â(ÈÀÆ ½÷~›Úy½ª¬ÚÐñ$“<²�¥ykSTóþRÉ4ÁvÈ ÊP†! �D@¦ÀAxp œAF�%˜(¤Ö·>/¸Ð…ˆ¡ gˆ�Ú0†È¡s¸†á‡@D!z`†Ѓ&à €Á!P�Ù±C$S‡�ËVfÑ ¹ô—.Ùå3Ÿ¡âdš@Æ2Bðo(„ÀÆ6¶ñ ¬ /ˆA .QƒSØ •xÇ:6Ñ‚|‚ÝxJ±Œb¬âÎêò—-Þ*!ù ,q—ÿ€~‚ƒ„…†‡ˆ‰ˆqŠˆQ|‘|5އ7’|7•›œ�žŸ› 6ž˜" ~5˜|©ª°±²œq’ qœ5 ’±—˜)¹³Äű6­š›É’²Í˜L”ÆÕÖ‹L¼·0œL˜Ë‰"Ë)­‘Lã×ì²q"x­ëŠ0˜¾õ|xÜŠÞæ÷QJµHëF¼VL:Ù»E¯Pm™Ù(÷O5‚ Å�AQ^#N òy¦h¦‹Šj09h.£Ë8D܈֪�¸N§0ñSdã�›jÀàÀ�Ëk“ÚlHˆ…Ó§ %‰0@µ*Õ§OmIcê&УŒš ðÊÏS«T¨]Ëd‹[·Lÿ¬�KW-š|´€Ë·�ØHQ¦±°Jw�aÃ9r@Hã­["Kž<9‡á$>»½rËU}Áþ �âÆÏæV,¹ …ׯ…¨©@›¶‡¸sëÎ 6Ùš·èÝ£ÀªÓÐG�V]{¸5ìÝ+VTñQAŠu)j‚\ÈÀ½;÷ àÃ_ˆ÷³k¿õQB®ÚªÇ‘[œV­açtGÏýƒ‡ë×Å h �$$¨ wá½BzµÑ–…‡­õ™|²Ð—šˆEæZ~¸­Àw >€Öu´èâ‹0† ãŒ&È]@amjø†Yh@|n¢¡} °öZÿn"nG" Ê„Rt`å•P1À–\vée—0¶H#‚AÄ`ÝŽÄ DdA¾7d‘ŠÐÇÜ‘-"xOF‚GhpåŸ`‚„j衈 ðeŒ2ò Çƒ×Eh‘YæÞ…p"'’u‚(b%”ð¤‚á@蟂2@Æ«¯2 묲J`«²Â «¡^¾(£PDšÅ ¼Ö›—¾™é¦÷A`g“<�b•«:´2pë­*Œ€Ãà†.2àꪮ¼nék?ø † ŒGl±Ç™,h³ôÑ(ÌÒ鬧xf@‚´ÔV{%×¢ í¶-4ŒÂ` ñÄWŒ0ÿ¶Îºk¡\º(ãTñ]y¯!ë&¾±èûI¿�ÞI"�OÄÅÌ@Qs¸h€ƒ ·€ÂÏ*¨ð­¸D]ô ·jü*ÇêŠ6‚7/ÇZv2Ê ¨Ü Ëÿ>­À<üúÃØcƒF®µÞê0 A« à 8Ä-÷ 8ÐM7ÞÊ­7 œÀFÃIŸKÓ,Љàȸ• äÉ)ïË ×KB›`Ø!´Èe¡±¦-�Ïl-ÃÛs¿ úè/Œ`úé¨ï÷ (ž±à„vì4ÔˆÓ �ÕÅ)›µãFÖçï³NBù«å`NƬ¶®íùÛÞŽ®éÐC�zÞzƒ Bë�o,ûOG=^â&çŽuÇ'úb¥ak%Ö„vDGCe 1D €Àø› ÿ üÏÁÿX‚�@@ Pá€:H è8ð�Œ h� ZÐkÈ`6X ôàƒ`ú§?üMÁ~ ßàGƒèØ¡ ‰±”{Üô™§´¡ f1ßù–3§$©¯ ëcy.@ƒ"¾/~ò›_–ˆBû™ÐGˆ¢Ã$Ð?þI@„XŒµ@z‘ú+¡ ›H?Ê�…Et!û€CÎ0wð1ŸÚЇ@!ù ,z—ÿ€‚ƒ„…†‡ˆ‰Š„~�އޑ’�‹•–—˜™š™“�”|  ž�q† ›©ª«¬£¤žqQ¡ 7¯¥³ xq‘­¿Àš½¶ž ¹"ÄÅǹ¨5�ÁÑÀÊÄ5)Í0Ô°7̹¤Òâ—Ú¶57¹|6å¤qLݳxÙáãöƒí¯5Lé|LÃù¶áé×€»z÷¦,&+p ‰ÁÐ�O”¯²Š(©ŒñB5¨Å‘š xýèeÔˆ©¤�7R ¬8 ‹›, èÜɳ'NœÚâL”G�¥¥|“ò¹r‹‚§P£†â!EŒ(W³¦¸�Ä©‚ž:o’ÚwŒdQ£�*Ý–í&aÿÈÍ‘‚]Œøh»¥Bß¿~ÿn `$‰ÜQ¿òëH(À³hñ-œÅ—o %ì6¡À¹óƒ7>*ˆMº´é Ü…�ã0â§‹YDŒìªÜM�•Ç`b‰çÀ¬~´”ãÈ“+OnZ à�)Üm-êNÆÚ"ÛÞ UîÝÍ‚ _q¡|†óçÁ¨Y.Š6?âË�D ö>ÊÞùîaë`G ZÊä¤ÓSsiÆYpä™w ò a HÑ�…dßvèá!„¨G…Ê�€^ú­gþ½¦˜€mRR#€àuA° p ¢!!†È¡dhäl  äÿ’L6¹ä?™áq H!z)®Ø„]ÕÁàŒ“ôÑGmØÝví(œƒ? é¡’ ``¤†Ôiç�xÞÉ$sv€ÃAòpåyì÷‹¬u–l`þ1æ*fÞ˜fxk^ð @ºÉ!“°Ñgl�!*¤–j*©¢¦šj�|ΩÁ†h%¡…ªÈÙ–( m‰Dê�Ž”ö˜¦™vÈ©�8dˆÁ² À€ÐF+í´Òššj²sb�¤‡²Z+t¸êʯ„øŠ&°<²Y¬±JÚy-³Ëj€‚-ÔÛ øæ«o¾ö¶0-©'È™m¨Ä‚ $º¢â’û‡¹“¦ûà„ì¶+@ÿª¤¶ÀƒÀF¾*„² $—l²È!ó[o´G°á²0ÃDsØmÂú�›¨—7Ñ1ºÂbªé’ubLªŸ‚ "›|ÂÓPG-õÉ*¨ ­ËXÇL³’±ÎТЇJ—+Ï‘ý¼`�ºItÑd”z5ÇJ3MrÔ#Ôm÷Ýx�uÉ)£°²Æ/³áÁøèw¿ÆúT´=ÔÃ/}ÐÏм ËO‘<D_F4ŽšÐê¸H1×ÁÝÚð0ÜéîLt! ï†<á ¯xÆCÞþò7…ûÕ/zó‹@õ¬÷¾öµo :Xß,°B ¸ð…/\CfHÃØð†!¬ßýò·?"øÐ\�ïHF%68iC!ù ,ƒ›ÿ€‚ƒ„…†‡ˆ‰Š‰q~Ž��‘’�‹•–—˜™š›‰x�“Ž607Q¦¨§ ¡~œ°±²³ƒ|¶¶ž6®q0)·¿À¿"­®�´ÈɰÁ¶Q7Æ5ÌÔÌLÅÆ”ÊÛÉ�Á¨"ÐÙqÓÕæÀ âÙ¡Üí™ëð� Ìx)ÏùúLÌâ¹rGÐ�Àƒ7‚5¡ ^ &Á˜X�ÛD�5¢ 㢾~Ýð8©"2’ðlлՠ#J?"€qÀöÒ$§—ëb;€Ó‘Î[Qö|eÓPWåXÚ`Á”…�§P£JmÚÔQÂ_ �:*ºHk¤¦I·lI�E�Ù³hÓªM †B5ÿŽrE¤•iT³FÄŠÕbdAŽ L¸pà '£E¯X[W8¨«9wN»OÑ*Nâ8Æ  A?Mº´iÓ¡C7 œÄ‡cÇ 2%YYIÌÎ*Üt…ßF¯~¡¸ñ ’+_~Üøðá¥) ‰ñÛq’ge³˜X{¢ÓÌfóMzÅo)R–g Áž=�÷ðãÇoßž¹ó?|¨ùC°âìÌO7uAž_�õFAyÆ)×|!DáVhá…J(á{õ)W\Füð@hþagÖSzõG…õ]n $ä=°Bq’ðž†àã�@)ä~°!ìyxÿt#R°‰¸�W}°¨Ìwº-X�7"·žŽV’$Àɤ“�q §…€ª¥¨Âª#¡ü˜j¢�¾Ú³-  í´ÔN m ¯6š(­DRhé›™Ò ¥‰�û‡°~[ꎢÊ,£®>;­ ôÒ+ýøæ[/½Ö>Ûª¶ˆ®Y«··&Yœœ#®†Ø‰æ©'ºÄ’ºÞ íúXæÿ» ´*/ õæ{ÂÇ ‡,²¾*ôû/Û–ùc†—f°äœôʰÕA,©î‰©ìÅ‹ÂËj´Û+CÈ#môÑH�2¾ü¢à/«�,ÀÊ#©ëœ /�D 5tÑ-m„-öØa»aöÙnp@ ØaÇ�4°7ÄiÔ�L!€ |›0ƒ· K¾„ˆ;1#èàø /x¹äxQùå^d®¹ãŽSá9â@aø”ø 3ô=Åêw#�s—Q KÚ! j£­;Ùd"¶ a» ûði«}€%¬@ eÌM­¯Þ7ꨗ^zá=,:ž{ιæ™; þsøä—o¾^X ¾k´¿Fð‡ÞÃü=X_:õªOÑúóCÈŽÄÿH0ÞÒF¼³xm(„ØÁ»†Í /’Ê]Öž)F1É Ó„zÐm¦yÎsh <ŽÆmnó “Á FÉDl‰ŠHÃ?,p�;ukui-biometric-auth/images/icon.png0000664000175000017500000004472515167732630016320 0ustar fengfeng‰PNG  IHDR  ‹Ïg- pHYs.#.#x¥?v9ðiTXtXML:com.adobe.xmp Adobe Photoshop CC 2017 (Windows) 2018-06-22T10:02:14+08:00 2018-07-02T11:05:22+08:00 2018-07-02T11:05:22+08:00 image/png 3 xmp.iid:d25dd608-d1a1-4345-8aed-f31ffb97fc5f adobe:docid:photoshop:bf20e7c4-7da4-11e8-92f2-d9e6550a8a6d xmp.did:3a170e97-9755-d640-8f8f-3f9b31c0e3ae created xmp.iid:3a170e97-9755-d640-8f8f-3f9b31c0e3ae 2018-06-22T10:02:14+08:00 Adobe Photoshop CC 2017 (Windows) saved xmp.iid:d25dd608-d1a1-4345-8aed-f31ffb97fc5f 2018-07-02T11:05:22+08:00 Adobe Photoshop CC 2017 (Windows) / 1 3000000/10000 3000000/10000 2 65535 160 160 4F 5 cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF_IDATxÚì�MvÛ6†ßädnm@Çê ÌÎ:iÅ 4®º‚È+¨²‚Â+(³‚Ð+(=Ö T:hg¥VPéhŸ´‚|^V4�HJußst;– ‰ï.€7ë¯}CÇúéÇÞ€å�¾þùwçl¼å�™uM1€,�u»zÇñë’±»W²d± f1€,ÈbY,�ŲX ‹d±:Õ;þNÏDHÿ,¾Fôï€ÍSw¶¥ïSúš8ìW"åO—TÁd€û/w/=*ý­2¤)�™îWâÀÞps‚îá C( �–Æ´! Ó[òÝ€�•€›¸ëá0èñ+�ù@ ¹ß ¼9׺Â]n5±�¬r¬8¡ÇÈÁÒþL�ÏŒû•ˆ‡ à¹%ßÇv,²vK ËXîXÄcôu»_‰¬å±@ºÆ›G1€h¿[ß�“Û±¼�.®ðÁâb&¥˜k{Åq‡¥‡)�/bÊ^ßâE†àíº¸mëÖâû Jaƒ‰Û^Xøhe½Œ÷+q(Õìª,]ÔWè¤÷“Q È:. ÆûŠ˜““�+Kø,ýlCÐy¸“U[XRBµ„TWJ<x<G�íJ±ÑûýJCÊ÷+‘ìW"ð€ç’u�“ûöÍÛÁ“ÞÅ&/Á~%�źeÌbY,�å·¸Ð>A]‡Ë¸½Š“�V³ÍÒc„óZ\•6ȧü¶gÆŸ,XeÕæ°Ÿ›µÕš LH°€/†y3C›*¦ “!Õõ8´×µâ¶;ÿÃx&ÕrÅðdÝBËýJÌ+~'ð�æ¿wÈ›2¼nN=K8JÍE’2¡ÇÔrØÞ·\Ý<€”DÄ¥‹ÿX5G<ž‰-Å}�¬Ñ ÈÃÒäS{ @ ÄÁ8ž �¼ƒ¤|‘wû•˜ÔXÊ‹Í)[.ð¶÷ï¦$«—@ßÐùq¿QÇ=‡ºåJÖ'²ˆ‡!øv ð-(N{¨¸xqÇ®i¹RéWYM#.[À ƒ7Bukþš’�Ì3K.P]Œ5ô@‚/ÕX½#] Èã›KN¤dm(6ÌÀË_œ€à»Ó\˜ùP‚vŠ#¨ggŽdác°ð}گIJKàT×N›•u 8hyS"ƒ 8P¥§ýJð2ÉF¤€¯5KàX³«Ò§Åï�Ö"“5Œ5czޯĂì¾Ï76‰…º%ºmD(#ŸÞ:Œu}¹É;½°Âí:Ç{äÖÞý•ÞÚù‚ùØaìºìß+{` |¡m)¢Tæ˜;¸×5}Ýâõ¦EÀ©opûM‰v”µÛ‚ûa¯$X²6à+m`ô›l)=2GÐËñäC Žgb àw_!ì;€™â¹À§K^äX2AGýy¥ ‰æÈ·`«‹�k|ññcßK4}P¾»�&¦ðs‹‹á‚›BÒ¸Šø³ê¦0.+Q†Êºßçbµ1`H– 6ÙnMÉ¢p±Wow"ë%*!ck¨ˆ [¯‹ÞjÕYDã:çx&RŠ=½˜!jCêêyâ^ÏÐ�ibD£ðƒÞûÈ—©ÈÁ¶äK´W÷šðá—!.^º…5!s´ÐºTÚëYV' Ò¥��>wöÜ,€ ¬O@%“Ì‹Êņç[œ¢ÉŽe„|¦'êçÍž_ô ídÃk‡ YˆI›±Ýx&"èÛžšÂ!_ry`ôr½õ¾@Jµ´¶”v4ä;ä…âíx&�¿ÉûÆ3‘Qš-àŒñºèúØR?`v9ž; o0Í¿з%)Ì£)¾K]àÃë o3d_[ò—8Ÿ€·š¦»P2"ŸrÓÍÆ¼·PÓ qD¾wô–ìþÂÊw?ún(DXH–ÑyšLÓ†µÙ¯DÀ1`÷Šð=™ÀGqÓâÒÞ¯DLkß#Ÿ Ü!ŸÿuÕyq½¬ãAßÖ„¨\ïš.®�å¼jaw<“¦î²Â|ç“+~ë|#…Õ8’k3ynÙrþNnì*jJˆ„ÆC° î@‘ân†3Âyq9hZ ¹ÐMWa„Ó2�BSŸ¶ïð@ÊüTAwdðܹâ¹GäÍ ‡¿çòša]b¡Jd¼‰}Ù!U~ð* ¢‚Ô©3†`p:€ºÐ–­ìý,µØGP/„ÿÏ�gâ^ÏÞLÇ3ú°· Ñ#ÿsL<ÎÛÔ­ÊÝÕǧ–µÃi»ÝƒÃû�ã¼™¶²^HŸÑV QŒ>#vÁf%kSê2–ᆠ„Ô]üYÓµÃ÷}F0Ù*£Áøýè±" ÀæZ(b¿Ô\UÒr¨‹7 ¼/°ßßYñÛÚ%U‘¦‰A¢e¦0€õîïÞàƒ6wW7WL±×¿à­‘o&ù„|¯¾µÂjúÍ¡ä£úý¹¸Ï6Ïá$Ä¢¢¿Î$ŽºwÈ «ˆäÛh$5 Åßþ0ž‰Ô´Yb¿ÛñLlðºt47¸ù)ã¿ÏļÏ� }wÁòlºvW~ÞÑäâSûQúñ3òÙ…Ú I#€z«ÝÏ–1ÙYLg0þ§Sä½°‚½Pã~Wp-b°ˆ¬ÝšÀ³Ú¡~¿ÚãÙ0N3¶Æ†ËñqȺ)4øpuàÞ¹HÍ÷+6™2#7Šdbaø|Õ{�vÁˆ'=^Z*t-vÁÐDa ÒžÀš&[mɺ†Èê?,S,öÇ6`½pU'fÏ=ø`1zîWN�œ*S�o¡ºILs¬6Í ¡k¢£™[Ý‚u›V¬®pja-kú¡˺)RX?í¢ ÍZ�”q`]¬_ õºßÈ&Y±L@|Œ9 i¼ ô§ -*¬ß V5.xk0Þ�ãÆhp¨KÝNY ÅóbËa M8nôÀÒñôÝ'ÏÑ,e÷éPÿ“Ìž³aÜsK;¨?Û÷Ñ`Ù¥€Ûj9ùF¸s0txNjnNB ÝÖ´¾ ò!ëà›h¬Ÿ­û ®45øÛκ³š¸•-`CÙî+@w!}oÒò?Wü,ËKkˆ+,�*[ÞØZ?�%K Ýpâ€e+‘:i°€f@‡ñ¨,fb3>4̺Àkˆ€svU§-m÷ñÓl’ùb`É–¶Ð2€ž«´'´êÜÝgÇmTω }f÷ëOìßyaXßÂá5…"†\„Âd¶€oýDWø–8ßeu1$Å~ e=‚.¤ÇÕk,¬Ï©qã ÜhdhÀ6Áiu„×Ûa˜,¶Þ!?0³ø›óÔwKZû-]¶¬ƒôý„¼¬÷W§#ò~@‹# ?°ÚÔ�g4†;S—]ñ:?»Hï½÷whIÈù¶¹Gø}ÙçÉ4†$K7Ái–ä‰3ßá&!Eë}ÒÒ6l²»^#Ÿò³rŸÔ�ŽgbyÍséÀvµ¡¸(C^jIÛ8Fa ¨ã¦YkCød«9€Þž˜~ ¢RÎ?Ò�¿ïà¦ãÐsPÂ.v9Ѐé³c›Ã7"wýe<i[~¬•�õŸNå–)€�èÒIN¬|:Ž•”¬U›pÐkÉÝ6»–7EW½VÄz§QVùGÇ”¦êÐ¥‹ÔÁõpÍß@{«!ßT¼p•mÄj)Χê>uÔl p¾ÓׇŽb΋jÐe˜Š³Û€¼->p|Ýç�.;AW§°K‡XËz¦"õmÆe�Ö€WÀ2w<5]@=?ý½ãëML¡©èðV½¿Äæ`n°9tœ®Wµf½ bëG+ôè°À©¸I`c9k,aY^œ˜îûÞ0òÂl}KÙ*,]3Ô Ë÷É>w*Ý$1 �mدD<ž‰Œ2aï§æzm)s-îâ NíH6|±SVäŸib>À¡Ëš²ç­"�y¦ä`ñZY|Õ è…ì;€:«s)ðFÈëpÓ6à“n¬/ªÄ@èŒpÚ~#°u\|Å–>Ôê–xÔÄxIÓŸ ‰5ñ¤3|±Ü‘bÔ7 ¾˜¸Û]Q‚€ù‰êu–DTd›�á3L(^È%oÀëºà"Ž9àÔ,º¥GÖfÝ�¦Ö¢Š,ú±m·Vaã0‚ô#£ÉêM+¬ì¼«>½Æ¤”yßU¼Æ|H ÍëôõÏ¿¿1€úäB º\$,ÆI½naMï†VFaÛ�/@õTØŽJ¶vUÞZ“è|K¿WX¼¨ÁVo:Ÿh¬áš\òáV¼Ù�h¹fRß ší3¨”bïÀ²¦²6Ö-sÒÿx/Õ$›®hõz0È.¸»x/í‹ 4茋l{0² ÖÇ_Oû•/}‘)û}�ó�@ãüy±}�nùœKûà—¶c½ãÂAëæ¤ú]Hà‘¯BKz0®-£|D^öao°o³û•ˆ©»å‘2ñAÃÈ…h'!¬ÛÈbY ‹Å²@‹d1€,ȾÎVÅÉ•ê6ij+~ª زسX «úÿ-Füã‹ p IEND®B`‚ukui-biometric-auth/images/FingerVein/0000775000175000017500000000000015167732630016702 5ustar fengfengukui-biometric-auth/images/FingerVein/16.png0000664000175000017500000000535515167732630017646 0ustar fengfeng‰PNG  IHDRbb«¥ ´IDATxœí]Ín\IþNÛ±“Ñ Ï0CD‚�±@ƒ@qÈÄ&½Dlâ'Àx›%œ5›@íáœ$$ܱbÄH6íHh¢ ‰œh`LJE�ê{nuÝë{»«îO;ŸTªº·ëÖÏùªNýW˜yÀªè¡v‰èý‚~'3ß° ‹$]]1p(â> ¢¿FNWÀzAï±ï¸GD}nñä8 ’«tz–™y�™÷˜ùhš´IkRÐB§s8EÚ¶ÜÀ¶Õ�û’èÛ¡]0ck’†< ÅÏ›´%îý‚Ùg浚òvÛ“¿mý£E] \aúJ¾-Ñe ‡äkƒ³kԑĹ3o9é[Si¹ fîËC¿¦ÝñêHÒu'p<ýŒ¸‚ÅS2M{#ÙsR•oTœˆ%•‹¡”âh¥TâÝàq¶Wuí`æ6ß°©¨!œR¹U¥ دÔP �ü«&BHp3¼7S"=ËžBQµá!¡–vÉNÚÊJɨœQ�$ÁÂCFtUYºú7Ž ‡ŒÄWœµïÅŒ+8Ý›Û:ÿ‹©âª†Nºh̦ËX˪ D�Uº£µU±¯2TË´É$àôŒÃ~Äxâád¦±íB8Ý^D)DU¡kCmc…IÁfŒµVD'ÂÉDëjƒ…S+bL£�ˆrœõ„í�àdú8š¾ÎˆW¨íáG‘¿s ¾8›‰ºZÔ'c a•ñN §YãàtÃ_iï‹ÓkQ A'F HÖ¼�d�¶Í(÷j–§i‹ˆžØÞòÉp Ü+�Â,Ƀ�¿#ŽXDXAäú*"z®ß n ؼD)Á‰`3…Ñ•Ç`Dž¯ l^ºaš&F�Ð%&4QKeÁ¸£Äƒˆ®r‡&¢NÕ¤óó¡„J¤£×Cà9�%›Ý«0»ü0�… i ¢çj¢"L�DXÄÐç6Ì0j�V‘Þ&š3À�2@Ø^\PÄ$"†ú‘+#ö"ºzE̦|wˆ41Q÷ÆE¬îk,d5˜‡v¬Á‚Uyç¶S]˜Mûš2!³FÄÆ’]Õ©R-í‡b¬ [�QiÖX ¢§´°ZŸŽ¶žÃšj¾Iæ®¶ÊŒ TÜÁ×±[U#ˆè¡â·àþaÝŸæûÐh[1³h#£©†:m$Âva»u&"4ÚH„EÓÑÐF"b×1ñ m$b&ÑF"­£êµë˜h5³„6¡Ñ­;¡ÐF"ô$^¯®D„FëˆpzÖeóWëÛŠÖ!(÷ €›Ã%Á6Éce´ŽvOw‘Œ´WÊŒêÄK„€>L§`·µµ-æ4¸„o77åy‰Óž™'8·m ð„³¦üD›ŽÈëúdê¶óÛ2�_¦2oç.ûÇCÎi/fŠ ¹j�'8�Çék'r¯‰cíCˆßhDT:Å!‚Ü•ÇgzöžÞµþ‰èƒ‚QéõìnžGÙß´³=Ó¢a'{µÈªek‚|£GÒ…J!§/4)uç’ªY*²Ýªi<ßšYÕñsàÙÓY ¢_–ùÎö~ õ÷9Ý6¿¡ &•ì}%¢÷™ùÌâ…Î#pr8�´+çÁú{†â÷u7•mB&¢Ÿ–üdSìC"úð<ÏRJ-q;M=T|ªi‚0–ʨNwq£ÝÃS55u…n]¹{êÝŒo[ƒ¦±©Ü=ȨÏ#›[Oï6åL\í˜V5qzqgÈi Ù3Á¦›û€#_ÜxÑTÓºr÷Äè3vÇÆHèDôÝlýh8$¦©N£»çü¶Áéõ„#ÎY Š�‹T#Ö•[Ïý€ˆ~ S#våÕ[v¸†î[�)k„mr¯l“vÄ]LòΘ†DÌ“Áé鉢ÓÝ>uíßQ.„j’ng©óqêê›…¤VÝ3Û"¶]Ø,ªfˆè¹ü^‘¯{‹‰¦aïÒ( "ºOD7aƒ›¯çš¦Ðõ‹4ØuàB´ ¶Vt‹6Ú³€Æ!�ö@×ëKIµh[+zÜÖó %ÑÔÛi~sP¤ àÇÌüg¤ ” ì¸]sàŒˆ*ý¿½2¨”fž0瘎²­›üÀÏüÀ¯<’`4©à•í’ÀΘùLž_ylkN‰è,Tž‹bžå*µÿGÍÌoÂ�­�%À%¥ãØð€/ø€_`¼6Xû\�OÀ©v3ó©z àb‡•ÿ<’qb"˜ùkÞP?}IÞ¹dhR²jIÀüÀ,Ã\÷ Û­eHp p¯…ï#bž™çˆèU9Iy±L¨š˜™`¼€„ë¾¢¼¾‹„ˆKÈ'ÅGÈ÷TXï‰ø=Æo ð¶ 8ŸŸðµ­�Åo3³}<-)¥ˆ`æ9$_PFqY}ò6ƉÊ"æ’2à¾èIÆ×üÀ'>‚i;¬jÒµ Kýd ÞuŸ M‰JÃeKÊÏ 3Ÿ8!"í¯0FDˆzé ÝhÚ†sÀ¢$à²r/zÌ—UøßAš¬E$¸Æ%ã[žôžª4]óÀ¡�²ƒ„�”þÛ§v´àO”mͱ ÿ«¾à¥üöRÌ13�ÜH×B[(N‘. Ò5B ÃÚ ’ñ7aªã˜6à o MÐeudñM ciB²°ö"LûÉÔ"’ÞÒKå�¼#Æ ʯUOœ! K„&ÇGıCÄu·¼�ô¼ð¹øù¯¸­qÃ;vÞ�ñé¾zGÙn÷²“cþào掎¶~Öü.L{p à·¾à¦øù€‹û€¯;ùø‹#8öØyæÌcŸÁÔ<Àôèþ¨ÞkUèë�¹í–~6·“srƒðÔ`æk0%DôÑßÏ!Ù±÷D®�ƒQUóö�ãÿªMÈ�&ÕÙi»%ÎOˆèQ®çâa2ÐÌ)Žw”û1H�䩼{—™¬"z%BùI‰ŒŠü6› h8šHÄU±?'¢êýcåÖdòF-¶Ž�F!#ñEyÔ‚‡¨»”z ¢“BšODìqàS˜†Ö÷ÿŸŠ=ÏÌcµBÃCÈgDôŸ�‰�Zæ$sÿ½:£!Âû}쩊 moèZ‰0Ñ?C¦5zb:HÜ7ý~Û[YUÖfX™t�^„iüÒ$=E2w½Î´L‘uOw:¢GïÊ‹].pKKðfÔúô<�M'7¤íÊ«»©'<~ ¿ ú*œkÌ|K ~f6_2hµïúÙb9£»BF½&9ãÖƒ™ó/‹(¤Úô&øæÌ¡úѹÂÿdÊë�éŠøðIEND®B`‚ukui-biometric-auth/images/FingerVein/03.png0000664000175000017500000000561515167732630017641 0ustar fengfeng‰PNG  IHDRbb«¥ TIDATxœí�MlIÇÏvœÄ“D‰Ùì*^m �Xi�bñ±@bÅ N\Ù… ‘å„8e%¸'GÄ%!�)9Â)ˆˆÕFD›(QÂZ1ë•'vÆyêÕô›rÏLϸ{¦Û›¿Tªêžššê÷¯÷ªúÕǪzxÃÀÅpID¾W0ïPPÕ/¯‹dõZ´pÛÀ5K_‘V\¯‹Àw f¿fñàŠˆÜÉ+ð¼�KyªÎúœTÕsªzYU?ÜMݬŒsÖÐÊ®çû»¨Ûù´° îëVé³eWºàƒ�³:ôÂû–粆tÞÒW 檪žÓ³�Íy¾ þÈqUð° 3¯å¨ª¿SÕ©êëª:cáf\8¨ªTõ«ªú–ª^éQîyU=<¦g>çêrV4³q£°óSÀd¾üðùø‹…¿LØgbaGñ.öá™Å_^¾–ó[ß~lOEDTõ2¡?¾$ªú>¡Ã{µ¬ŽÍÞ-DŽ¿¾ì¾zø ð'`ƒŒ“÷#á™…m`ø:ðmà“î·ÿ üøв¼- O©€ �ëÀmQU‘¼VV´À}€S9±Ÿ~ |ÊŠX'´È?OBŸ &îÚkCZß"$Äx8|øpÈʸ ü ø7Aøžˆ6!À�˜gCˆ«³ÒQþáªÓÀ4™ð}º1ûÂÿð‚uøÁD¤fkÂÅ^+º™¦”ˆ<bK�ñQà-àe+gxx�LðyaË¥7Ed{ùµ+= ª:I&ðiöõˆ=Q¯4aÆŠü;ð[2¢&ÙiÂo"}½üu+%âvÚöiÂ!à …‹Xz¿¥cH ‹} ø„ýÖ2Á$ùßštqª ©‰êpiÿà^CZNOí^$äÁ\A0SsÞ2!Ga?vñ†ÝdéGv?Õ¢ÍäÞjJÄ4�-Î cšN;?E÷ŽØ·â˜^Ž[¹«Às„ì;å¼>!OàÝLkÚw¤ù6�D=#�1k÷ï[}½fÅØ“˜jYö6ù� Þ‚ )<…ÈÓ.²+¨ê!à´]®‰ÈÍ*~§LX_x† É-àÝAmÿ¿d/IUbÑâ™S®Ö°Ðm»œæ«þÍJ‰PÕc„V°\U«ª"²ŽÙoภ×+CÕ1gq‹ÐA7 w]ºR­¨ŒU�#,Ú0Ô Ï8aüÐ.+ÕŠ ‚-\í“o̹ôÊn SÕcªúiU}q·e _÷#”X�‘—Eäh¿ÜC Vzµ¤¾a’0¤Â«péf¯êLÖ\º óT³o”ØI?vé‘!"�ÉÌÓl¯¼Ã¢*"Z¼Ñ3×H�,«ÜÂÁž¹†DéD˜Ùˆvüq¯¼C eñLÏ\Õ 6ªýæ)Uh„7¥i„¡lb�ï'J׊*ˆð6´*ÁUb§ûÀÁK×ÈJ‡‚¼MoÐ…3G,LZðªu´»†ˆle3å÷QUÑêŸe`DbB»?:B 'VÎ ªÚ"Lð¬Üðã4o]Q%U”‰˜RÕ3䛈5B‹�ŸM‘i FÌ*FN]<ÂãxKÝ |çïIX#ø„V£9t¦êA;¢;~Š0[xÜòÝ‘±{†›F„Ç™ðw´j#dÅBjÆ‘={Ù#»¡Ð4"¼ÀïšC®Œ¬e Ñvd�2ªD£ˆHF.³;?lY�ï{IF1gýÐD"âî¨=°•¢‰DDì9h"ñ]bØÊÐD"âpsØÊÐD"ö$šHDû]–sî 4‘ˆÍþYš‡&á±gFN�#"qIìÓÔ(GŽ«ê ú�êˆÆiDÎÄý pZU_)s½“-ñ,ýȈnh¢Fø™¸‡vÝžüQÕûìbŠÔFb Ø”¬ª®ŒBÛšHD\ܼ!"wTõaÉü »¿@˜"]n��K 0´‚çDx˜éi/õ‡öÐ=U]&ìNŠ‚œ>¯ªº-d°2ç±;CÜÏ1²í�"‚ÎÕØkjm®â>Ù~½ˆÀ1U}à§DëB@DS‰x˜'(Y·ÅSŸÔ$Á´L/©êaÐ ÁÄÅçµ&Âìö¬ ½6¾¬b­\DnØ>¾y²½ß§\Þ±Q"lX?C÷Õ|­>£˜u3ª:-"+ÀJBˆÏ;v`ÌDØ¡U±µ÷rk¯‘Óo˜ï;Ž�uê‘�ÄN=y?§ª·Eä£� DŒ�{Y:žó‘_™·avÿ=× ‰È¶ªn�iÕròùGªzƒ@F|9¥ª«„áîǧ�HHØ$}� ø¼±ØI]™·B ∪N¦Âµë[uÒŽ‘‘�°ÜìÕ m˜YÔ,Eø%ô‡gAí@�´c¤¾&31…I0Ä�æ-³óEàýQ=]å"²-"·ÇÅ…ÓÓ£6Q##ÂHX´ËM �àÖ¯BÁ“ ì;ñwZÔ"3G7þ«[E¾S&FbšZÀ­‚-.š (n–æÈ´` óbywžN<ŒJ#âN‹  E=£ÑÁWhÓ¼­g]pßë�tŒD#ÌKº ¬%!9Ëãa¯¼‹7æH¢ˆ‘�šDäÞ€_‰Ú°Y¤e«ê<q÷êð¶<j9Cgn]õílˆMÒÚ£«Ú –DÐéîž-0ºhqãLRD]‰ðG Å žù¼�æÎC a¨{âEíˆ0ÁÆá§_L¶œIO·7Oì{„9бï…µqƒ;x³t“°â%²3fO¥óÑFÆóå4eÁú‚ØI¯ŠÈ–ˆ¬‹È»„™µè‚èi®šˆZA§6|à?0³] �éHO5«u%b3oÎtw}‚?ÑlÑÎû«äŸQ 6D$�ôƒ^y{˜«Ïªê‹M4Wµ!‚lKܨØÅ\� ˜«FiGmˆ0TœÐ™+Úª»˜+èÜ_{Ô†Cì ãÔea$æªëʾº¢VD˜s/¾Ä u´ˆ,7ñÅ®VD¢÷ï…aiQÔ‘ˆ²‘Ðs"Æw¼ÏëžÙžÕ µ#ÂàmüÇB+jI„9óFö'uÀ”ýW)UÿOéø€l;ϘVWT�¶üËø‹Ì¤àylÚRDþ±Ë²üŠkÀýqîUÕ×,y_Dzºa(S¡¦¦ vlÓ‚àK:mν=×�×–ºwÒ{’�¦±F§·uÏRK"l^º½l’ιë„KL )uÃû¨QÇ9kÈFKñÔâI¼õ,a¥öÛÎ;G¶)1nxHWsÔN#’Åe«îM;jÀ´Ýߨ©!Ç óÙ'›¤!µ#‚ξÁoj�n�޼„?AÔ(BêH„?âÁ/XîéöpDÿ¢�„ÔŠˆdÞ:Ý„èÝ~% i¾„ÔŸˆtݘ°Epml’ÿ·ií¼~s9„¬ÕíL'/ó àš¥—ÆQÞ=¹Ñ툜Á‹„H=ÿG{ÉâkÀu»øÁxê20¢�gÿx‘‹2¿>¼cKªznL* Ûû‡ª ½òÖ&ë%»|gÂìèÛvã’ª^åjCb™ì�<½].Ù­·�ƒv† :<.ºræUõ5ç2Þ3ˆÏe®þxïâ.äv!–Ó5‰È›U¹2DߨÍ6KC|ç °d2àÿOŠ*G?H@IEND®B`‚ukui-biometric-auth/images/FingerVein/07.png0000664000175000017500000000553015167732630017641 0ustar fengfeng‰PNG  IHDRbb«¥ IDATxœí�ßoÇÇ?Ç6\¤PS[IqDÔŠHy­Š¥ö©ªšü´ýhÿòÒgò8ÿ<ô¡U@}¨Z5)TAAEE†A±°0µ!¹æšÓ‡9ã=»ì½Þ{½?¾Òhvï��™=ß9gfÎÌî ªzøÐÀ"Åð‰ˆüª`Ú± ªg�÷€’z-X¸kàšß‘V\¯%à—“_³ø pEDîåexQÇÇ“Rî*]Ÿ“ªz^U/«ê“ÝÔÍò8o ­ìz.ï¢n³™]r^µJŸ+»Òoì¼Õa–-Íe è¢_- ˜«ªz¾¡{;—s—üŸMUðˆ 3¯åÇ}a”Æa÷uAkÔ+óH•÷6¤~ç]]ΡªKv²ÔP…>ÈÔ«×%—³4 ¬ÒʱN—·e¯‰*Ÿ­¹G\E"–­WÖJ­Ü úª »\·v¨êÙxßÄZ4P�ë™Vy±NAh¾9¼Þ@ƒ ò¯›#!{ó¥�fF¨ÏÉœFQ�‘CB#ýR4é+k%£v"Ì´’„ˆ2*7•MáÕ¿u$Ddȸ^Cyõ¡éYûå*Ë*šÍ]ÜùŠ]•Uš ÑTÃ�±‘ Ô(03ºìê]YQ'WÝ 5â6šö8\­°œê‰ÈÜLkû…AÐtQI#ª‹¯ �ÍÆ…†9F¥ZQ9™›èœ6Dd´¢ 7ú6ËZÍzÂ¥2o@÷qeöz@¹¾A]ª ÿJäŸ-@µ¤±¸G]#fN“9Ðr�åî™VTʇ¦;þZG_š^;¨¤LT‘)Éš7$ë´]Æ5wüá D»AUD,Z|#w�|<ÜpÇï•”g!Ø=Äò«(£*"¢ n M5Dä©;=ZV¾# ÞK%� t"4¸0ì´4" k%ç7 â½,hnš*4·˜²‰¨´U,»’ò« bÁ—MDD“¦ Ò÷X ¦ÊÎWÉŒ]/ U� 4É„›„ÎrBU¿å/±øçî&o x)"[ãÔ%BDž:ÄÂnòÊCDD¼bÏUu ˜Ì„ ÇcqçâΣ$~ ¼ ~ üÄâ<|üUUÿB ò?Àð2ÇðBDjÝLÕqTUY>D²¤LäÄ’‰½)ý=pª@=Þµðk;| ü�@Ò@Ÿ„ˆ¾ªÆó¾…*C)D¨ê> †÷×wì·,ž”AZ’§ÿsy{ÿnŸ�ÓÀ .í<ð ~GZðQøÙãˆIU�‘—EäSc¡ªÓÀ4 ñø Kvœ„ˆ} 'e'³%b# ø/Ál)Ád)ðÈÒü Ø|—@Þ)IËÀ Ò÷±3À·U5þÞÛm4ª:I"ði<Ü%oð*QƒˆÙG¢!ƒÌÖ~—÷§Aï#‚½WòíÿA[þFò÷š²Lh0Yáo’&aÓ•}8âÒlªê&°)">]aL¨jvtâms<ÞïÂtÎqŒýdg�W‰Ë#Æ“3Èteûˆ³À1w®.~IBBÖÞûø¾o 5'Þz®¬7€·í·ø_è©jøÚ®�uQÒõòç*"/£Fx!øxÚ„pˆ`rÔò ¡U̘ð¸ð–«ð�H•¾/kÒŃú OÄ<ÁÜdîØß¸×�¾GR¶HkD žˆw€Ÿ_™Ð¿ž[šgvüÌ~Ïæ×ËüÖSÕÍHÄ–‹_¸�áƒÍIÖÎ?>·üþÈ`33¬SÎŽ˜|˜%û5°ê„#äCsBÖ„y¢²ÃÙíÑaPp›0Úò$æõ+›îúl#ðyë Ê� U�#´VDä³ ò‡0X‘Ûeç¿CÙïÛáyXfÞUy_«DÔÞÉFkQ2ºHÄs‹g†¦êºHÄžD‰Ø§› eO ‹DôvNÒ=t‘�ý;'é:G„ˆl¸Ó=cšªtƒ×�ãª:|™!¨sèœF˜ãÑc8­ªo›G¸¬rŽÕ¹£°‹á׫Ûù”ÅGUõ°&"_�“¹�Äæ ³wTuµmë"³?‘{ªz˜#¬)@⼪®w‹º¥³ú„Ák"<ÌôÄõ €-ÈÜWÕ‚Û= ò0ðCU}<´pcyÎÖ$"ú–ÿÊn|Š¢SD�^HmN‘M3K§Ó—p8¦ªEd%þØ"ºJÄãmã$@ÃDØfÞØÚ‡¹µ×Iˆ¦ �î;Ž’tê‘�¸I:y ªwÇÝ•X#Â&KÇsþêZê:aˆºa­9±’sÍ6DdKUŸ“hÕJæÿ§ªz“@FœƒœRÕ5Âp÷›ÓGdH脾A|ÞD,vÒëç«"ŽªêdV¸v~§MÚQ;ž·‡µBf5Këîø�+Ø6iG­¾&31…I0ÌYÜ7;_Þ5ÔU."["rø7ɶÊéºMTmD vÚ£ 6’о¥¡}CæšXNŸ‚Zdæè&Áu§È5e¢Ó”!¡Ü)Øâ¢¹€âf)î{‚Í‹¥-ëáË‘P—FÄœ>AŠzF£ƒo­H'­ª±=UvM£CÒQP‹F˜—t X-J‚ 5Î-Kë°`qŸä=á�@m£&¹?â%QzEZ¶í0ŒÄÝoÃly´r…Î:Ü8ºÚ±o°!n4Ië#Œ®ZƒVAÚÝ}¸Àè‚Å�3Im%bÖÇž¹œõjï¡…°4Öƒ"M£uD˜`ãðÓo&›ÎdŸú7Oì¿k…æmDkÜàÞ,Ý&<ÜòÉC1§²ëÑFÆëí4eÁú‚ØI¯‰È¦ˆlˆÈ-ÂÊZtA 5W]D«ˆ ­ �üfv¢ "bžà1õ×um%¢—· gº{„>!>'1ExcÌ;6 ì$ZCD¦“úXÔsõ®ª¾ÙEsÕ"HÉ‚ÐAïˆæêÁ\uJ;ZC„ù â‚ÎlÑV=À\AúõÖ£5Db—. #c®îìk+ZE„9÷â$nnXÚ!y¬tqb×*" Qˆû÷°´(ÚHÄ*ÉHè5MÁl{tcÞKOŽCëˆ0xÿ�ЊVaμ¸uòx™�dµSjßv¨ú{ÔcàÉvކvWT�mù«½CSDJySM™o§QÕ3$ëÐë„·Â4æî®âí4Qþ­4MðÊcZ|I§Í¹·ç:ðÖÁàNzOÒ5"ÖI{[÷ !­$ÂÖ¥··M’^»¾Ix‰n–�Rx¯m\³†d´Ô' c' ëÖ‡ ;µÚã¼³$%ÆÞÓÁÝ­ÓˆÌæ²57ÓŽ0 Ûîª!Ç ëÙ'»¤!­#‚tßàj�n�Ô/Cˆ_ ê!m$¿âÁoXêöp DŸÓABZEDfÝ:û¢w{ø�€dÓ !¤ýDTñÝœ1°IpmôÈÿžÐö ÞNk9„¬·í�N^æ$ßX[l¢2&¼û"rsÐ+q/R÷Ëz bÑâk$ßÎùM3uÑdzLä¢ÌoLÛÉ¢–ô9Ë*aÏ>Ä¡êü°´m†ÉzÑN?ž0;ú‘ýð‰†Ï·ýÛÓ+„­3�{ ÅFoKÀ'öÓG©¯Wjú³Ç£bÉå3§ªï;—ñžA¼/sõÇß–v!·íÏ2o�šDä·U¹2F+ù�jG°8Æ5W€E“9ÿUý²¸¸£BqIEND®B`‚ukui-biometric-auth/images/FingerVein/06.png0000664000175000017500000000543315167732630017642 0ustar fengfeng‰PNG  IHDRbb«¥ âIDATxœí]ÝnÉþÊçØf;Â1²µ'!‹ˆ±ÑÞåK¹Ïî�}’'`߀͘70oy€Vq- 1 ¯Žíå˜cW.ºêLM{f7Ï‘·»þÃ%Ó·ÊÎt΂ݖ)>!YÚqàG~ àŠŸ ä'Á'ÀüNCìö¿$�f^°ëkÎy02b·§á„?‰ˆˆß™Ëþ `AÒÑëÒHI#ÄjÇk?pN#bYÂi"ò�$|k°¦ð€¿2ó{8m9"¢“â;…BDH£§ÂŸ2ÁñKsË€Ÿxç• Ÿ˜ID’f¶¦å¹sˆk„ÖL«iæ'MðþöâDl›ô>ðÄ\sÄÌGúDô>‡(O!7Ì<�¸ðÓŠ¹­'4Kœ¯A~èšØ7]ïä¹Ó8­'.K8€Óž]ß#]ð6eÄ?pÑæ_yGDÇgˆ4†.043¾TXIô# 3_�íiÙÖ Ñðy†%1M𧵪—üñöÃï¢Þ�ØjˆÕˆD¤h¯I÷}ú¿ð%Éï$>”k2ó�÷Ÿ×÷Žõ©FhFaöõؤr`n<¡^�óÖ\ýTbøÖ?«±îag5ÖÓp•B¬½&‹žÜ7“pN˦eÙê1%Ëo¨"8ÌýÀ¿áHP™ôåšw²­ùdÛgk…ंœ ̼`ˆèo%?û"\Cí£g†öÔ$ȘeޏYDÚäã%íäLÿ3Ù|EDÛ™DUãˆ:pˆHøGþI!dW˜y Ž˜Y8rºæ9�£mDX�¿$¢ý¼7 Y;À̘/òŒ*Ñ*"ˆèˆ£©“Y8?ê³¾‡³áA *§ßD‰èI<•yUËÐF"i½ V¢�Dèx§Óh.JF‰ÐîfÚ€­•h#c‰61KÈH{,ÐF"úg_Ò>´‘‹±é9µŽÏ%16¦©U.Ž,0ó ú�BDë4BÜÛ3®3ó/ÄÃZV:—ê\QØF�˜7Ûod¿+ñ<3¿‚s��äГžØ2œS̼[‡¶µ‘ˆE‰eá×€%¸¹jÀ q™™{ž'ÍU$Á'@0€ë| ÂBL�ލw€áÐ3ïÀ-\PAÎø 3¿°�6™/Ï\‚[ö£ÈówŠ.­"nÑ€bÏž�¹ŠW8=•zÀ%fÞ¶S¢¡ h+o’EDû²\² ç“Ò•]W˜yÀK8­Òˆ@ƒ(‚&Bìö¬ ŠÝŒÛö µœˆ6˜ù\ÍŸ–pÍ\Û8Š`ˆ�n© ~qÁ[ ÎèÅìÃ1ÃÌSD´ `×#Ä^Û8 @ÃD°{çZk{–[»‡ˆ˜,mâmÇ<¢F] ™ƒkÔµËûkf~NDß.@‰hŒ,-$œÀÕÔ\u_j³‘¹‰ˆŽ™ù‘Víxç¿cæ 82t r�™÷ົ?œ6Â#¡'ô}8Á' Ä´‘îåìÂ1ÏÌ_¸²ÿ,$í¨��„CO³j¡t3óš%EÏl_�(Ø�´£V_“˜˜Ü$–$ˆ�Ïë�Êt•Ñ1=ƒ{e ‡§ê6Qµ!$¬Èn9H0ëW�3ÚïMg€œZ$æhÎõ,Ï=e¢Óä‘0ð,g�Ssä7K‹ˆ´ �y‘kO�¸Ô¥:�3€Ó„¼žQuð%.4ö!ëY—Í=�vI‹ �/é1Ü €¹H¡êØâMΤV$ úNx+P[¯‰ˆ¶ Þ¢ÚÐÏS³å½ %n+„Ñr9C' ®ö®Îl¤‹«&©W w ‚$qw÷lŽ)Љ[g’¡±h¶u‚g)a¾Úzh7”kF.4G„V»Ÿv1Ù2€ì}œQ<±ßÂÍQäk„ˆ`ÜàÖ,=…{â ¢W‰¯ùóÑBƇå4eAÚm¤÷ˆèˆˆö‰èŸp3kê‚È4WmDPD ® ¯í 1;ê‚P,ÃyLí}­D¨Dô“fáÄA÷®MÐ÷$ºp_ŒùD�­D0Dx�tæËäæêWÌüqÍU0D þ Š\K'SÌÕe8sÕ*í†ñAé„ÎbÞZ�b®€øËñÁ#"Ú@ëÔenxæ*ue_¨Šqîé n)ëÚŒgì´q`âô8tKó"D"võ„>ÑÌç}çy›×³²kãZ$âÌÓ¥“ e¾’*º,ÿv¨úÔ#à5¢.ìZ]Q5†ògù•ò}¿2¿éÇÌ7ÍC÷ྥט»»Šoú©üƒ4MÀ©×´çKº.ν±kÀƒ%é�ôXÒ6"zˆ{[dž� ‰�yéá²IÄç®7¼ÂiBJ}á½n„8g D½¥\7¶7o= ·R{[^ç]DôR¢¾ðþ-\ÍœFx‹ËöÌH[5`º¿·qZCàæ³¯¶IC‚#ñ¶Á¾Ô®n�ØÏ#ÄNµŠ�‰°Ÿx° –3Ýf‚èïh!!AáÍ[û/!Z·‡] ÿº BÂ'Â_A׎à\}xŸx gðΚ«H ¤Ú7�¬Ì'ýcmµ‰ÌXˆð¶ˆh#í(8ƒ§„ÑÓ2óZV%~4÷¯øS3y) õñL�Á@NeþdÀײ³Ê%ýβJÈ»ÚU]κ6dˆ¬We÷ë ±£_É�ûì~ú¿§wýÈ£U�ÞÛ€ûrè+2¯ô{\kæ9KÌü™q� ´\âê×ckç�Ûð·ÌÃ^ýNUŒ�ÇJ~¤Ú¬ŽpÏ«"sÀÿ-¦ÑEjlIEND®B`‚ukui-biometric-auth/images/FingerVein/12.png0000664000175000017500000000545415167732630017642 0ustar fengfeng‰PNG  IHDRbb«¥ óIDATxœí�ßoGÇ?c;v9U“´6‰rQ V…XD‰Êå…7ˆQÞxq‹ÄUZž�xpŸàpyEBö Ï�]‰P\„Z ®«@£Z IëÐÄ®íÓ‡9swvîÞ›ûcçîîM¾Òhv÷îž™=ß9gfÏÌî5x‘sÀ‚&€:ÝaÕój—çö9Ì5’zÕ4liØÐíMcÌ»‘ëµ¼Òåéš_®c>ȸ$ýãN.w•®Ï9Y‘5¹3HÝTÆ¢6´¼ëÙ nK¡°eïÇu­ôż+Ýå�-j:¡¡ç¬‰m@Kº½Þ…bÖEd± {»˜qËþ�EUpF•™Õò]‹¾ÒKãÐûº"í-ꎖ9óÞ:ÔoÑ«ËEDdEwV ªÐ¥ EÝÑz]ʹœ•6eåVN�uZkê^S>?äJÌxqhh+ŽÖJµÜ+ÒêÂÖ†m"rÞÝ7®TàZÐ*—†©Év‡× h�VÿÃ&BIo>÷ÑLõ9—Ñ(†FF!Dd�PH¿”IúÊ¡’1t"Ô”’‡ 2¢»Ê"ˆðÍ¿t$8d\ByÃ#BÒOík1ËÊ’Í-=üŠ�Ê’ ÑDì�±�¨^ n´áÕ;Z1L"Ö½*$lÒ$qX�XN|"‚›)m¿Ð’î/¢4¢aá[CaÏ ýBì3FT«ˆNDp•³‡À*b„Ñ›D4$Î|Ârž7 Iø8š¿nS®ß –#È�¢ÿ°‘œÆâbu…¸9Iž�Ã,w`­(—9IwüC}Izî J#‹!”dÎ’yÚ*cÃÛ^hwÒ ˆED]óÍÌ òþ°émÏç$³+è=¸òë1ʈE„SÔfdzz€1æco÷D^r{€»—(� w"Ć0jº›Š»9Ëëî^j!LÃ"ü“7Q[e—eG)?5o;o"ŠtM�¾Ç\0‘·@¼J~=lÒ¡³»c»Êo;XÈ¥Ƙ�½D-™>báß;™uhöG ¤—‰¦ "›XR6Èw—+bÃ}4ÉÕ'ön|õ¼¦×õº-ÒÄD]Û-b _c¡]‡¹¼,c ¶,è±°Ÿªa ¯›e HÆ´ˆØØ$YU�jÕÚ/üI“saóX—æ’ÃFôšñæ§#ÈöcXÅ›4vµÔË3�Wvî󨕲cÌ¿uàíd½=Èõy£j}ÄÈ¢ŠD4C EV"oT‘7„­Y‰¼QE"ŠsDC‰ØÐ¼ˆÀ_4T‘ˆ‘D‰ØrÞ»Ž‰J1J¨">jEW /T‘?ˆW/ªy£rD=¯èâ¯Ê÷•#B±ámÏb_.Émñ—‡ö€Ê¡Ê®ëî*É“ö°¥Õ¾_,QV°ƒ‚ÕÊZ[Ì0¸Êw‹›º?#éÏ"}¼·íÈ�³è�- ž;"ÏGøo¦.¿�“Ö�©4æ^¤ýw@–C"‘È^ô”ÑÒHz¡rGB:°’%[¯yL„Ên¨è¶Ký=ÅÞ‘V Yûq”žðd?šDH2�*ôJ‡kV¼ófÄZQCÚc]ºì� "Ti—ÄúæPñ>:~@Òîë’'{IZ­ §w¾G–±-~YÒ_%h×j:¾>¥JÏð™æÑ� "rpé˜÷Ó)=vø¥Û^ÃZÄ3Z‡ñ 9kø.– €wI[Ch¢iAåü˜Q¡ò~Þ.éþ)Ú1!"ãÆ˜ƒ®Ôú"Býí`’„·=í�zR�}G÷ï¿ÀZÄikq)$äzÝ?€)"Ú¹¦§�êþ¿4ÍÑ™?}–‘ûÉaxRDÜñÝAIé‰'Qø¤—|"Žz—<©Ç~�UÔŸ±á:BB¬òÝþ,Ö¥€m©Ž„1ZÉp®é²æ»Øu­stV~¨p{�4 {^yG±–æÎÙ‘=`ÏãŸ×5&ÀŽRH»·ï:Î l‹<ªiÊËÃôŒ'ÿk$d]ǶØ3$$ø)$ã•q 2ç‚úÒ„œÀ pøÖ>Né>¾â÷¼Ü¥]ï¾Îßèo4íŠHs›´:«Ü§ÕBœEŒÊpù¤þöÖ§±}À´q, 訧 €—TÆiëiG€O„#txž¤¡˜6ÉÝ‹`[ë ½áC=–¥ G„ON»sÀ,á4ÿTÏù¿n»ÊÛ Ží‡š>?Lc^î[Kh9azø’Vø�@N(ÛßÇÛ?qCóvu Kö>vf-ô×’‘wJ‡ù!ð-½~ ø·w܉e�Î$�“*Çs8`Œq? ¹üOåþ³O/ÿ l‡�¢‘ïéî cÌv?evY/×ÿ}hŒ¹™§ìÒÍY«b§t7t/†O¼Æ˜{À{À­˜$ÄFßzÊÛ~Û¯œ%é�ž‘`Ë�P”Œ{¡ *¡T!"“$�ý]cÌž1枺¸$UÇ�¯ˆÈ¬©+�RAÚ>òP·s¸åž^ÖpD¥QV"vÕݤ`Œ9Ð/¼‡‚u¯5yAD¦Ãkª‚ÒtÒG$ÜÕK"r¦Šîª4D�ûOvsAwõ4Ö]UÊ:JC„1æ>6pºÛVÝÆ]A:6Tz”†…ë 'èñeÅÀ]ÝÌ3D= ”Š�sq³}ÊØ®âƒ]©ˆP8%N�°´[”‘ˆÛ$#¡ÇDõí·u÷¸kG¥#BáûøGÂ*JI„óÜ›@'55Ò˜ý”Zìÿ£î‘ ag�R~qP4õïVäé·ðò<‹ ÆaŒùÛ€²^$Yž³ƒ��),Ü-"t3·‰!§ÿRº&h†Äý5RÇ�/kpoä:ðÒAûNz$ ©;¤£­#CH)‰Ðyiß"=w}»� $äÙ*�®Ê8g Éhi;ŒÇÎ[&�17Ed»lÓ-Ý<œ‘[Ø ßãèë Ðð·?oíž´�œ†føû&­r;Ÿ}®JR:"H÷ ÛÐöH=à„øD•"¤ŒDœÖüS�,rèöð&ˆþN )Á¼ujN!{œ¦ t N;BÊODÖ;c`ÚØ%ûÿ'š3x›«È d§È§ò,ø:#ùöQ½ˆÊøPåýÇs=kªSÙÓ ž#Äó~žuÍ uÍ7ÆH>Íöz1ué.Æ35rNç›cØ?»¨Ë¿ØÕ/Œ1þPv®Èº Õu]wßS?ú¦X•.¾ÒRlc—ÎÜ~؉eƒ$_H[ÕCo¦þ÷HZßÂï+žœY¹à…ŒGî¾4Ô  ·æ·Bš£&cÌXS¹ÚG£ü‘jEPï㚫ؗêßp>8Ù3CÏY _IEND®B`‚ukui-biometric-auth/images/FingerVein/04.png0000664000175000017500000000552215167732630017637 0ustar fengfeng‰PNG  IHDRbb«¥ IDATxœí�OlIÆe;qlbÅR,G6D±DÄ*(Q€ˆsÌ$N»âŽ Rಧ,®YqB€ä8 $\á�Ü@ ”‘VDDIHH+VÙ8±wœ·‡z5ý¦ÝÓÓ=Ó½ù¤RuÏTWW¿¯Þ«ªWUÝ9¼§`™l¸êœûnÆ´CADÎ_–ˆÊµ¤à�€›z|Û9÷�’˵ |'cò›_®;ç&exY†Ç‹Bžª·<§DdED®‰È‹Qʦy¬hE+ºœ÷G(ÛåxfWÌŸ7´Ð‹.tÆ[Ñ2¤á¾¦¹&¾]ÖãsCDVjz¶‹ ÏwÅþPW�©0“j~¨Ñ—òT}®KÒ_£^è=�•ùl)å[1e¹ˆˆ¬êÉjMz7AP/´\ï|ŸÕ>÷*ì>9Ët­+{‰Tù|Å…8f p_kqiµTï{Iö›°kUk‡ˆœÏM(E ¸«•—«„$›Ã[5TH/ÿª‰Pâ_xo&GyN%TŠÊȨ…ˆji—’ Q[Y)•¡¦  "2&""rHD‹È¤ˆ‘)™Öð¦M˜Ò´“zí!—¡Œq2J7•áf.�àœXÐox ?2ø ð`3q8væÜ™sÌù¾[˜Ø†7&a/!á—@èÆßvÎ}y¤€®üË BD&~¼¯ÿø¾þ>nÂXBìbâ¬$ô# ;þ5ðMÍógÀO�ŽsîÍbID¡DˆÈ!À† Ÿþ IŸß^'$‹vÀ~­ÈCBœw€)àwÀg5ïoÿ>¶Á9·7„¸z = jo‡‰„o�møð½ô}à#zµÅ†$B’´£ŸiŠ‘…>6ñYàçš÷ßðæÊ±kŽw†%%È"çEãD?l¡>ñ"nâ5bŽHc‚Ö„óq’I‰kGœŒ`š¬ô3?ý?~ü ø:ðUàkÀ_‰صÇ"² ì:çvóÈ4 K„š—1zÍBxø `8¢aÒÄI!ô=s¯{ú@IZcÍY68kÇöÛÿ="¡[2l Çÿ3yþø•þ·£áµž¿Ö°#"Ýczµ0Tн¤—öÛöP«Ç�£x»9Lk|D�-A–œãÀ;š÷�’Í—% ÄýÚ‹8IsÌ“ôF Â’c‰ØÅkñ"p¯놄W&ÞÖßÿ¯Ç!ÄóÛ‰ýÖ%â0«Ú²v9I ƒÂ2ðRïó[}€xÞýº¦I‚=§aø=ù qZ°&îð-½î/ÀŸéí ÇÛ¢¤ÞY¼Ý²ç€ÙÒÆ:2�6œs÷ Èo8‰ïF–:ë–pï³x-ßvÎ}TÆ=Æ'É™"2{e»­q®FAXÓxZD—qƒRˆÀ›º€¢ˆè¢,a¤`ÓÏöM5Ê"bFãí"=ŠWæ¸R"œs¯ð�,DÏV(Ê"bJãíÔT9#t¼¨|s T„©ÔTC¢p"Ôl;þ*-íèh<]p¾Y*Õ¤l EaÍFa¡(šØ<°íDáZQÖ†–%¸RìôX×EáYjW°À†:`›>$¨¹˜Õ0ޝÁÚÐŽ çÜ®™?+Ü4•IDgp’ÜÄNA·=šÅ“ïV΋"Ò¶ðÄlELÑ(“ˆ2òDLˆÈ’MÄ&¾Æ†ÿ&ˆ4%f%gXoiѨc”: lãoIØÄû²6‚94¦ê(^;&5íÞ?§é9çÖ¨m#Âb›Høûjµ²®!nÆŽ={Ñ=»¡Ð6"¬À9ç¶²^¨d­iþ°Ùi é¬+óÖñDÌŠÈx\¸z~¯IÚQ91¶�»iµP»™YÍR€]B”hwkš¤•úšÔÄd&A± qGí|XTª«Ü9·§»^ÿC´púpÕ&ª2"”„%=Ý! fý* hbׄûtȨEjŽîàýW#oG΋JLSŒ„p/c� æ²›¥y"-Èe^4íþ·W€ª4"Làtðš�Õ3|‰ �ãÐõ¬‹æšZ»¤yP‰F¨—tXÏJ‚ 5Œ-žg¼Õ’Æ¢÷„·•õšœs�s^´a'KÍ‘"â7a´œ�œ¡Ó7ô®¶ ÚÅ &i3Gïª1h$ôº»g2L�.iÜ:“ÐT"æÍq˜àYHÚhn<´à'€±'./G„ 6t?íb²EàLü]¬ê‰ý7~Ž¢ö½pâ1npk–îâ÷Aœ$z[Úéø|´’ñv9MQж 4Òι]çÜ–¾¬ê‘ "Õ\µ�"‚^mxfÿP³\‹x�©½®•h*;I³pê {ˆoìÍ–Dä :l%CD¬‘~š–6Å\}QD>×FsÕ"0ï@%ãFÅ>æêÞ\µJ;C„ú Â„Î|ÖZÝÇ\AïæøÆ£1D(B¦.3#f®ú®ìk*E„:÷ n!-mJkmØ5ŠEâäAè–fE‰X'ê ½%¢.˜×û€÷¼˜íYih kã?ZÑH"Ô™–NÎÕð êÊ1!ú²²¿G=žua¨iuEÙèÊ¿è¯néÜñ¢æù÷ó²/PÜžÔ¹{TD.èáç\ª&Gž 5M°o›x_Ò;êÜ;p xc‰ #} i›ôz[ !�$B祻Ë&é�»¾ƒÿSœ�B7¼W�&ÎYCÔ[ o-ÇÏ[ÏàWj?Õí¼óD›Æ÷ç´p5Gã4"¶¸lÃŒ´ƒÌC×ýý”ý2‡ŸÏ>Õ& iô¶ vS{p{ô ðb„Ø ¢VÒD"ì+ì‚åT·‡™ ú-$¤QDÄæ­ã›­Ûî$ž.…�æ_AWvñ®�’?›Ö�Á4W‘@ÈfÓÞéde>†ÿª.øOZÖ ÞcçÜ�~¯x ç ^ Ä9w·È²„e�oŽ·õäGõ”%7‚�gò ä‚Ìo�êɲˆ¬ÔT Ìн¡«º˜–¶ÉPY/ëé‡cjG?ЮŠÈj•¯PkDòh´÷¶ \ÕŸ>Pº ®ÈðX5ù,ˆÈã2>0Ï¥®þðÛêr»òéöšœs?Æ«Êõ!ÊøÞ(Ør,qÍu`YeÀ'@1��ïÐlIEND®B`‚ukui-biometric-auth/images/FingerVein/02.png0000664000175000017500000000535715167732630017643 0ustar fengfeng‰PNG  IHDRbb«¥ ¶IDATxœí�ßnÉÆÇÛÁ±ƒ7f�l±‚²„hWJ²ÒÞÆ÷¹Ù7Xr›Üì>AȰoHy�\D‘"­´«m‚‚0ÂáØÊ�1†1cN.êÔtM»§§g<Ý]íå“JU=ÓÓÎWçTÕ9U5BU½|f `“b¸ü˜³ÔÊȳÒl�‡iÆÒ, V¾\Þ~f÷=g `ø�•¿v€ÇÀ#à-pä>õ2rŸÞd”߇@艈ªê-àzA9ݳü.pWDû/ÄTõÀ�‚Lãð éÔJ•óˆñéðSàcà2pfÂg{üøø'ެ,Á§îóaéÐòoqdÜ‘?‚¡ª7�/ìË{Àm`KDþþJUg€œ@çƒ4—“Ïeg3‡#àWÀ/F¼\ÇÒ!°(°j÷X~”óÛGÀ×Àß8.ð°|H¶àÃ<]îŠÈ›a7VÕ_ã4û:‰µùJD¾ûòž}x]Dî ¹ÈƒÂ•ærÊib–€O�_âˆqˆ«Å{Àÿ€ÿâL•¤Î{‹#Ä›Ÿãy8o÷ ñGÆ_HHÍx–à‡¥×"r”%Ç@žŸã*<À¦6îOÀבּó¸Zº„3 g€EË`å+û´$/ü°œ6[ïì>¡P»öÒG$í…' /”ß’¤ ¶;á½vq$‡íÀ@M·tˆ#°kù« ?°Ï_Zù¥}ž¾^7(ß~ÜU}„S—O�0؈zBΘ½ çƒã9ÍU˜·Rå0-Ø}ÏBéš@º&¬°±I˜á8$£¬A I™~È ö½¶¡¥Û�P˜þøµ}–G”¿Æƒ&°\þ l‰ª*€ˆ¤U½4¨ê\ìÑž‰ÈNUÏ`ϱ¬ã*¸š¼%"¯*|'ÿª‰0>$yùî嫸ÆóÌã*Å¢}ÔTEF-Dd�ð\D¶Ë¾oØÊ�I*#ÃË?ËÖ–uÃ4 [±�`ƒ«];l—Uu6ç'SE%DØ ]f�„½*î=Rd,àž¹T¥Hæç1’àad´ípÙôÒQ:ªºDb{;1™£lẠëÖ —Š*4â’å=Ü FoÙa ×Å-¥¡ª«$&i§®.ê$‘}u®l­([#¼}íáÜÒMÓ \ªV”F„uWý ig”,F˜û^T©Z1ƒ³…íçM‚°·qâ^’ª®ªê‡ªzá¤×ᳯ”pý- =#"?‘÷J¸�èö”Ú†Y\¬au ×* k+|jê÷öò/Å4™Yòƒ·iiÛ�å­Ü³Ê�oßË2Oeµ¡ OÝìUѯO¡”Ë0O¥±lùÁéÐW)æüóæi9ïÜIQ>Ð�{ÖHZ™3.€¯“NbÈÅÔ‰0³áíø´ÝÈ=ËsÏ*¾R-”á•-C#B³15�0T9Ë@ØNL]+Ê "´¡e ®;=a|êYjW°„ÑôCH0s±biWƒÛÓŠ²‰È¡Ó „6ªL"z£OžØ3Ðo�Vp䤻•ËÀ†ªö€}lRZ•ÆA™D”qmODKU¯‘m":¸ë¿k‘h FL#'�p£Ô“ lüC:8ŸPÛ›ÃÀT-á´Ã»ã[“—UõIÕÓx²Ð4"B�ÿX­6Bö,¥Í؃s™jGÓˆþÄr…`díXòþ°•q®Q&EDªç²Œ³ó“^ëõŽKPÙ¼¦wÈG‰ð#ܪ=°¥¢‰Dx¤×Q4M$Â�%êðÀ–†&á»›ux`KC‰8•h"ý±„Mç<h"Ýѧ4M$"Ä©é95Žˆ”KâÔ˜¦F¹82pNUÓï#§�ûEપ^žæ|'›â9éÖc£‰Fâví¸üQÕ§œ Dj=± ,$«ª{Uh[‰ð“›D䱪nã¦ÌŸ·Ï7p!Ò±– § 0ôp‚wD„0ÓÓŸêýжªîàV'yA.«êsÜbú̉ vÍu’åe�¬ç¨l9A£ˆ`p6öÀœZ‹U<®¦~sXUÕ�� b!À£©Dìf JDömr@ 瓚ř–ð�­}‚Óª5’÷¯��¨‰0»½$�¼…/m¬–‹È}[Ç·N²cΕàÜÚ ðˆ†ë–zÁ/2|6_oD/fGÄ¢ªÎÛšî½!á¹µ“5¡ªgIj{ž[»CB̨e`aÛ±BÒ¨{BÎâußåýHU·DäÅØ/0EÔFDj’á̼³û«$DäÎA‘#U= Ѫ�Ô÷/Tõ>Ž ?¹¢ªm\w÷ûÓF¤Hèℾ�|Ö@Ì7ÒEgæíáˆXQÕÙ´píøaLÚQ9)pÛñ ­…ÖÍ,j–<Â)ôK¸]8�!&í¨Ô×d&¦0 ¿Ð¼7Æf*¡?*×U."G"ò·%©Ÿ8=_µ‰ªr¿¦U’}9º !˜¿ w.°ßøûô(¨EfŽîãüW‹üfš¨Ä4¥Hè Ö8o. ¸YZ#Ñ‚±Ì‹�ûxä‰% *�ðœq·hó¾B‹æm>ëFð›Z»¤ã �0/é°W”„Ô^»yç¸dyc¶$ò¨¬×4Á†Y^ºEj¶ª®“·ÃhyD¡³×÷®F¶ ÖÅõ&©óVuÃ% º»— „@/YÞ8“ä+áC>À³žµÐ<ðЂ E±&n\DG„ Öw?ÃÉdÀ5sKôažØábµ¯…›ѸÁ„fénÄ$;ó_IÇ£�ŒwÓi¦k |#Ý‘CÙ‘ïp‘5ï‚È5WMDTD0¨ ÏÃ/Ììx„ÇÎcZé®fe V"ºYQ8sÐ=Ƶ áŽf—l¿¿R¶ð©Ñ‘j¤Ÿå�›c®~®ªšh®¢!‚dI\¨8Ä\�Ç™«FiG4D˜ÊtÖŠÖê!æ ÇG�hˆ0øÚ‡. #e®†Îì‹Qaνþ.õ^c§‰»¨ˆ0x!.œ†niQÄHÄIOèu!ØÞœçõÔ,ÏÊCtDBÿ½ÐŠ(‰0g^e¢Zö_¥ˆÈoë~˜ž“taשivEÙèËÚh±ã »æ×'¼V¸�bxZçêQUýÄŠOE$× 3Æ5«ýCÀq‘Z¦ΗtÕœ{§®�–†7Ò§’�¦ÑaÐÛzj‰’‹K÷§M2»¾<å8!S]ð^5bŒYCÒ[ò»ÏââÖ˸™ÚÏl9ïÉ¢D¿à}—ÎæˆN#R“ËÚÁHÛkÀôÝßÏ8®!çpñì‹MÒ�èˆ`°mµ{·ÇÀ/EH j!1nñNXÎu{¢¿Ó@B¢""·N/B ÝCÿÚØ¦à #$~"Ò3èjÂ!εÑ%ûoÓú¼Q±Š B:±íéÊ|¸gåÍ:&„ o[DîÛâ�1#xžy0Íg�6-¿7|c_Ôó,cÃûxNÁ@ÎËü›à+;ØTÕÏkz Â°µ¾«º‘wnÌ0YoÚáW3fGoØ·UõV•[¨Mˆ’?òh¬÷v ¸mÝ0ú'ÜÔÉq+¸Îºª~¸ŒO ü{™«ßvër»é¯Óï5‰È—8U¹;Á3~v’l86'øÍ]`ÓdÀÿf$á …ðÿIEND®B`‚ukui-biometric-auth/images/FingerVein/01.png0000664000175000017500000000475415167732630017642 0ustar fengfeng‰PNG  IHDRbb«¥ ³IDATxœí�ñjÉÆ% /§ !#acg.$äààô÷ç¼ÁÝÄyû äCù5r¿Ž�‡%›ŸØë3à™ˆ¼ö_HpÀ?�ìO_D~³ào§BUoÛ¶õæ4/Âøôqý¼®¡{c¨êÉ.†ªx$"#BU?Ú—'ÀSàTDþ¾T/€ªî;þ¸¶mhŸmë¶müÖr¹|o«AU¿Ã‘ö�LÛ<‘ŸÄ¾<±ŠÈ_›î €ªî{Àfî«+œªù@Ucª¬gÛ-`cÊqÏEä|™~/ UýwÁI ã¢ëùú¸Ë$#ฬKÇ1{8U’r¼‘_ê8OÅ>ý 7?•@Ç}#"ÿl°ëvÞíàã+à}LµaçÝö™$¿�SǵÎ!súòGà9p*ªª""Å?«µ7�ûd1ÂШš0u¸O&!CQ-­\Üø7M„‘ðÙŸàþüÇ&Î?¥?7p…ŸàGÀ˦Èh…ˆ)$œ‰ÈÛØç-»‡ÚµÝÆÈðã¿ûDÁ ó$œ¦B€Ý\]Øîpßæ“FÐö‡î3IBãvü<äÈØÄõ¹4%wÈ&æ³Ið02ú¶Û³ =:¢¡ª·Ètï %uT€Sœ) °ozT4!‡ö:"sÊ% »—8µÝ œ‰Q‰0¿‘WIçm™¨‹@D¼£`7¶TÄ–¯_G@+>�%ñ&xU*¢ÄÀICc®ƒº`ì­¨¨R±†Ó…ý9íAhm,m%©êŽª~¥ªw–=VE„}ßžÙjqœý5ùmÝAƒït¿¦¹açÒÞ©áX¥as…· j?·ÿ(ªÉÔ’¿y«KÚ|(Wh~~ÛŠ¥žb͡׮öš°ësïc¨§hDø0ç°ÆI:tÀ5J„9ÿ¼zZ&~>±ˆ¸i¯ÃÂV�#´1g\!Ü,lµ j'ÂÔ†×ãu»‘GöZ” þ¢ÚŒá•�!¡Ú¨M" �EΦ œ'j—ŠD„:4ÖÀEÑÓsšàµKdTS0ÂÝô�$IÛ¸9d€»‡©åb‘�LƒsTL"Fó›T†'ö&LdöøÔ¬ìªê3ý87|›êm&bãØžˆ Uýšé*bÀd¶ß™¤`Äô1rRñ·q—º ÂÉ?$a€ó �s[Uu 'Þ¿� TíZ»7meû…è!†dƒÿÉUm„\Ú–Wca fÝ–ÝBèဿ1‡\)Yç¶yØv•cÄD§ˆÈY.=œž_ôX¿Òî}ÉËkúŒbt‘‡Û´6*ºH„G~E§ÑE"ü½DØhè"áR­•A‰XIt‘ˆñ½„¥s®ºHÄÕü&ÝC‰±2–SçˆÈ¹$VF5uÊÅ1»ªºEE¿SŠèœDL ÜoTõ~�ùN–ây¯®ãÍC%"ŒÄ]�-`ß¶UõK„HÍ;ÀB²ªzÙ„´u‘ŸÜ<‘תú—2Û>?À…H+-Î`á ‚ÏD„0Õ3Nõ‡qè­ªžãV'ù�ìPÕ3Übú©‰ vÌ}²åe�­çhl9A§ˆ`2{"§ÖbßÜvTu¢²A*xt•ˆ‹i%",9`ç“ZÇ©– à®­}ƒ“ª=²ÿßIaz»lE _úØU."/lŸ/€² |´m��dˆ0³Ôü³³ùFs¬˜8"¶Tõ†­é¾Ì¶m�h™«Õä¯ö"·ö€Œ˜yËÀ¹c›lR÷„|�›Ô½Éû{U=m£^SˆÖˆÈ! fæ Må s�DäZU‡dRužûþU}AV+jøRU¯×¢"r$”)ç'é²™y—8"¶Uu=?¸¶ÿ*%éhœˆ C\9ž™W¡™™eÕ’G˜B ˜:°)IG£¾&S1¥I0ø…æ£ ÅTBT¡«\D®Eäð3Yâô�¦UT“õšvÈêr\Q‚„ JV.jBV¤q.L½Àù¯^•ùM�hD5åH¯J^qaEʲÒ–,­¤^¬íë¹ # )‰ðœª%Ú¼ƒ¯Ô¢yËg=~ÓªIZ�H„yI¯©PÇ5WË㢨m€C{íLI"�Ƭ¦ fyi¸*se«ê>qoS¸[®‚$#t6ázëjîÜ`&®WIƒ”KÕÍB’D0éîî•�ÚkçT’GªD„%†|€gÚBóÀC .”Äš¸ªHŽXo~†ÉdÀ׿–Ã<±ÿÁÅ(Z_ ·(’qƒÕÒKÜ:ˆ»¸‰x炘ˆGŸÓiê‚Í~’î‹ÈGù "ÿÆEÖ¼ ¢P]uIÁ¤4œ…_˜Úñ.�œÇ´Ñªf1�*WÓ¢pæ {�›Šf‡Vï/J Ÿ&� ¹Iú}QÛuõ;U½ÓEu• dK² äBÅêê6N]uJ:’!Â|P> ³Wöªž¡®`rq|òH†ƒŸ }è²4rêjff_ªHŠsî�«Ô/xŒÖi¶ ’"ÂàqsÌÒ²H‘ˆK2Kè3m!(ïÎóº2˳Š�†PÇÿ_HE’D˜3¯±‡h¤€ uÏ*EZxN霑™°û´”]ãñ¯û�€;>°cþcÉc…À»6W�ªê·öö�ˆºa*³ÙVEn™8_Òsî­Üž,Ìž¤W’�®1`ÒÛº2„$I„Å¥Çi“LÆ®_ïø”�Z¼7�cÖ�YK¾jñ:.nÝÃej¿·å¼{d‹ý‚÷ :˜Í‘œDä’ËúÁ�¶—€=»¿ßó©„ìââÙ÷º$!ÉÁäÜ.j÷n�‰¼!a€¨S„¤HDXâ!LX.t{¢ÑAB’""·Î/B Ý3ml)8³IŸˆ|]Køˆsm\1ý±iãÞ¼XÅB©Õt Ç| 8±÷Gmt&„ Þ[y1«Ä#xžyYg_k‘½ž¬ÏmçÇvúRÞdz¹7r~ÌŸ¯OlçHUh©C¥ak¼©zPÔ6eØXÙî“5Ó£�샧ªzÜd µqNö �NÁ¬·cà©}ôÈ87x¬‹ã88ξª~¸ŒWþ™«ßv¼Ä¸=öÇ[M"òNTž-ÐÇï—ùƒÇÑ¿yÙ˜ð?æ§Ñ¹Ö&LIEND®B`‚ukui-biometric-auth/images/FingerVein/13.png0000664000175000017500000000532515167732630017640 0ustar fengfeng‰PNG  IHDRbb«¥ œIDATxœí]Ío\WÿDZ“Ðâ‚K (®�(•@q•B"ƒÄ>†lÜ ‰mÊ΀p¬ØØÝ±§¬ØyºbUňHlÆUQCÜ'rIjÇɯ‹{î¼óÞ¼¿7sïû˜ä']½�¹çžßýzç~ŒÀ€ä%+ê ƒbØ‘7 ú $/X°„D®%u°«ºz¿#"ÿˆ,×€× zïêõ&€›"òA^„kûAr•–çÉU’[$÷'‘MãXÕ‚ZÎÞ²­e#[7?n«ÐWC ]0c«*Ã(ôÔÏ]ZÓûíŠÙ&¹ZSÞ®æäoÝþèQ—€ ªÌ¼’ïKôõ2…Cóu�ÃkÔ¾¦¹3o#ä[5²\É }بI k9ŠÚW¹®NgcHZÁÒ))ÓV_÷Lªò劅X0‚xô´G+¥šîu6a[U×’—}¾á¥¨A€[™R¹V¥"˜ßÞª¡@:ýWM„’�Í|ðÑL y.åŠÊȨ…ˆjé—òÀ¤¯¬”ŒÊ‰Ð¦ ‘$xä�½©¬ƒ[ýG‚G†Œ[¤WLµoÅL+˜Í­�b¢´ª!‚É�tCÆZ> Ê@›Ñž‘;ZQ%Û&Cµ˜MÆÓ‡íˆéÄ'"“™Æö ÃÀt¥UE„­ µ}+Œ ºoŒ¨µ":™L´®6xdjE 3zŸˆãÌ'¬‡Ìóq´özHº¶@­Gˆ?Šþ³ ��Æât†ºZš9&ß@½*Ó�™RdŽƒéŽ¿ÒÑÓsQ ÁLŒH‘ÌyÉvÌýr 8 AóàÓïÄH#^Q;#}•€ˆÜ7�/„Š·|^¢‚àDЙ0–ô1Š{�ã+Ÿ—%F0ÓĨ¶Ä„&"j©,˜v”ôc±dîCáQgÓ¤ó³¡#„2Ó®‡ÀFt–t«1VàVùuá Ad‘ûƱ"N‹DxÄhÏ}œ ß­ ½L4’;p¤tv1‰ˆÑ|ôÉÕ/ö"mõ²º75Ü.ÒÄD][±†¯±0¬ÃÜð€¸B°¢ï²ýÔÜ¢áM;M1HƬ±±ƒdUuªTk¿ðŽ:ß„-Ã5iÞyt£KZhæ§#ÄmmXÙ›ÔvµVæ›À¤|»U5BD>0üv¼;A\ïN>4ÚÖGL-ÚHDßÔP§¡ÑF"üv©N!B£�DxÔa戆6ÑÕk†¿hh#S‰6±ëoªž»Ž‰V1Mh#Ku  m$Âñ:u ­#"3Ñóº.þj}_Ñ:"]s¿  K·¹$Øâ/50Vv@ëˆPewôqÉ—ö €]µ¨Ž½±D Ø€l¶¶¶Å4ƒkü~qsOŸ˜^ðLޱoÛ�ϪñÍ ‘ç#ìÎÔõÌo—8x˜Jï¤æ…ÃÏYÏùŒˆ$îU£Œ�þ€é…Ê# AÀF^ÜæwO£ºÔß(vŸƒ5d›îp”R˜¸ŸN"˜Lgfz}D˜ ão�®õ8Û,Ø!?D¨Ò®ÑµÍYÅ[Œ<€éæëš‰{�ƒµ Ôžï©%‚®Ä¯3}*Á°Rë1rû”*=×/]‡ža>‘f*‰`ºäZø¶}�Úd°äŽCln_BWz™t×xÂpwêˆÈ(Ö—[2™ÔˆB™Þo—«\æô8¢¿˜*"rHÙ,pŒýxL;1ò˜8æ×Ž�oõ�ˆJMªÈM}¼ S`íé ï_DÞ.˜”�Ï^åQ×7-Ã-ÏôèDXÉ^-†Õˆ²5AÃØ/éB¥�éMJ�¹djǰ&²ÝMÓ8$ä„+dYµé3°õtˆØ(K‚†ó£ŸBã}¦û†à'Ä$¢’µ¯"òÉ{pgˆÚ�Àä,p éWN‚÷wÅÏën*[„,"¿.ê—ä ïÀßHž ê`®@¿ABÜü—äœþöÀ©ôXÕ2¨t58ÉY§2nÆ\ýýß¾¿à›HFx– �oø­Þ¿àm ãI €'$Ÿèó㜫wÇ"ò$Tž‹"*$ŸÓ4¬ódI±„üÜDó#°‡ÁÚ௿3þ�0š€c{Oòؼ?ðH¯Ñ„’§xwÎüô5}—%Ã’’WK~aâx ÀŸlÁíÊ’ð?ØpGÄ(²do•ŸGÄ,ÉS"ò¸„šFb,"H œ‚ç�àïϯ�q£Iñ„|À¢†ÿ€¯èýOáæªÿ‚ô"³�õÝÜFº6! Oùöj�ÇYçIú÷G"2Q�)EÉSH>gœ%⌠rƒD #æ4?6áÿ¬q\…«]çü@n·Ï‘úûÀ_áˆ÷$ k~†)>{„4 >-hŒŸ#’GþyœAÁ,ÐWp¶©ð šA¢à³êÎ7Ÿ¹¾lâÿ ÒdÍ#! ëNÁ5k¾™9ðC}_;×$½ Wò÷á”k›+Û‘gk‚%Å’ñiÅ™«wŸ›x_…«¡õ·‡ê< ù¹ú”IÃnÓäk„ï(}Éô×9}ÿœ!áœ!ãœ!À»/�¿®qÌg±ÎÖ† &ì1€‘Œ¦¨™�3aõ½'#Kˆož¼O̱Þg•䟳Dªóø2\Ax¨ à�úù¿Þ{—�ïPャ�Hv81H^pDä�%Ãþ ŽŒÃQ>MãU¤]ŠÈò2—�ïWzûžˆ¼2îD\ð”V‡º¯è㮈|Z Ì"€‹H÷uwÜ 9¢1é]ÑÛ�DäNȸ›´ÒÏ*n®HÙƒ)}b^¿à{$Ïæ‡j&C„6)ú¸¨ˆ"áëA'ÿ‚k“=ކi$C„â®^gQr³¢ˆ|&"ïø‘š¦˜h:+æG'ÇŒcO›¬V¡QD(¼çI~µVI*D‰ø‰]çuAÛv?t}^‡µS�Æ¡°müSQ+I„ˆ!Ù tAgÚ¦³Ô£Ôbÿõ¸‹d{@#Eœ}ýûÕz^ˆˆÇ2q ‰ËÚ“àL ŸM&áDò7qxý7²imެQïy¯�üÎ4và�%Ã;é©$¤mD ùƘ*BIÝzÕy}ÜEzRæ6€�0HÈ·Û<ºjê)—~´t 7Œ=à[pJŸ‘;$÷àfè‘ _ ù œÑï™õu¨ùÛO™Þ3_Ú¾,}ó÷ Ö� ¾O·¯¢55¤qD Ý7ìf�Ô^†;AÔ*BšH„_Óô 3ÿ<Òìa&ˆþ‰Ò("tôã;éÔœBÆì±ˆ!‘£„4Ÿ6ãï��àL‡Èÿÿ‰þ ÞIs9„ÔùUž«ó$guêÆB•÷¹�7Õ©Š,5ƒç ‘‡”5:zíÎ 9šíÍzd) o㙟‚9¯ó�$»);¡÷œÅ€®wòCÕ—ê”e¨®;úøÖŒ¶£7ôÅ& œÒÒìÁ-�9qZÓÀä„´M}u#õ¿GÜ…_&ž‹$¯“ñÔÀçKMýþÝÆzëŸÒ5é·Üf�²ˆòGª-AgŒ07á6Õ÷÷~ Q±@-‘IEND®B`‚ukui-biometric-auth/images/FingerVein/17.png0000664000175000017500000000521615167732630017643 0ustar fengfeng‰PNG  IHDRbb«¥ UIDATxœí]MoI~ÊŽ?â xñÊp\i%{  éC´|ÉîkçØüûÄÕáŽ4³w$go+�äIN,Ò#Á i¼hÑ®¡l6^'‡zkúížžv÷LUŒóH¥®î©®z»žzßú®1P yÀ¦8ˆP =cÌ�‚a'É5ë:ˆåꈀqÐÿ±1æo�åêØ.¼/×{îc>ÌŠp�“ãÔËW%å¹Ar‹ä!ÉÓid“8¶¤ ù–s0…l{éÈÔ�G"ô-ßBü°-‘! sH[€öÄT cŽHnÕôm·2¾ï@ÿèP—€«’™Y%ß•è�2…C¾k‡ã5êTÒ\ ùm9òm)Yn�dWnº5 ´‘‘Q§"׆çtºcÒò–NI™‡yÏX•×*bU â0�R¬”Jº;5a‡UkÉ5÷ÝpRÔ ÀÃT©Ü«2#˜mÖP mþWM„��þxï­™òÜÈ(•‘Q $ÔR/e�q]Y)•!¦ ‘$8d�ÜTÖA„VÿÆ‘à�"ãaéUG“½öÃ�iù“­¹½‹ß˜*­jˆ`ÜD#m“±–Tˆ(¹ƒÕUq¤>¨–a“IÀäˆÃQÀt‘ú˜ÆÖ ãÀd}¤UE„Ö†Úú “‚¶�T+‚‘úˆÖiƒCJ+B £‰0Ì|Â�Ï`<|Ì^�IW¨ƒñÉÿt¤§¶8í@]-fŽqhPeºS#UмÌq0YñWÚúbrî H!˜ )â9o ž§m3úÊ¿9.Ð4ED$×ãÌ òÉp¬üëžâ,ù—~"�PD¸Œ:Î UƘÇêöU_ñ–€û– …À;´C¹õF„à‘çøÊÀ}K‡†iBh„.1¾‰Z* ¦$ýDt”ß7uš& ù�^pÅw„PB¦ìº#§²¤]�± »Ê¯ÛXð"ƒ1æ±€èøˆS#!칋3†õÑ&’ËD y KJ~[q^’ˆæcH®ôØ‹Øêuq»òÞ ’Ä][¡š¯¡0®Â<pÀ¦1ÆÀ‚My–®§:°‹†{Ž›2 R#BãñªêD©–zá]q΄­Ãš4çúÁ%­TóÓâÖcXS�7ÉØÕ^™>�JÛûÁ$˜“VJ#ŽSK¡‡¸ƒ·_Ÿa1Ìÿiššc"žªùšŠ+ý÷εÖ!š¯.Â&›& Ù©‹`ç"j'$K„ Þu2~Š0ƒ„4’ÑÔ;?=@òÞ>É$BrEÜU’Ë$—H.’\ 9OÒT%ÿ$¨ôpE’W̧ܜº:ÿ·¸áì.€_ø"€%·a›´o˳xÀŸüÀ¿P¹îJò…Ü?ϸ:wnŒy&Æ#($¯IÚ9Ò¤hBôè{ læÀw`Ï{ý#,A¿p – Û¾à?P$ Ÿ€sí'y®žŸø\®Áà…’ œ[Q?}Ež¥ÉФ¤ ù€_Èû÷å™>åm¿‡%çÀŸ¼%nÀOÅ=ð!§ôg\Ó™ŸEÄ’óƘç¥3k &"Bìí€EÄ8ÿUôˈ‰X@>)Ž�xEÞÿ€oÂjÉnø!€÷‘<þðsX�€‹û ¬–üÙde¾¾jçpÀk$Ýó3cÌTSŠ’óˆ3|Q9MIJzå5Œ5Ž˜X"Þ’wx à°Dü–¸à¯Z4¹¾KÞw¼.Ͼ'Î &~ŒìŒOûÏ�$áL¥· `U…9#yæî�1¥ûPC"H.!i*\Í!Îà«â–•[J]¿­â¿�$YKˆ H»yØÊ÷ëòî?C²9™Ö\‡5OÎ!åkªÜý,©Ÿ`T ž#™ñgêêÜgê»^ðKØ‚r&×§žø”ägþóTšpç’Dø’¯Kì¢dÂ5Ä$¬ &c1ÎÖ.ÏI¦.JMˆvZ–ü1a_C²5u®ü_…Õƒñ„¸:aN¾"iœËoéLr÷i"ž‰ûDÞ»k2ŸJ†?ð©„y"~çÒñ=¿�Õ* Æ;6½¬~ y�äM’7/=QüoHüo„ˆÿ‚´oŠ»î)¾ 7|3‡¸E²›÷Rƒðo¹.Ió¸Ípy~<‡ä$Lã§&�1®²¬Ío%$¯#¹½;'«öåA�Nii>‚µ¿×-HY0>!­'�ö+N8º ¿ º*ž uD�Ȫ#8zêY Ï úÉ·vø ,‚ü‘jKMðÎ=ØMõÃ}…ÿ};íD‹Is¢IEND®B`‚ukui-biometric-auth/images/FingerVein/11.png0000664000175000017500000000550115167732630017632 0ustar fengfeng‰PNG  IHDRbb«¥ IDATxœí�ßoGÇ?c;ÎbÜ´iJL*_Ô*(…’(åG”\‰>!D-$o.ðRʀܞ]ñÄ›ýÈ ÔvB©ŠK#•¦»b%$²#‡˜ëØ9<Ì™»³ë½7{ïÝÙn¾ÒhgïîΜ9ß™33gf÷<ˆÈ$0¥ I6Ìc¾›ñÞ¾ "§�3@ƒH®†€ ‹_2ƼX®9à匷/êñ"pÑóAZ‚3Ò?Ör)U\žI™‘ "²6ˆlšÆ´V´¼å\@¶™db³ÞÅú\ÞBg,Ø´ÊÐ ËzϱhFã ³ "Ó%•í\Jùfý‹e 8®ÊL«ù®FŸï¥rh¹ÎK給yއ,[ù¦=YÎ!"sz2W’@/¥(jMåz)ç|æ:ä•[>=Êt¡­{‰šòé‚…÷qXÖZ¬–j¾çe· »Ptë‘Ó®Ü8)JàR¢VΩI7‡—J¨�VÿE¡$$ Ÿûh¦y&S*Ead”BD ¥ôKi�¨¯,”ŒÂ‰PSPIRÈn*Ë Âoþ•#Á!AÆ¥ò+މÏÚ/„Ì+H|47óà'Ê«"$¢‰Ø!c)¨^ ftÙ“;XQ$ ^�Jq›ô‰{枈Da*Û/t‚Äû‹ •¨("üÖPÚ\¡_ˆ�cmÁ‰H¢v­Á!Ñ*B¸ÑÛD,K˜õ„Ù< ‘û8˜½î�¯_¡f¤DÿÉ Dr‹‹uÔ•bæ$š-™ïÀHÔ¢\Ö8$Þñ:ú’øÚA�J0"Q¢5oˆÖiëŒE/>Õé¦AŠˆ¦—RÈûÃ’?“Sš™ epù7C䊧¨¥®wõcÌmïô‘¼Òí®,A*AîDˆua4ô47"ë9§× \YÀM¢Eø5&o"‚ÖÊŒyÉ? /ž7eš&ˆ—1Œä� ž� »ž–èÒYŠÝ�1…Ýå·ˆ,ä"ƒ1æ¶ç€h䑦�D8„°ç.Í&´û£)âÛDc‘%,)‹ä;ŠË!‰a>ÚäêŒ=‹­>£á}n…81A÷ÆfE¨ák(tê0W€×€)cŒÁV‚)ý-ÙO5°›†ç�¥ª8$C¶ˆÐX"ÚU«ÕÚ/üRƒ3ag°&͇Åà’–ñÖ§¤íû°ò7©ïj¦—9�—wîëØµjƘ<~›À¤õÆ Ïç�ºõ{u$¢íj(Sˆ¼QG"ܶQ¦y£ŽD8”áæ†:±¨Ç2ÁPG"ö$êHÄŠ‹½vµ&b/¡ŽDøh”-@^¨#¾¯Y–y£vD$z^ÖÍ_µï+jG„bÑ‹Ÿž\’Ûæ/u0ö€Ú¡Ênêé<ÑL{ XQ�jß/–(sØAÁ|m[[H7¸¦ï67/ëù¸Ä7<‹ôñÞ¶# %�iïž`nðÜx=Â3u6qmRvLeùAæE:d6IäC"¢´§=eìê$¾Q¹+!]˜KK[Ÿùp!"C"2""ûDdTDö‹ÈYѤß‘�xá�œb×Dd1¡ä±Gé‰O®`DºB'"#Àp" yG7ÿ"ð¼†/xIý8‘L^�¿¾‰õΞ^Äîà8Áîõj€??Á®Ö툈1ÆúmL„ˆÖ<üàH’òQàóÀg�“ÀÙÉÞþŒU¬qYyÇ÷¼{¿üø>ð-àÛÀ˜wýwÀ�màcÀ°-"Û.®áž†`È…Ù¸pÈ»ô¸þ–$Ã…³À Àià©.Y¼œÒøŸ€#À£I14øoõ¼ü¸¼üø:ð ½þUàWØñ.‘â�ò“q‡a2ÆÜï"sOè›F‰pñƒÞmG‰ˆØGœ”�¤$}ø7ð>V‰+À爈ø+ðdšH^¸LŸÑã}l ß~ü øžÊ÷40üøp›Hñ÷Áá𨈸ß[Ƙ�NºÊ‚žˆ‘a"…�zÁ'â€÷Èvµø ྊ¹I¤ð7‰›­ l_– ÃXóâÌD¦é¾Æß×ç>|K®onÖ�Ÿb[„›°}Gφ%{‹8 [^~€qïž-Ù¶Œ1þ}™1 "F 懡D|¿FSâîè�½ì&îY¬½F•ò:°¦²Œ�ïOuÌÿžIÈæà÷~?ð<ðÒÍÎ{X’^T~ üëFÙÄ*{ hyiÁšÒ–w­´D¤üOó¢ÊáâÉs1ÆÜw-™ŽäqT•qkrªbbkÅ!¬òxÁ7_&NÔ$ð)½¶�­¹'5¯aïè‡Ãž‚OhúiÇ'Æ'è,‘irÇm�;RV±ƒ·þ%,™> >'±�MUú&–ж²ÜÕã&Qkºç¥åÿÖ‘-vÜN|éÎ]%ÝΧuÄ U¸Þ$ªÙ�é5£B\SE$‡¬.MBÏ×´€É–àà~žÐø6p�xÿá×RGŒèÑ 6ÖU‰;^ØÆ:øÖ”ÞÓkÎ|%û•-ïùd%ðÓÞI+Ð@‘ãXåaŒySs$ ‚\1ÆlfHËîí,ö×Ïø{žïhˆÈs½fŒYÍ+](ÎûêÌKfÇô¸ž‘„ƒD$¬xQ& ™YëžÕàVVT©nNr3cV =nS³µíÂ\Ƙ«=>âZC+KÍV“䈻:踾hTraHç+GõôV†ûG‰LÒ†1æ�ÏT •$;ÂrSEwCC�µ3IU%☞‘ãÚRbPÇ¢›À­ö;³-•#B»_OýIÔpJ«fƘ;X‡ÝMcÌ�b¤ÌU|cÈ7KW°“É'‰fñO‹È°âj¿’q§hAóD¥Z„ö®“^7ÆlcîcÞÁÎf�+º«¹ª#*EñÖpÝ¿ fç2ñ9Åði��×U%¢¥æ&cÌŽ~9à]¬ß Ô¿%"'uXKT†ˆD'ÝÕ�ÓÅ\=#"'êh®*CÖ éð yÐÑ\=�5Wµj•!B}Pzz,k­î`® ¾¢VyT†…ë GèñeÅ„¹Z}èkêÜs“¸ã}¦q£Ž»J¡pJÜ¿†¥YQE"n�„QÔ¶;7ö˜k÷<*G„·ñŠVQI"Ô™çÞ:ša=¢öý”Zèÿ£î׉†°Ç�J~qP´õïÞcÐoáå‘ð®í4¤uŠhz»�¥4wwˆí4Nÿ•4MÐv‰û;ËÇ€OªsoÏuà•%‚Î�ôž$¤nDl÷¶îB*I„®K;—ø ñµëËDûf!"ä©:�®ª¸f ÑhɽË0Œ]·F�1«"r»Ûã‘“ð¹I wsT®E$6—­{3m׎AÛý½Êîr»ž=Y§R9"ˆ÷ 7`—Û#6ÁKâ/ÕŠ�*á6—ÝMlXîêöðˆÞ¦†„TŠˆÄºulM!áöðw’¼¯ !Õ'"¹ƒ®$la]-Òÿ¢½‚÷ µŠB6Êœ•§Á×ùÑ·�šeãC•wÕs9m©SÙÓ ž#Äs%OYsBS�‹CDŸf{¥Yz†óñìß9§ó¥!ìŸ]4¥À/võ }÷Á U'ºÝ[e¨®›zúÚ�ÚÑWõ‡ù,_i©n`·ÎÔî…‰¾�6¯?½ûß#Ùý°^0ç¥s\Džó\Æ{®\êêw¿Í  ·öǿڣ&cÌ�°Måb2ù#Õš ÙÇ3�¦ê€ÿ¶GÑFƒ…QþIEND®B`‚ukui-biometric-auth/images/FingerVein/15.png0000664000175000017500000000540615167732630017642 0ustar fengfeng‰PNG  IHDRbb«¥ ÍIDATxœí]Ï�GþÞîzý#‰ÖIŒ%G�ÄyQ$¸ y.H!y/\8°Î�ñ¬ÿƒ5W.»¹qÊ:°q‼�‰p˜µ„lÅ8ZGÆ1»^ûãP¯¦_×tÏvÏtõ�q>©ÔÕ=ÝU¯ÞWõêw�À€äE+ê �bØ‘÷ ¾;H^°  ‡D®ž:ØS;êß‘�#˵àjÁ×wôz À-¹“à'Ç~%©JËs‘ä*É-’ûÓȦa¬jF«ZÎÁ²­…�­›·UèËU ]0a«*Ã8 ô�-º ´¦þíŠÙ&¹ÚPÚ.g¤oÝþèÑ”€KªÌ¬œïsôµ2™CÓu�ù%j_ã\Š™¶1ò­Y.ƒä†Þl4$Е Eí«\W*Žg#'®Êâ))ÓÖP÷LŠò¥š…X2‚x 4GË¥ï5Žš°­ºKÉK>ÝðR4 Àí W®Õ©f›ÃÛ dH§ÿº‰PÂÄWÞš)!ÏÅŒLQ�‘AB#õR˜Ô•µ’Q;j ZI‚GÑMeDØâß:<2n×_}D0ÝkߊW`º5·vüSÅULšh¤k26Ò�*5£#w´ú¢N"¶M‚6™L�8lGŒ'>AbZ[/ä�éú"J&ª‹[ë+L º>FÔR�ˆ �+ A©ˆ1Œ>$bÀ8ó ëU&€Éðq4{�¯ÍPëÂ�¢ÿ0²¢¶8Ý@]#fŽIhPg¼S#ÈE•Ìq0]ñ×Úúbzî J&˜‹(’9o ™§í2vŒ%ï¥i‹ˆ¾^w3'È'îñ/Wf!h|üýqÄ"Â+jwì[% "_˜Û³U…[>-Q2AåDÐ aôô¶2"+¯ |ZzŒ0L£DØS5QseÁ¸£ÄƒˆžñWM„G“¦ H§±,T Œ��]¯»SYÒ­ÆX�[å·×X¨Dù @ôªÓ"1ì¹³ 룤—‰¦@rŽ”TÛŠ«1‰ˆa>†äj�½ˆ­^Vw]¿ÛCš˜¨kc‹"Vó5ò*Ì=7¬ˆˆÀe‚}ÖS=¸EÛvÛ2 ³DÄÆ.’UÕ©\­õÂ‡ê¼ [†3iÞyìD—´ ÐÌOGÛŽaM5Þ¤cWkeú&îÊç±;U"DäŽá·à£)Âúhšï«F×ꈙE‰54)DÕè"¾ ÛkRˆªÑE"<š戆.±£×&þ¢¡‹DÌ$ºHÄž÷Ô=w�&b–ÐE",zM PºH„Äë7%DÕèÁDÏU]üÕùº¢sD(vŒÀÝæ’ÊécmtŽUv_o7‘ô´WìéˆêÄK”€ ¸FÁfgK[Ìap ß/nèýÓ žÉ öm{2ÂY5ïD¯‘ç#ìÎÔõà·‹=Lepœyaþ9 ë!‘_‘„½j”1R0½Py,!cØÈ [¿ùŠ { Aç.õ7ŠÝçh Ù¦;¥&ì“&Ó™¡B¯�ùfü·DWŠÌÇ6 VÈ/ª´+t¶9T¼Åؘ6_WLØk-¥ö|Ï,t9~�éS òr­ÇØíSªôÌwé*ô°…UøDš™$‚éœkámûÕd°äŽClf]B—A¼k<¦¹;sDеGÅeæL&%¢ÐFF¦÷Ûe*—Ùý�ÇÔ3ED cÍ'Ø�Çô±c�‰cvééCè»Ñˆ¨uˆC¹©·ô ¬=½áß‘÷ Feç³{ã^ÔõMËpË3=úV²×‹¼Q¶$è7¶'](2} I©3—LéÈ3‘Ý6M“��ñ]¡‘U?+=�"6Ê’ ßùÖO¡ö>ÓuCå'Ä$¢–µ¯"òɇpgˆÚ�Àä,p ©WŽƒï!ŠŸ×Ý Ô¶YD~Uò“ëzÝ‘�{Ys©'îf[wÕ†,Ó4AKeÌÓMÜhçðÅ4Mm�¡»jüýõfη�A[‰¸nü}èhÖ‹t¶¾ÞÞhËž¸Æ1­ibzrgÀ4Ì‚ kæÞfäƒ_4ÓtÕøûêìž¿bc¨ty_D¾ÛùÞp•˜¦D•îVðÛ5¦çö9f‚(^¤qÕøíØDä7p%bS�p“ œpß LY"|�0öÈ6­GÂɤÌÓ*³DTŽI‰`zx¢èpw–¹Šöï(/„iÒfg©ýq9æêÝDR§Î™m  _/\'ù:É$Iž$yŠäi’gÔ½Dò%G~ àGþ¦ß÷œÔoO�œ¯?)åPë†w’ æ7g®¿ƒ›: Wq@ÔùLãïC üÀÏÀ3_ðÜEÍçꮿ…WH­õD&‚äˇuž€�OÈïüÀ¯üEŸ‹¹"ãJsý£^‡$àxެŸä‘y~੺h¨„’'xwÆüô5}’aI ùü ÀŸáHðD„$ ÅÜ8BBÅ{å‡~�y’s"ò¼œ¦ò11$,"!ÀûO›×Î!!âÆ“â 9ð/oø!œÉ KE–iÊ"¢YÊ·Wë<Îx�¤~ "ÏŠê. ¥ˆÐJÏ+|Ñ8KÄ)óÉ«%*�˜HJÈÇpD|À÷ÜÕßòÈð¦É–‚<ó“§øÐˆ4 ‡&¾S–Ì;‡$Šˆ}¯0€¤O˜us�ÿ¤q‹~µ�ªF‰Ë"Æ’³ ñýOü}ÿDbž²Ì�®'li(JÀP©×C¸’êñ*€·ô™ÿíÀÉ•ý)Ò&ÒÊ•2Ÿ"òÜ—«{]„ˉ/ÙœÓpÅò´*éŒ*ÿ”qo�€4Q¡òm\óæ:�Ä&¿ GnH@žƒñÛ„Ûr¤~OƳ€œ,,ïø1€'ªô'¾Ôw«ÿ±>Ã;ž�<\ Û¦$~aò-ï#ßœ„vþ3W�ÿ€üÖ‘÷û{A:Ç/ø††óÀ2n‘õ ­;ŠüÒD…õ‰5m4ÌOüi³ê•Có}˜ üóß ø¡= oj�¼à ó¯S†õm$­°GîŠÈ§“p*yÞUï]¹WQ˜Ú׳B[e¶)ü €o‘|Gû'3…Öàõœç3IH׈x„¤Ÿ)BZI„Î+œÔÛ=¤[,ŸÀõ+BBÞRsÖI´õ”K¿šûnh|®û €E¹Gò>€óêô›³$¸7iǪ)´®DhïýœÞ>Ô¡ƒÏ‘”€ó "Ï´å–�s¾C7ÿÝ™Ò:"�®îNépdÀ9«à€�æÛNÒF"ÎëõKybžß7þ‘Š\ ¹×™ì!­"B[?¾’¶Š‡Ú|?•z9‘Ã1„´ŸˆØ+ ânˆäÙÿ?ñ™^Hæõ3dò¨É^y¬Îç�œ}ÔoB UÞ¿E䓬ñ}U¤oÊ^(æù´JY+B_¯;sH–3^Ï~·uðc<'g #çu¾;‡dåD¿èz¢&!"¶)ûF“²LÕu_ooΩ½¡6Yà”–à>ܘÿçǽØ609!mSÝHínâè.ü2Ø0á\ ù®2žøtéP¿¶1…Þ†g… [MºÇ­÷w1eå�T;‚þßÜ‚ÛT?ÜWøœuÕ+ëÀÒIEND®B`‚ukui-biometric-auth/images/FingerVein/18.png0000664000175000017500000000516215167732630017644 0ustar fengfeng‰PNG  IHDRbb«¥ 9IDATxœí]MhdYþn:鞇Ɍ´08B \è®3Eò–ºê {SíRÔDqŸ ®'DªÆÙˆéAgå"Õ‚ Qé¢ËJ¶*¤{%�I÷çâž[ï¼[ïUÞ«º÷ýTúƒËû©ûîÏùî=çþ—�É Ûâ A9 �1Jú� $ïØÐCš®ž88#¹?5Æü=rºú%½�äúÀCcÌy^€ûœAr•MÏÉ’Ç$/I›„±#-t:Ç ¤mßìPýx"‰Þ �è’Û‘4ÌÂXüÓ }¹?)!˜’; åm+'‡úG‡¦¸.ÂÌ+ù®DïV)’¯]ר ‰s=fÞf¤oG¥e $ò0h(A÷su!éº8žAA\Á⩘¦ã‰ì™Vå{5'b]%Äa,¥8Z)•xw9­ÂŽë®$ï¹|Ã¥¢�<öJå~�‚`¾:|Ü@�´ò¯›!ÁÏ|ðÖL…ôläŠÚÈh„ˆ±Ky`j+k%£v"D´’‡2¢«Ê&ˆÐÕ¿u$8xd<®!¾úˆ`¶×~3®`¶5·ý ÅUL›h¤m26Ò�ªQ£c•îhö¢N"NT†6™ÌŽ8œDŒ'>^fZkŠÀ¬½ˆRˆê"B׆Æú ó‚¶�µVD'ÂËDçjƒƒW+b £Oˆ3Î|ÂaÈ 0>ަ¯ âÕê0BøQäïG@j‹ÓÔ5¢æ˜ö�ÆuÆ»0¼RdŽƒYÃ_kë‹Ù¹ƒ(…`%F Hç¼�tž¶Ë©ûí"O‹ ‰\Os'Èçéºß f)H\üIŒ8báu:ÓWcžªÇ7C…[./Q Ap"h‡0zòŒÁ“ÀáU�ËK�†ibÔ]bBµT–Œ;Jü1ˆè©ûÐD84©š€lƒ`5t€P‰ôôzœb†±¤]�± »ÊoÛX’cÌS5Ñ ¦F "bèsfLìÑ6²ËD3 y KÊa[qA“ˆêcB®ôØËèêMq{òݲÄD][±š¯±Pd0ÏØ6ÆØB°-ï|;Õƒ]4<pÚ–ɘ5"6N‘®ªÎ”j± ‰s*lV¥9ç0ŠžÒ&@5?!l=†µÐx“Œ]íW騸ƒÏcwªFcο €G „õh‘ïC£k6biÑE"&C M&"4ºH„kÂöšLDht‘‡&†9¢¡‹DŒäÚÄÀ_4t‘ˆ¥D‰8s7uÏ]ÇD§‰X&t‘�^Ó ….¡ñ’¦�#›èéËâ¯ÎÛŠÎ!©ûM#ÚÍ%ÁÉcmtŽv"�C¤=ímg2¢:÷Æ!`Û(v¶¶Å—ðÝâæ±<¯3»à™œcß¶# 'œå'Ú0xpDž�Ð;S½ß68}˜Êø:õÂâs@}"_‘†½£„1e˜]¨<“� ò–o^!a�%èÂ¥þJ°œ®!'´‡£T"@…}3‰`:�é twÆ7åo�¶�YŒ–4È7‚Ú}ZÝì ^cæ‰Ìª¯û*ì}NׂJ{¾—–ÚÈì©E¥Öaæö)z®_Zƒî·°JŸH³”D0[r5œnß§¨ Vܱ£ˆÍµ%´`ìÅ»Ïkš»KG„'X}T\nÉdZ#Jmddv¿]®p™ßÿs†½X*"rH˜©8Ç~)a¨‡ßvm%bOÝ'�)Ð<�´¶DÚ²'®q,ªš˜�Ü3‹1s† h›¹�ùàÆ›¦šúê>§÷D¸¡c>0ƼÛùÞpH,R#<£{ìý¶Ëì|ÂgLÅÀMª}u¯Ç~`Œy¶F å՛ިÀ ÷�À‚5ÂÙ„™G¶‰ñ'“rGLC"f�Žy‰`vx¢ìpwžºŠöï(7B5I³³Òþ¸uõ�v"©Sç̶†�³ {eÕŒ1æ©ü^‚ÈǽÅD[‰pgi”†1æ‘1æ]ØÎàÞ˱¦Å;tƒ2» Ü¡àjE¯¬Ñ^´Ž1Ú#yì7—’zÑ:"®V$ìêþ„Šh%2t&�ýæRRZI„ÀÕŠ~×úó`EZ)­8NÍÃiï ¹dÄÅDþ‹45 ^¨ùê…åÿ½s£ö"FóÕØfÕd;u ì\Dã„Ä@k‰�Á»^ÎO –��Ö�üÖÒÙCx—†�V!­$§–Ž�=U¹k¼}B‚nx¯m4Öž‘Þ`v=ë=ñSyW袈i¬[G³+ÀònC :Ç-„Ü4"vT†·Ôû�zŸ·Çz�Ó'%ä¦1ù«1’k$o“¼CòKJ?%ù)å^Sî $ƒ�˜DÔz²ÄwËs+êúU¤ ‰àsŒ¸ ðeßð¡¼\_ø €_ø€oÉû>€�I^x.þôÕ¹+cÌ‹@Y.� $×C/Ð"ùºÄ¡�#À'eÀ'~ ` À?¼#ï�\?†%â ßð•ºj÷¾„÷ÀÛÎ|Ó\é{’Wêý•¤ë“p’‘ĪéàUضy"îÚå﮸ ` Àkê§ÏÈ;Ÿ MŠ&Äø €ß û-¤$¬À ò¿îÂñ/� ϽP×!¬`ß�Wús®Zøþ½Ã*É•5'‘ëhéßÅì¡$o#þšºUy»‹”ˆ5Ì&å:µåy«nîøÒáò<" Õ¦¯®¯Ú9¼ àÓ$ÝûgƘçee§à[Ÿ®Âv˜ö`'avfíÜ$y ©Ào+§‰xE}ò¦‰*"f i ÉS[®Æ<ð Àßð{díƒ#¡Hý Þ¿¿D–„K•¯W¬+?—b{.�1Ú_!h§�yZ�¸&+qOòÎ%7(yƒäP‚¬„$Ú(ÑZ±â•ƒ³vÆ{¸¨SÓgÊ=ãžq÷t·7¿TªêéêªêóW�ª:UÕ#8¨êiàsËÃ5ù°`ܱ ª€gÈÊuÆÀCs·,|GDþVq¹V€_Œ~ËüÀ y”—àeÏKy«þòœVÕKªz]UŸï§l–Æ%«he—óÁ>Êv9M슻yÓ }±ìB|±KV†ax`q®k¨@—-|³€`nªê¥šÞíbÎû]ñ7#ê*àQf^Í�5ú£Q*‡½×G:¸E=·<�VùnCÊwÉ•å"ªºb+5èýA=·r½_r>+ò*-ŸËt½'{Íšò… â¨+HīŕÕRË÷#ݭ®Oºu¨ê…øÞÄRÔP€ÛI­¼¶€ûÝ»C&|> œ²èNÐOÒ 7Lmmº"œ'S{½b‘Ó/°7yÂ÷þ+àÏÀ�w€ï€mU�÷·E¤;Š SŒD„ªN“ |ƹC‰ÿ ÷Ø�¯ÑOT‡ÝÄ"k!yjë-—æ[AöŠf¾oƒÔÏ Á§ámþ·Ëë—À5»ãl«jïzÔAöÂQÀ©ªˆ™2!½6÷†s³9þO,ý5à ³ô«0ï¦é'#m³®Ü?¾ $å;ò´%¤ý@üý‚ßv~tÏ�7�Ÿ–ÿK»÷Òܰ©ª_ØýWIžpŸÿ«Ø"¢ ˆ53ú3öûGœ#cÎà‰yÇÒ]¾n¿ùÖ“ö')ƒú‹ˆ£V¦aC[!SOJ éZ8R¼N‰Ø2á¿IØ5ò¶#"ú›ïŽ.Mo˱¬;@%s‡à]»üTDVKLû�¸'"ò´¬t æ½HAAئ³ïŽÚcjï(#cÆ…7Æ/KNol¸ðᲯ‚ˆy®Jpó{G)Û.hd­šCU¬Î…Ó¨­""¹Ìôü¸iE³D#PÅ<â5Æ@‰ˆ3Ü™¡±Z†61»w”ö �DĹDé³Û:ÑF"âp³t{O�h#m$¢7—PÕ#u¤L´‘ˆ­º PÚH„Ç�9µŽˆÄ$q`TS«L98¡ªsŒhwj"Z×"̼í1œSÕo™…µ¬|ŽëY¶±Eø•¸gvÝ[üQÕ'ìc‰ÔFbKØ’¬ª®M¢µµ‘ˆó7E䑪>�“öûa‰txXt.%ÀÐ% ^áaª'ΨW¡·ôXUW ›¿¢ ç�wUõ3àé � –æ"¶bgèZú«l€ÈE«ˆŽ»ðº¿akO€sÉ3'�ãªúÔ/‰6…€ˆ¶ñ,OP"òÂ6t6©¸g¶œRÕàSB«ŠÇ F"M„éíyç"Ò³ëX-‘»ªzœPógÍ�uqk' ¢1Dذ4 ~ŽÁ»ùº{Œb^ˆ˜SÕYÖB|ÜÚI€š‰Ðpæ:Ööafí 2b†µèï;Ž‘uê‘�£„N=y¿§ªEäó‘_ DÔF„M–NäÜò;ó6Mï'#bè$ÙQÕM²VµšÜÿ\UïȈs�³ªºNî~uúˆ„„xöàAðy±ØIÝ™·F ☪N§ÂµëûMj'"!a¸7¬Ú0³¨ZŠð[è�¹‚mR똨­ÉTLa ‹æwMÏ�·G 5•‹ÈŽˆÜþC¶qzfÒ*jbD gìr‹$¸ý«°Gß�<óéR°™:ºK°_Ý/òL™˜ˆjJHè÷ Ö¸¨. ¸ZZ k#©‹[ê—ŠbR-".àt -¡¨e4ør7§°ý¬ñœÛzÝCÒQ0‘aVÒ`­( &Ô8·xV0«3æwÙ} ¾Ñ˜Ø¨ID�øHl [Ej¶�úŒÄ=nÂly4r…Î:Ü8ºÚ³o°!nTI#Œ®ƒFA¿¹{¾Àèó[§’"šJÄ‚ ǞŜõjo¡…°Ôˆ3q£¢qD˜`ãðÓo&[ÎkòqF³Äþ‹°FQûY¸qÑ3¸ƒWK÷ç N‘}÷ãlºmd¼ÞNS¬/ˆ�ôºˆl‹È ù„°²MCÕUÑ("èo Ÿù¦v¢ "b‰`1õϵM%b+oÎ t�}B<'ÑΨê·mØJ4†ˆ¤“ú  !êê;ªúvÕUcˆ ÿÓp…¶NPW' êªU­£1D˜ *.è,­ÕÔôŽo<C„!vÐqé²0u5pg_SÑ("̸'q‹ÃâIcµ�»FaˆBœ=ÃÒ¢h"kd#¡×DÔ÷y–×s¡6&VÉþÈ£U°ÑÛ áo6>ÿ×̪zEÇÇŠKgQUßs&ãƒø^fê�¿­ìCnWb:½Q“„ÿi^nŒQÆöŽr`±<Æ37€eqÿ�ýHë#0ÀU�IEND®B`‚ukui-biometric-auth/images/FingerVein/08.png0000664000175000017500000000554115167732630017644 0ustar fengfeng‰PNG  IHDRbb«¥ (IDATxœí]ÝnÉþÊ>Ø`áÀ bbk Ž– ÚU"P¸K"á«Ü®ß€ä Ø<�÷ Ø70oûx•ÛDxµHQPˆM@ ,ŒìÀçàÊEW�©iÏÏØÝ3=^>©Õ3sfú§¾®êîêž3f¾`Q, îÑŸ*Þ{(0óU×Ì#+×¼X—+r¼JDßE.×2€?V¼}Eâ{îÑ“¢—øðx¤Vùò\bæ›Ì|—™_¥l’ÆMih¡Ë¹v„²-ù‰Ý6?Þ—Bß]芻)e…5¹ç.»´$Ç÷+æ>3ßl©n7 êwÛþ¨h«€gD˜E-_[ô­:�Cêu‹Ë5êµäy&fÝF”ï¦)Ë 0ó²œ,·T / õZÊõEà|–Kò –OÍ2ÝÊž3U¾Úp!Θ‚(Ö¤Gk¥’ï-ÞoÂî6­Ì|Uë -E xàµÊ¥&ÁÅæðA ÒÉ¿i"„¿òÁG35Ês© Q4FF+D�ÐJ¿TÎúÊFÉhœ1I’ ( #º©lƒ«þÉ‘ ðÈxÐ@~ÍÁùYûݘy…çGsK?q¤¼š!‚³!³2¶2�ª1£k¦ÜÑú‹&‰¸o*ÔŠÛä0à¼Çá~Ä|âáU&Ù~¡ œï/¢4¢¦ˆ°ÚÐÚ\á°`7Ljªщð*Ñ9mPxZÃ�>$b�ã¬'ÜYÎÜÇÑìuI¾¶AÝŽ�~ùû0‹³sÔµbæ8›­5™ï‘áµ¢ kœïø}q~í J#‹‘(²5o [§í2VÌñbÙMGA,"$^-\ ?VÍñµ@iV‚ÔAó_ˆ‘G,"TP«#ïª"zcNφJ·´.QAp"ع0æå4‚­ÀéÕ�Öež#¸ibh„m1¡‰ˆÚ*+æ%ÿDÌ›ãÐD(Ú4M@¾ŽAÐ � L!=»«ÑY²Û�±·Ëon°¤ DôÆ8 æC¤iƒE {®i.Ãþhùm¢90ó*)+;Š Š˜DÄ0CreÆ^ÅV_“ð¥<·Ž<1Q÷ÆVE¬ák,”u˜ë¾°HD×åšßOÍÃm¾`5‡dL�ˆ�Ud»ªs­Zú…o$¨ »gÒ4(V¢—´ °YŸŽ�¶õaÉß$¾«¥:s“wðuì$5‚™ÇàÌ&yaÃÜöfþ«>b/{öˆhx} àÛXu¨‹F‰`æ€q/Œ™X�Éœ“9·ø €�mò&öI`{̼'çï b "Ú U窈J3Ÿ–V+rö_â"³c¿kb }“þE¿ðƒüöƒ„>3�‘×Bmì×Ð÷ªãž04ž�ßNéã)¸>àSÈtÎ)>—4&‘'¤Œ�Ëú‹1äµøS‰íמ«yâa(–œ""ús®x'Bà­Üó_9Öà§×÷®õì0´ù~°v¹H eá8ÓÁþQ�l‡¦Eå€Oø¹œÿ[„p¸ ö â=¿“ç×üË\·¦°htæ÷[¹|ˆh¯2Ñ 2fæwþ#éþ=Dš^ú§\‘Óu"Ú �Lj¼µÿ{ND/B¦Ý5§ˆhÇœžn­ �‘¤‹£Î3ó€§A�Cç4B†ÐS®0ó'Ì<0ŸsMî(ì¢FاWrÞ“ø,3?°EDU:ñ}�>hÀ´œo6¡m]$bFâ·Dô„™ŸÁÍ-.Èõ9s̼ ×™Wš`ùpCïDXˆéQ_Öˆká3oÀ­¾© §üš™_xQæ‚�4g‘Ÿÿ $ý��þ¤QèΙãÜæ"Ú³t%ÿ.8ÇÌ/ˆh¸ž‘ Š®ñªHPD´#.ìܬvδô\dæOá´jYý[#@‘4b·§MPŒšÄmAZ9=dæsp-_}a—ͽ­ H†–ªà§�¼Åà€QÌSÌâ‰ýÜE¥¹FŠHÆ n`ÍÒ#¸mš‘mï¼ì¯G ¶Ó„‚ôÚIoÑ.íÈŽÁ§È\#ÍU‘ÈkÃKûƒ˜uA(æà<¦ö¹N"U"úE«pâ {×'¼•Ë=¸Œù¥L;‰dˆð:é‘|G˜«Ï™ùã.š«dˆ€Û®¨´u²Ä\]€3W�ÒŽdˆ”.èÌTmÕ%æ È¿j•<’!B ´.]V†g®Jwö¥Š¤ˆçžNâfGÝ;"��.Nì’"B Bœ<ÃÒªH‘ˆMd#¡D´±íêÆž–aí±GrD¬�ÿQhE’Dˆ3O·NžùJVªèé_©Åþõ!ðÙv-í®ˆ�¡üõŸÆä¿ðB$< Y¶$¢¿1­Ï�­CoýßÜš»›™¯Ëa°÷¬UþIš&`ßkZ€ó%]çÞ±ëÀ“%å�ô±$¤kDl#ïm=6„$I„¬K·M"¿výÀsì'$è ïM#Å5k - à†±ãpëÖÓp;µ_Èë¼3È^JÔÞ_¡ƒ»9’ÓosÙ–™i«ÌC÷÷ ì×�ópëÙ—º¤!É�|ß`_jW·Gn‚çbˆ:EHŠDØ¿x°–Gº=ÌÑ÷è !Iá­[û/!Z·‡Ý ÿ¾„¤O„¿ƒ®%ì¹6ú(þþÄpï µŠB¶SûO'+ó1dÿ¿ÐFa,DxψèaÙ_< æ žBD�B–5$^Cö}…/Û)Km¨�gòLäTæ«cp»€ô9˘�wt¨:7êÞ”!²^�Ó¯ÇÄŽ~%î°ûlpêßžÞ€Û:Ó¹Rdô¶ ÷EøŠìw�8ÿÙãºX6éÌ2óuã2>6Ðz‰«_¯-AnÃÏ2GMDôg8U¹wˆ2Fù�jG°pˆgîX™þþ¼/W›„ëIEND®B`‚ukui-biometric-auth/images/FingerVein/09.png0000664000175000017500000000543015167732630017642 0ustar fengfeng‰PNG  IHDRbb«¥ ßIDATxœí]ÝnÉþÊ66xq`kb´„eE””}ÎE®³N^€ä Ø<�÷ Ø70o`òxor±Ò ¯‚´ 2( #;Ž©\tÕ™šöÌxÆgz¦Ç›OjÍÏééŸúºª»«{Î ˜ù*€E ÐG9Ü#¢?—Œ{,0ó 7ô�”«'žJ€U9_#¢ï—kÀŸJF_•ã}÷‰èYV‚K||¼®¥Véò\eæÛ̼Â̯Ç)›¤q[ZÝå\£lK~bwÍ�¤Ð·ê.tÉŠÝ–2a]⬰k@Krþ „`0óí–êv+£~wí�ж xN„™ÕòµEß©Ò8¤^w8_£^KžçBÖ­ |·MYn�™—åb¹¥}‘!¨×R®/jÎg9'¯Úò©X¦•‘ì9Qå âœ)ˆb]Zq°V*ùÞáÃ&l¥ií`æZoh)Z(ÀC¯U.5)Î6‡[h�NþM!$ø•¯}4S¡FäÊŒ½Œ­¾)áKyî)ÒÄÝ[¡†¯¡�×a>ð5€E""¸F°(÷ü~ª·iø€µX’!5"4Ö�ìªNµjéþ*AMØM8“¦A±¼¤m€Íút€´­k,“ø®–ªÌ LÞµ¯cwJ#ˆè™á·à›1ÒúfœçëF×úˆ‹.1r5´YˆºÑE"tÛk³u£‹D(ÚpsC‰X•cŽ¿`ˆrÔÄÌp�„2Â)ï#=µ�g„>Q£ï�TA£D0ó€I/L˜£ž“¹&s ;&É?øV“7GŸð�™?ÈõAÆQÃ�ˆ>ÔXíRJ3Ÿ•p%H@1C{ÎÌCsགྷ¡"˜ùœÉ8`Öüô‰Üóɰ¤äiIžvÌ›ô¯ø�åIð ðo…ŸEÄ3OÑAeaåàXD0³Úêi$èùõ""N¡˜”£Ì–bò[êÖÎìp4Y·Gg|ÌÌz@DciL%"˜y‰À§M°Dœ6�|ŒÃDås ‰†ä™-ÛWŽˆŸø€ ¤µ Ïüä Þ? M‚5‰§œ3qÌ<Ðëã ¦€‘€}S¡™@"à3N›0ãnÒÿÒdÍ !À“H“‘g®&ìKZ€Óºßx#÷-|M°¤X2�ü@òüNãÞ™t¯ø€·òÛ[ ûö˜ù�Äïåa ·ù¿W�Ч-S�Órÿ¬!aÖ�1kРCJø©¤1ãbƒÕ=æõz®$ 1[êEÕÖHHÌ#­!C9÷…4”ç.¸ é|àßH“üŸŠðßÉqOâüWÎ5XíHœ÷’�Ö�5ƒ™\"ú.@ú×áÀý Ú¼à’uÀS"øiä¤{®ÜsæöÀs"Ú’8ŸËýD´1F5!Ê ]˜yɨldäòœ™7áüO*È9¿aæ—6òF8’æœ(†’þf�#£"tŠ$æð6'Ñ€™_øÌ{æ€ ̼AD›z3]%âU– ˆhW&cSpöy®?™p…™çü N«æ‘Ô¿5Q!v{ÎÅVÁcÛ�VND�˜ù\ËŸ‘pÍÄm�E4DH§«‚ŸEZðC"Ú-HjŽˆYfž–ŽvË#ÄÆm� e"dá^[ûlAÔ$Äi�î;Î#éÔ•Ý$=%¿ÿš™ŸØ•X ­!oÞ\Ìøi×Rwà†¨»Òš•ˆÍŒgF ¢fÞC¢U›Þïo˜ùçádp�™·á†»?ž>Â#aNè»p‚›ñˆvÒ;%ç[pDœÏrÎÉõ“˜´£q"<ö<.j…2Ì,k–vÍâ,œûãbÒŽF—JÅÄ”&A° Ç¡ÎpK`ÒœÏ䯂Ó"zàŸH<»ÓM›¨Æˆzr¹�$ÈHJ7 ö Þ3šÏ%µHÌÑ#¯<)óL�hÄ4y$ <)ÙâÔ\åÍÒ<-¨d^$n+Ûö›Òˆ³rÂiBV‡œ]�Û.ÓI3óˆÃQžiuHZ�h„ìY=°U–ªÎ-^•̪'Ç!’ÿ ï5ÑóŠ�¨6ì—iÙâ~WâžÇ0[®‚(7˜I‡«£«#ûâªIÚ©0ºŠQ�´»{N]„ž;g’±a·ÌèÏ‚hJ ÆC ¸ R+r±!:"D°:ü´ëÄ—\÷ßðOì?àÖ(JÍ5bD4npk–Ãm8¸‚d£Â5fN­G E®ñè•FH_ �ô6 ˆh—ˆ~€[YSD¡¹ê"¢"imxi³£.Åe8�©}®“ˆ•ˆý¬U8qÐ=ƒëöäöÜ?ÆüR&��D4Dx�táž¡sõ+fþ´‹æ*"àv¼)Žš7È5W—àÌU§´#"Ä¥ :óe[u޹Ò›†£G4D´ƒÖ¥ËÒðÌUîξXâÜÓIÜBQÜ‚46»8±‹Š� qæ$ KË"F"¶�Œ„þOD[Û®nì9ÖžxDG„ÀÚø…VDI„8ótëäÅë�Ç”þ•ZèïQ/‘ aÐÒîŠÐÉ_ÿiLþ ¯Ž„k{u˼¦¸ÉÞ‹#v‚EˆW·TþQš&àÐkZ€ó%}&ν×�GKò;éIH׈ØAÚÛzb‰’Y—m›Dzíú€8LÈ/º<ºŠqÍHFKC¸aì$ܺõÜNí y�wÉK‰çáÞ‡x…îæˆN#¼ÍeÛf¦­0ŒÜß8¬!áÖ³¯vIC¢#é¾Á¾Ô®n�ÔÏ#Ä.uŠ�‰ÐÍeþk\…n³@ôwt��¨ˆðÖ­ý—­ÛÃ€�ø‰¨òÙ1€smì#ûû£¼£Ö*2ÙisVž+ó $ßÙo£0"¼çDô(ï/PqO !¢Çu–µ&ôå¸:�ä/ž¿l§,•¡>ž™0‘S™¯MÀ}ìú\Óç,CBÞ}Сê墸1Cdݗ˯'ÄŽ~%7î±ûlpìßžÞ„Û:Ó¹Rdô¶ ÷Eø*õÝ#Nö¸*–M: Ìü¹qŸh½ÄÕ¯÷–Ç�Ûè³Ì£QýNUA>¤Úô�ñÌ}}‘9àýÛh$+IEND®B`‚ukui-biometric-auth/images/FingerVein/10.png0000664000175000017500000000555415167732630017641 0ustar fengfeng‰PNG  IHDRbb«¥ 3IDATxœí�K�GÇgžŽã‰�Ø™0V"_A„‡lˆ„‹ò*-ŸËt²/{MºòÁŠ ±;(ˆÇEkÅÑZ©å{T׫°“U÷U=èë�/E 8“i•Ǫ„æ«Ã354H'ÿª‰0²•/}63Byä4ŠÊȨ…ˆj—ò ÉXY)•aª ‘$xä�]UÖADØýG‚G†Œ3äWš^µŸŒ™WÐôlîØÆol)¯jˆÐdŠ¦ê¦Œµ, F�©Ñ‹A¹£�Uq:¨P-f“Í@Ó‡Óó‰OD¦2�AÓãE”FTao¨m­°Y¨[cDíщÈT¢u½Á#Ó+b˜ÑûD\Ô8û Çˬ€&æãhúz@¾aƒ:!ý(òÏf ZÒ\\�¡®5§Éèb•ùn™VTʇ¦þJg_šÞ;ˆÒÆb$J²ç É>m›±„EÚ b1oþrîùæ°„•”f!X|þó1òˆE„ÔòÐX#@Dî—{ÊJwøºDi¥¡Î„ѱËÒˆ0Ü.9½QàëÒÑfš="l1eµUÌ;Jþ1ˆèᲉð¨S5AºŽ¥`¢ì ™Ñëe`™!ƒ¥ºÓ ¸S~K¸ÉB)e‘;�¢SFš!báCŸû4ç¡?-�>&š‚ª.ãHY¢ÜY\©ˆID õÑ'×VìEtõ!s¯Ø{—HõllQÄš¾ÆÂ óð:° "‚k v/;Nup‡†OËM1HÆì±±Lrª:Õªm\ø™9¯ÂáTšwKÑKZ4ØŸŽ�vhÃÚ’½ÉlWÇFYy—¾�ݪ!"—~ç�7·�Ö›[y¿l´mŒØ¶h#}SC�…(m$ÂOa;u¢l´‘�:ÌÑÐF"–̯Ãð m$b[¢�D\ò�ª÷®c¢ÕDl'´‘ˆ�º PÚHDhÄ›¯«e£‘D¨ª¨ê¸¹ U�TÕ)U�Þ ¢¾l‡¿^PÕisSæ&íÝqUmd=CTjkRÕq`Üòõá±À÷a ®%¸ÆÂ>cׇ€_¿~\4p]ÖúÐÂ�9þ}óˆˆ?H6/"oDÅ:D%BUwY¡Ë##Kˆ÷%ÇŠ„„_Ÿv/˜{x ø'Fà xô‚ðTõUàÛV‡k8’”*œ J!BU'€)`Ø"&NÊ BÂÞ±ø‚¥}xÚÂo^>< |ø®×üžÁL_¾fïyüø!p Ø‹S]�{Uõ>ÐÖDäaQÙåa$"lÐóŸ \HÄŽà•ÇYOÔ b&IzÈ µõQ¢/Ïø¢™G„ÇÀw€¯¿Îà„ß³<>|‘t/~ø ðo+Óã8Ö‚8;€Ývï>°¦ªk@WDB £0ª:MZøƒÜtðÚc¤‰ Éá›ü¬êú¬¥{gô ~<¸oï¯á,µ³8¡}ø4núûð)Ò�æ�ÀÏ�ÿX»IðÎc 7.ùûýò!ï‰ÈHcŠ@_Íd…à…5n™>bn§ù;,= ö"SGçp¦“ EÞ)•¨¦ =àBÁçÕWK³$½`$õbqk9¶_U�Øe~×òä<Ìš»È ­ª�`Sg{§òAw³¨¤GØ™ÕÀÍ¢$˜PýÚâFÁ¬:æ÷hÙÞve³¦a‹°ð½¡[p±5GBÜ•ºÖ›E#·mÀõ³« Ç›âz•´2Âìª1h$$ 8€ô0tÌo�Jòh*³Axø¤ªÎYOIÁ¶cý‚ïjÁ•wãÐ8"L°~úÙ ížËþÂGDVqVÞY_›ÐÄ_ …jé<Îþ ÉÞdzªº‚[#¬AŸŒÕª Z&Õ#l,ðƒômY‘Uù;ð6‰ b¨ºj#EéÞp-|`jÇ› <öã,¦á{­DS‰èšºIÁ t—qcÂ=»=�ûǘÛ"°•h ™Azèî×uõ1U}º�êª1D�Þ3ßhÝ TWOáÔU«zGcˆ0”ßЙ-Úª¨+Hi<C„ÁÐ~ë²02êêêû¶¦-ÀŒ{~77,î�4®·qa×(" ^ˆÓÛaZZM$â&ÉLè}"ê‚évoÆž±ií¶Gãˆ0„:þÿ¢W4’3æùÿÜØW`?¢õ˜ð¥û{Ô›À5’)ì5�®ˆ�¾üý?�Ùá•‘páCÈÒzŽdzwø·6swŒCÈ^þ�TMÐ7‰‡'Äg€�˜qoÛ à�%‚Áƒô¶$¤mD¬�¶¶nBI„íK÷�M’Þ»>¼ÃzB>ÔæÙU÷¬!™-õpÓØqܾõ î¤öUU½Ž;í1Kb$Ü£ª7háiŽÆõˆÌá²ÛÁJÛ÷€Y蛿¯²¾‡ìÃíghSi¤Ç†ë°Îì‘Zàe 7ˆZEH‰ð‡Ë²?ãjö6ˆÎÒBBEDfß:û#ÄÐìž$o!Í'"{‚®&¬áL]ò¿?ÑßÁÛh¯"‡�•:Wåye>Fò÷�óu&„ œËÛê4AŽ´ƒç ‘óe–µ$Ì›¿4Fò×l¯ÔS–‘ám<ÓÛ`!çe¾<†ûØÀ¼–ô9˘°ß>ø©êþaq› “õ¼]¾>fzô5»qBÝgƒ›þíé븣3­ûAŠÍÞq_tx-õÝ#MöxT,éÌ©êó�ÉxÛÀ×ËLýþÞâäÖÿ,sÖ$"¯âºÊ©M”1ʇT[‚ùM¼s ÷Ç�¯úÿ3š « óÉžIEND®B`‚ukui-biometric-auth/images/FingerVein/14.png0000664000175000017500000000542015167732630017635 0ustar fengfeng‰PNG  IHDRbb«¥ ×IDATxœí�Oh]YÇ?'MÒ´¶“‘©:£6âŸAA]HŸ º°Á… iÁ�HëÖMºw‘.܈‹D7*éàÊIféBqêK¡Ni™±-cÿ$“æçâüNîïÞÜ÷rß{÷Ü?¯ó…Ã=÷¾ó÷÷=çwþŸç0‘³À‚€ŰꜻTÐíP‘sÀ<0G’®95[j6Ô¾éœû[ät­ :ßÐçuàºsîV^€K2<î—’«tzΊȢˆ¬‰ÈýQÒ¦a,jA+;�ÝÒ¶” lÙü¸®‰>_v¢ flQÓÐ]u³&¾-©}½€`ÖEd±¦¼�ÏÉß²ý1 ®Ϊ0óJ~(Ñ—)š¯ËÒ»FÝ×8gcæ­OúMZÎ#"+ú²RS‚.ä꾦ëBÉñ¬ôˆ«´xLÓÚ¾ì%©Êç*NĬIH@WKq´Rªñ^–ƒ*l­êÚ!"çB¾ ©¨!72¥r©JAH¾:¼QC�ôò¯š%!›ùÒ{3¤çlN¡¨ŒŒZˆÈ!¡–v)’´••’Q9ª IB@ÑUeDØêß82dܨ ¾êˆ�ô¨}-f\e@Ò½¹¥Ã}ŒW5DHÒEñ]ÆZPƒ@Õhפ;Z{Q%ë&CµL› IÏ8¬GŒ'>™Ì4¶]èI·Q QUDØÚPÛXaXˆcD­щÈd¢uµ! S+bL£ïÑ•8ë Ëef@’éãhúºG¼¶@-G?Šü³ˆ”Ô?QW‹š“d Ô­2Þ‘‘)E¥¬qHºá¯´÷%鵃(…`"F $kÞ�¬Ó¶ƾÐËÑ(ˆEDGŸ›¹ äÃaÓØçK ³4!þNŒ8bµÙ×ÕpÎ=4¯/–îy‰RJ'BüÆœ¾–F„âAÉá ‚�—9‰0M£FØS6QKeÁ¸£Äƒˆ9c/›ˆ€:U¤óX &˓Ȍ^/›ôi,ÅïÆXÀïòÛÀwJIƒsî¡™€˜+#L‹DÄÐç!Ìì·G ¤·‰¦ "›xR6(·W*bC}ì“«#ö"ºz^Íõ·Eš˜¨{c‹"V÷5z5˜[À5`Á9çð…`A¿eÛ©9ü¦áU`³)’1kDll’ìªN•jmÞTTØ<^¥°=¥u@Ìút„°íÖHóM:wµ4ȘÀÄ]ú:v«j„sî–á·¼=BXo�â¿l´­�[´‘ˆý©†:Q6ÚHDèÂÎÕ™ˆ²ÑF"ê˜æˆ†6±¡Ï:&þ¢¡�DŒ%ÚHÄV°T½v­&bœÐF",æêN@Yh#v¯SW"ÊFëˆÈ,ô\ÔÍ_­o+ZG„bÃØç� ñ‡KJÛü¥Œ•]Ð:"TØ}]%i/[:£:ôÁ%`ß)Xmmm‹9 ®á‡ÍÍ]}Ÿ•ô†g‘!ÎmrÂY4n¢Mƒ—ŽÈëödêræ·³rð2•îaêEzß²œ%ò#"’°�0´’ިܗ�>¬ä…­~>"BÃîjÐ=·úÁÞ—ƒ5d]üå(`Â~>‰�d93+ÐË}ü¬w³âkQWzc] 6ÈÏ*´ âusVð}o�´úº`Â^’ƒµ` 3ßcK„ø¿,é[ z•Ú€¾Ç§Tè¹nÅ7èÙVáiÆ’I—\‹ Û—DU† xbǛۖˆ/ÝL¼KrHwwìˆÈÖ^—[2%©…2Jú¼]®p%üÑ•>íÅX‘CB_µ CœÇ“ôµ}¯‰“üÚq` ¡n£Qé‡ rU_�{O¯÷ι_ŒÊ®gÏõs¨û›æñÛ3:v²W‹^5bК ~ìHºP)”ô…&ݹdjG/ÙnÕ4 9þ Í¬Úø¥äÙÓq bePÔ_èýêïKºm(ý†‚˜DT²÷Õ9wIDàï/tA’»À!iWCp÷€â÷u7•mBvÎýt@/Wô¹åœ{ó0ÇZJqךz2¨2䩦!˜D Hº‹í¾˜ª©©+t�½S ¡^íá·5h*WŒ½ƒ.�æ9?`ëèëÕ¦œ‰«£ª&I/ît%�®äLAˆïæÞ�È7>oªé¢±KM(åsø×Eäe™‘àwÀ×€§"2­fJD&E䈈41Ÿ)TztKDŽG4Þ`Ÿ0ÏO“ñ°t�ï—€Ÿ/€o¿~‚7Okö|Ô²§ö=àYÎóC}>sÎUzi=D&BDNhÖ䑈ø‘ñþGàUýî€?~ |OÈÏ€ï?nÒƒúð ØµvÙ5ßw�m}�†Rˆ‘I`˜Ž›Ÿ>¡ß²dXR,!a¦ôpø$ž„ B~ Ü~€¯AŸ~‰¯AkÀ#'!K@Vð»ø’µLˆˆ+³æ M„ˆLGñ‚ž"!â˜qvŠ„ˆ)ú“òàeõ÷ImµÅ™ç#àWÀ×ñ*êðmàÀ€Pœ€<áÛ§5^‘ñµeÇ9·7° "B½ üic,3ÆËÇ9HT/bv€'x¡žÞå`;bÉpÀmà÷xB^S¿?þü xHágní;¤IØ1ùšf�›Ù¶�s–°Â(L„ˆ%-ü^æ¨ñöi¢,ÖÌß�¯ª¹�/Éنݪ©€›À�/áô*¾v§¿à³‚îõ &`8a¾ïçA yꜨM™„}5cKjxN«NàKÛ1ÍÜ1|©8ŽüŒ1Ÿ7á—„œ,Ù8���xxCoUT?³§Ï7HÔ“�VQ»j¤„^SxÏ’°­&à+ø^Üà©>«›GÀcy¤ß³ámg¾m;¡F„bÞ÷)À®ñøH…:£¿[uu¯ðO#ü~�õ¤vWý¾”gëðž…˱g{P‡‘ÔX^C½œTÿ7�+ A&Ûêæ©ÚAY²mØ!n±‰/"rxÀ9÷×!üŸ>¥¯[ι÷KLÞH‘×Õú®sîN™a7qÄù>IWñ¥:R%G„6r¡œÔAáØ£qD(îûsQ+I„sn‡ä$Ð)™®3=U`Rô*µØÿG=î’ìO:ŒåÒç¾üú�Þ…WFÀ#õš2a}‘dîê|o壥p¤ô”Þk òo¤jPud'O¯‰ÈƱo,ôn¤Ç’�¶ñÉc¬i$ºöæ�¶HÏ󼃟™ÍòÙ6÷®šzËeè-íâ»±GðÓ'�içܹœV3©~^‘÷€;Ún W#t]û”¾>0#íPNƒ�kÏ%[CN_ÖMg­©!�#‚tÛpL{¤xBÞ3~[EH‰8­ÏÇι'æ{ßi%ä~q©u„4Šíý„FÚ >;íqšpÎíô!¤ùDÄÞ%W;ø©�mòÿâ®>'E¤ïd`!Ô9*σ•ùÉÝG�:c¡Â»íœ{'oÍWº²gó–sî_e¦µ$tô¹1Ar5Û•|·�C˜ã9:¹ óÍ ’Ó”©ðÆ®a¡K§¡«úJ�i*뎾^›P=zU?¬J�[Z€{ø]�YÏ. InH[ÕOWS§›äà)üA°bÂ9#"¯›)ã±AÈ—Nõ‡o+#Èmÿ®�ý^“žqëàÿ.fPDù#Õ– 3„ŸëøCõûç ÿ/ÓQ$_ÿÏ¡IEND®B`‚ukui-biometric-auth/man/0000775000175000017500000000000015167732644014161 5ustar fengfengukui-biometric-auth/man/uniauth-backend.10000664000175000017500000000133215167732644017304 0ustar fengfeng.\" Man Page for bioctl .TH BIOCTL 1 "August 05, 2018" .SH "NAME" bioctl \- control tool for biometric authentication .SH "SYNOPSIS" .B bioctl .SH "DESCRIPTION" .B bioctl is a control tool for biometric authentication in the UKUI desktop. It show or change the status that biometric authentication is enabled or not. .TP \fB status\fR Show the status of biometric authentication. .TP \fB enable\fR Enable biometric authentication. .TP \fB disable\fR Disable biometric authenticaion. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui/ukui-biometric-auth/issues .SH "AUTHORS" .SS This Manual Page has been written for the UKUI Desktop Environment by: yanghao (2018) ukui-biometric-auth/man/bioauth.10000664000175000017500000000121415167732630015667 0ustar fengfeng.\" Man Page for bioauth .TH BIOCTL 1 "August 05, 2018" .SH "NAME" bioauth \- command line binary for biometric authentication .SH "SYNOPSIS" .B bioauth .SH "DESCRIPTION" .B bioauth is a command line tool for biometric authentication in the UKUI desktop. It authenticate user by verify biometric features. .TP \fB --user\fR The user to be anthenticated. .TP \fB --device\fR The device for authentication. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui/ukui-biometric-auth/issues .SH "AUTHORS" .SS This Manual Page has been written for the UKUI Desktop Environment by: yanghao (2018) ukui-biometric-auth/man/biorestart.10000664000175000017500000000133215167732644016420 0ustar fengfeng.\" Man Page for bioctl .TH BIOCTL 1 "August 05, 2018" .SH "NAME" bioctl \- control tool for biometric authentication .SH "SYNOPSIS" .B bioctl .SH "DESCRIPTION" .B bioctl is a control tool for biometric authentication in the UKUI desktop. It show or change the status that biometric authentication is enabled or not. .TP \fB status\fR Show the status of biometric authentication. .TP \fB enable\fR Enable biometric authentication. .TP \fB disable\fR Disable biometric authenticaion. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui/ukui-biometric-auth/issues .SH "AUTHORS" .SS This Manual Page has been written for the UKUI Desktop Environment by: yanghao (2018) ukui-biometric-auth/man/biodrvctl.10000664000175000017500000000120215167732630016221 0ustar fengfeng.\" Man Page for bioctl .TH BIOCTL 1 "August 05, 2018" .SH "NAME" bioctl \- control tool for biometric device driver .SH "SYNOPSIS" .B biodrvctl .SH "DESCRIPTION" .B biodrvctl is a control tool for biometric device driver in the UKUI desktop. It changes the status of biometric device driver. .TP \fB enable\fR Enable biometric device driver. .TP \fB disable\fR Disable biometric device driver. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui/ukui-biometric-auth/issues .SH "AUTHORS" .SS This Manual Page has been written for the UKUI Desktop Environment by: yanghao (2018) ukui-biometric-auth/man/bioctl.10000664000175000017500000000133215167732630015511 0ustar fengfeng.\" Man Page for bioctl .TH BIOCTL 1 "August 05, 2018" .SH "NAME" bioctl \- control tool for biometric authentication .SH "SYNOPSIS" .B bioctl .SH "DESCRIPTION" .B bioctl is a control tool for biometric authentication in the UKUI desktop. It show or change the status that biometric authentication is enabled or not. .TP \fB status\fR Show the status of biometric authentication. .TP \fB enable\fR Enable biometric authentication. .TP \fB disable\fR Disable biometric authenticaion. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui/ukui-biometric-auth/issues .SH "AUTHORS" .SS This Manual Page has been written for the UKUI Desktop Environment by: yanghao (2018) ukui-biometric-auth/man/bioctl-helper.10000664000175000017500000000133215167732644016773 0ustar fengfeng.\" Man Page for bioctl .TH BIOCTL 1 "August 05, 2018" .SH "NAME" bioctl \- control tool for biometric authentication .SH "SYNOPSIS" .B bioctl .SH "DESCRIPTION" .B bioctl is a control tool for biometric authentication in the UKUI desktop. It show or change the status that biometric authentication is enabled or not. .TP \fB status\fR Show the status of biometric authentication. .TP \fB enable\fR Enable biometric authentication. .TP \fB disable\fR Disable biometric authenticaion. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui/ukui-biometric-auth/issues .SH "AUTHORS" .SS This Manual Page has been written for the UKUI Desktop Environment by: yanghao (2018) ukui-biometric-auth/CMakeLists.txt0000664000175000017500000000361615167732644016154 0ustar fengfengcmake_minimum_required(VERSION 3.16) project(ukui-biometric-auth) # å°�试查找Qt6,如果失败则回退到Qt5 find_package(Qt6 COMPONENTS Core Widgets DBus Svg QUIET) if(Qt6_FOUND) message(STATUS "Using Qt6") set(QT_VERSION_MAJOR 6) find_package(Qt6LinguistTools REQUIRED) set(QT_PREFIX Qt6) set(QT_LINGUIST_TOOLS_CMAKE_PACKAGE_NAME Qt6LinguistTools) else() message(STATUS "Qt6 not found, trying Qt5") find_package(Qt5 COMPONENTS Core Widgets DBus Svg REQUIRED) find_package(Qt5LinguistTools REQUIRED) set(QT_VERSION_MAJOR 5) set(QT_PREFIX Qt5) set(QT_LINGUIST_TOOLS_CMAKE_PACKAGE_NAME Qt5LinguistTools) endif() # 设置Qt版本相关的定义 add_definitions(-DQT_VERSION_MAJOR=${QT_VERSION_MAJOR}) # 输出版本信æ�¯ message(STATUS "Qt版本: ${QT_VERSION_MAJOR}") message(STATUS "Qtå‰�ç¼€: ${QT_PREFIX}") message(STATUS "C++标准: ${CMAKE_CXX_STANDARD}") find_package(OpenCV REQUIRED) find_package(PkgConfig) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) set(UKUI_BIOMETRIC_DIR /usr/share/ukui-biometric) set(CMAKE_INSTALL_PREFIX /usr) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") set(CMAKE_INCLUDE_CURRENT_DIR ON) # æ ¹æ�®Qt版本设置C++标准 if(QT_VERSION_MAJOR EQUAL 6) set(CMAKE_CXX_STANDARD 17) else() set(CMAKE_CXX_STANDARD 11) endif() set (CONDOR_SCRIPT_PERMS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) add_compile_options(-fPIC) add_definitions(-DUKUI_BIOMETRIC=${UKUI_BIOMETRIC_DIR}) add_definitions(-DCONFIG_FILE=/etc/biometric-auth/ukui-biometric.conf) add_subdirectory(bioauth) add_subdirectory(bioauth-bin) add_subdirectory(pam-biometric) add_subdirectory(polkit-agent) add_subdirectory(uniauth-backend) add_subdirectory(images) add_dependencies(bioauth BioAuth) add_dependencies(polkit-ukui-authentication-agent-1 BioAuthWidgets) ukui-biometric-auth/COPYING0000664000175000017500000010451315167732644014445 0ustar fengfeng GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ukui-biometric-auth/uniauth-backend/0000775000175000017500000000000015167732644016450 5ustar fengfengukui-biometric-auth/uniauth-backend/src/0000775000175000017500000000000015167732644017237 5ustar fengfengukui-biometric-auth/uniauth-backend/src/servicemanager.cpp0000664000175000017500000000600515167732631022733 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "servicemanager.h" #include #include #define SERVICE "biometric-authentication.service" #define DBUS_SERVICE "org.ukui.Biometric" #define DBUS_PATH "/org/ukui/Biometric" #define DBUS_INTERFACE "org.ukui.Biometric" #define FD_DBUS_SERVICE "org.freedesktop.DBus" #define FD_DBUS_PATH "/org/freedesktop/DBus" #define FD_DBUS_INTERFACE "org.freedesktop.DBus" ServiceManager *ServiceManager::instance_ = nullptr; ServiceManager::ServiceManager(QObject *parent) : QObject(parent), dbusService(nullptr), bioService(nullptr) { init(); } void ServiceManager::init() { if(!dbusService) { dbusService = new QDBusInterface(FD_DBUS_SERVICE, FD_DBUS_PATH, FD_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(dbusService, SIGNAL(NameOwnerChanged(QString, QString, QString)), this, SLOT(onDBusNameOwnerChanged(QString,QString,QString))); } } ServiceManager *ServiceManager::instance() { if(!instance_) { instance_ = new ServiceManager; } return instance_; } bool ServiceManager::connectToService() { if(!bioService) { bioService = new QDBusInterface(DBUS_SERVICE, DBUS_PATH, DBUS_INTERFACE, QDBusConnection::systemBus()); } return bioService->isValid(); } void ServiceManager::onDBusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) { if(name == DBUS_SERVICE) { qDebug() << "service status changed:" << (newOwner.isEmpty() ? "inactivate" : "activate"); Q_EMIT serviceStatusChanged(!newOwner.isEmpty()); } Q_EMIT dbusNameOwnerChanged(name,oldOwner,newOwner); } /*! * \brief checkServiceExist * 检查生物识别å�Žå�°æœ�务是å�¦å·²å�¯åЍ */ bool ServiceManager::serviceExists() { QDBusReply reply = dbusService->call("NameHasOwner", DBUS_SERVICE); if(!reply.isValid()) { qDebug() << "check service exists error:" << reply.error(); return false; } return reply.value(); } ukui-biometric-auth/uniauth-backend/src/main.cpp0000664000175000017500000000246615167732631020673 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "serviceinterface.h" #include "personalizeddata.h" #include #include int main(int argc, char *argv[]) { syslog(LOG_INFO, "[uniauth-backend] start begin!"); initUkuiLog4qt("ukui-biometric-uniauth"); QCoreApplication a(argc, argv); syslog(LOG_INFO, "[uniauth-backend] KYLINUSERDATAMNG initing!"); KYLINUSERDATAMNG::instance(); syslog(LOG_INFO, "[uniauth-backend] KYLINUSERDATAMNG inited!"); ServiceInterface serviveInterface; Q_UNUSED(serviveInterface); syslog(LOG_INFO, "[uniauth-backend] qcoreapplication eventloop begin!"); return a.exec(); } ukui-biometric-auth/uniauth-backend/src/CSingleton.h0000664000175000017500000000266415167732644021465 0ustar fengfeng/* * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef KYSINGLETON_H #define KYSINGLETON_H template class KySingleTon { public: // 创建å�•例实例 template static T *instance(Args &&... args) { if (m_pSingleInstance == nullptr) { m_pSingleInstance = new T(std::forward(args)...); } return m_pSingleInstance; } // 获å�–å�•例 static T *getInstance() { return m_pSingleInstance; } // 删除å�•例 static void destroyInstance() { delete m_pSingleInstance; m_pSingleInstance = nullptr; } private: KySingleTon(); virtual ~KySingleTon(); private: static T *m_pSingleInstance; }; template T *KySingleTon::m_pSingleInstance = nullptr; #endif ukui-biometric-auth/uniauth-backend/src/personalizeddata.h0000664000175000017500000001074015167732644022743 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef PERSONALIZEDDATA_H #define PERSONALIZEDDATA_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukui-log4qt.h" #include "CSingleton.h" class PersonalizedData : public QObject { Q_OBJECT public: explicit PersonalizedData(QString user); virtual ~PersonalizedData(); ////////////////////ukui-greeter-conf////////////////////////////// QString dateType(void) { return m_dateType; } void dateType(QString val) { m_dateType = val; } int fontSize(void) { return m_fontSize; } void fontSize(int val) { m_fontSize = val; } int timeType(void) { return m_timeType; } void timeType(int val) { m_timeType = val; } QString backgroundPath(void) { return m_backgroundPath; } void backgroundPath(QString val) { m_backgroundPath = val; } QString color(void) { return m_color; } void color(QString val) { m_color = val; } /////////////////////usd-ukui-settings-daemon//////////////////////////////// int cursor_size(void) { return m_cursor_size; } void cursor_size(int val) { m_cursor_size = val; } QString cursor_theme(void) { return m_cursor_theme; } void cursor_theme(QString val) { m_cursor_theme = val; } int scaling_factor(void) { return m_scaling_factor; } void scaling_factor(int val) { m_scaling_factor = val; } void getJsonData(QJsonObject &json); QString getJsonData(void); protected slots: void fileChanged(const QString &path); void directoryChanged(const QString &path); virtual void timerEvent(QTimerEvent *event); private: int __load_conf_ukuigreeterconf(void); int __load_conf_usd_conf(void); QString __copy_file(QString); protected: // ukui-greeter-conf QString m_dateType = "cn"; int m_fontSize = 5; int m_timeType = 24; QString m_backgroundPath; QString m_color; // usd-ukui-settings-daemon int m_cursor_size = 48; QString m_cursor_theme; int m_scaling_factor = 1; // 用户å�� QString m_user; QFileSystemWatcher *m_file_watch = nullptr; QString m_greeter_conf_path; bool m_greeter_conf_path_changed = false; QString m_usd_conf_path; QString m_user_path; bool m_usd_conf_path_changed = false; int m_conf_TimerID = 0; }; typedef QSharedPointer KylinUserDatePtr; ///////////////////////////////////////////////// /// \brief The PersonalizedDataMng class /// class PersonalizedDataMng : public QObject { Q_OBJECT protected: explicit PersonalizedDataMng(void); virtual ~PersonalizedDataMng(); public: QString GetConfInformation(QString); void SetLoginSynInformation(QString val); signals: void conf_changed(QString jsonstr); protected Q_SLOTS: void onUserAdded(const QDBusObjectPath &path); void onUserDeleted(const QDBusObjectPath &path); protected: void __updateUsersInfo(); private: void initData(); QString getUserName(const QString &userPath); protected: QMap m_userPersonalizedData; QString m_lightdm_str; friend class KySingleTon; private: bool m_isDataInited = false; QDBusInterface *m_actService = nullptr; QMap m_mapUserPaths; }; typedef KySingleTon KYLINUSERDATAMNG; #endif // PERSONALIZEDDATA_H ukui-biometric-auth/uniauth-backend/src/servicemanager.h0000664000175000017500000000301615167732631022377 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SERVICEMANAGER_H #define SERVICEMANAGER_H #include #include class ServiceManager : public QObject { Q_OBJECT public: static ServiceManager *instance(); bool serviceExists(); private: explicit ServiceManager(QObject *parent = nullptr); void init(); bool connectToService(); Q_SIGNALS: void serviceStatusChanged(bool activate); void dbusNameOwnerChanged(QString name,QString oldOwner,QString newOwner); public Q_SLOTS: void onDBusNameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); private: static ServiceManager *instance_; QDBusInterface *dbusService; QDBusInterface *bioService; bool serviceStatus; }; #endif // SERVICEMANAGER_H ukui-biometric-auth/uniauth-backend/src/rsac.h0000664000175000017500000000275515167732631020345 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef RSAC_H #define RSAC_H #include /** * @brief The RSAC class * RSA算法相关实现,包括密钥对生æˆ�,加密与解密,签å��与验签。 */ class RSAC { public: // 生æˆ�秘钥对 void generateKeyPair(const QString& priKeyFile, const QString &pubKeyFile, int bits = 1024); void generateKeyPair(QByteArray& priKey, QByteArray& pubKey, int bits = 1024); // 对数æ�®è¿›è¡ŒåŠ è§£å¯† bool encrypt(const QByteArray& in, QByteArray& out, const QByteArray& pubKey); bool decrypt(const QByteArray& in, QByteArray& out, const QByteArray& priKey); // 对摘è¦�进行签å��和验签 bool sign(const QByteArray& digest, QByteArray& sign, const QByteArray &priKey); bool verify(const QByteArray& digest, const QByteArray &sign, const QByteArray &pubKey); }; #endif // RSAC_H ukui-biometric-auth/uniauth-backend/src/rsac.cpp0000664000175000017500000001442115167732644020675 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "rsac.h" #include #include RSA* publicKeyToRSA(const QByteArray &pubKey) { BIO *pBio = BIO_new_mem_buf(pubKey.data(), pubKey.size()); // 创建内存 RSA* rsa = PEM_read_bio_RSA_PUBKEY(pBio, nullptr, nullptr, nullptr); BIO_free_all(pBio); // 释放内存 return rsa; } RSA* privateKeyToRSA(const QByteArray &priKey) { BIO *pBio = BIO_new_mem_buf(priKey.data(), priKey.size()); // 创建内存 RSA* rsa = PEM_read_bio_RSAPrivateKey(pBio, nullptr, nullptr, nullptr); BIO_free_all(pBio); // 释放内存 return rsa; } /** * @brief RSAC::generateKeyPair * 生æˆ�密钥对,并分别ä¿�存为文件 * @param priKeyFile ç§�钥文件å�� * @param pubKeyFile 公钥文件å�� * @param bits 秘钥长度,一般建议1024å�Šä»¥ä¸Š */ void RSAC::generateKeyPair(const QString &priKeyFile, const QString &pubKeyFile, int bits) { // 生æˆ�公钥 RSA* rsa = RSA_generate_key(bits, RSA_F4, nullptr, nullptr); BIO *bp = BIO_new(BIO_s_file()); BIO_write_filename(bp, (void*)pubKeyFile.toStdString().c_str()); PEM_write_bio_RSAPublicKey(bp, rsa); BIO_free_all(bp); // 生æˆ�ç§�é’¥ bp = BIO_new(BIO_s_file()); BIO_write_filename(bp, (void*)priKeyFile.toStdString().c_str()); PEM_write_bio_RSAPrivateKey(bp, rsa, nullptr, nullptr, 0, nullptr, nullptr); CRYPTO_cleanup_all_ex_data(); BIO_free_all(bp); RSA_free(rsa); } /** * @brief RSAC::generateKeyPair * 生æˆ�密钥对数æ�® * @param privateKey ç§�钥数æ�® * @param publicKey 公钥数æ�® * @param bits 秘钥长度,一般建议1024å�Šä»¥ä¸Š */ void RSAC::generateKeyPair(QByteArray &privateKey, QByteArray &pubKey, int bits) { // 生æˆ�密钥对 RSA *keyPair = RSA_generate_key(bits, RSA_F4, nullptr, nullptr); BIO *pri = BIO_new(BIO_s_mem()); BIO *pub = BIO_new(BIO_s_mem()); PEM_write_bio_RSAPrivateKey(pri, keyPair, nullptr, nullptr, 0, nullptr, nullptr); PEM_write_bio_RSA_PUBKEY(pub, keyPair); // 获å�–长度 int pri_len = BIO_pending(pri); int pub_len = BIO_pending(pub); privateKey.resize(pri_len); pubKey.resize(pub_len); BIO_read(pri, privateKey.data(), pri_len); BIO_read(pub, pubKey.data(), pub_len); // 内存释放 RSA_free(keyPair); BIO_free_all(pub); BIO_free_all(pri); } /** * @brief RSAC::encrypt * RSA加密函数,使用公钥对输入数æ�®ï¼Œè¿›è¡ŒåР坆 * @param in 输入数æ�®ï¼ˆæ˜Žæ–‡ï¼‰ * @param out 输出数æ�®ï¼ˆå¯†æ–‡ï¼‰ * @param pubKey 公钥 * @return 执行结果 */ bool RSAC::encrypt(const QByteArray &in, QByteArray &out, const QByteArray& pubKey) { // 公钥数æ�®è½¬RSA RSA* rsa = publicKeyToRSA(pubKey); if (rsa == nullptr) { return false; } // 对任æ„�长度数æ�®è¿›è¡ŒåŠ å¯†ï¼Œè¶…é•¿æ—¶ï¼Œè¿›è¡Œåˆ†æ®µåŠ å¯† int keySize = RSA_size(rsa); int dataLen = in.size(); const unsigned char *from = (const unsigned char *)in.data(); QByteArray to(keySize, 0); int readLen = 0; do { int select = (keySize - 11) > dataLen ? dataLen : (keySize - 11); RSA_public_encrypt(select, (from + readLen), (unsigned char *)to.data(), rsa, RSA_PKCS1_OAEP_PADDING); dataLen -= select; readLen += select; out.append(to); }while (dataLen > 0); RSA_free(rsa); return true; } /** * @brief RSAC::private_decrypt * RSA解密函数,使用ç§�钥对输入数æ�®ï¼Œè¿›è¡Œè§£å¯† * @param in 输入数æ�®ï¼ˆå¯†æ–‡ï¼‰ * @param out 输出数æ�®ï¼ˆè§£å¯†å�Žçš„内容) * @param priKey ç§�é’¥ * @return 执行结果 */ bool RSAC::decrypt(const QByteArray &in, QByteArray &out, const QByteArray& priKey) { // ç§�钥数æ�®è½¬RSA RSA* rsa = privateKeyToRSA(priKey); if (rsa == nullptr) { return false; } // 对任æ„�长度数æ�®è¿›è¡Œè§£å¯†ï¼Œè¶…长时,进行分段解密 int keySize = RSA_size(rsa); int dataLen = in.size(); const unsigned char *from = (const unsigned char *)in.data(); QByteArray to(keySize, 0); int readLen = 0; do { int size = RSA_private_decrypt(keySize, (from + readLen), (unsigned char *)to.data(), rsa, RSA_PKCS1_OAEP_PADDING); dataLen -= keySize; readLen += keySize; out.append(to.data(), size); }while (dataLen > 0); RSA_free(rsa); return true; } /** * @brief RSAC::sign * 使用ç§�钥对摘è¦�æ•°æ�®è¿›è¡Œç­¾å�� * @param digest 摘è¦�æ•°æ�® * @param sign ç­¾å��å�Žçš„æ•°æ�® * @param priKey ç§�é’¥ * @return 执行结果 */ bool RSAC::sign(const QByteArray &digest, QByteArray &sign, const QByteArray& priKey) { // ç§�钥数æ�®è½¬RSA RSA* rsa = privateKeyToRSA(priKey); if (rsa == nullptr) { return false; } // 对digest进行签å�� unsigned int siglen = 0; QByteArray temp(RSA_size(rsa), 0); RSA_sign(NID_sha1, (const unsigned char*)digest.data(), digest.size(), (unsigned char*)temp.data(), &siglen, rsa); sign.clear(); sign.append(temp.data(), siglen); RSA_free(rsa); return true; } /** * @brief RSAC::verify * 使用公钥对摘è¦�æ•°æ�®è¿›è¡ŒéªŒç­¾ * @param digest 摘è¦�æ•°æ�® * @param sign ç­¾å��å�Žçš„æ•°æ�® * @param pubKey 公钥 * @return 执行结果 */ bool RSAC::verify(const QByteArray &digest, const QByteArray &sign, const QByteArray& pubKey) { // 公钥数æ�®è½¬RSA RSA* rsa = publicKeyToRSA(pubKey); if (rsa == nullptr) { return false; } // 对digestã€�sign进行验签 int ret = RSA_verify(NID_sha1, (const unsigned char*)digest.data(), digest.size(), (const unsigned char *)sign.data(), sign.size(), rsa); RSA_free(rsa); return (ret == 1); } ukui-biometric-auth/uniauth-backend/src/biodeviceinfo.h0000664000175000017500000000347515167732631022222 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIODEVICEINFO_H #define BIODEVICEINFO_H #include #include #include #include struct DeviceInfo { int device_id; QString device_shortname; /* aka driverName */ QString device_fullname; int driver_enable; /* The corresponding driver is enabled/disabled */ int device_available; /* The driver is enabled and the device is connected */ int biotype; int stotype; int eigtype; int vertype; int idtype; int bustype; int dev_status; int ops_status; }; enum BioType { BIOTYPE_FINGERPRINT, BIOTYPE_FINGERVEIN, BIOTYPE_IRIS, BIOTYPE_FACE, BIOTYPE_VOICEPRINT, __MAX_NR_BIOTYPES }; #define UNIT_GENERAL_UKEY (6) #define REMOTE_QRCODE_TYPE (8) Q_DECLARE_METATYPE(DeviceInfo) Q_DECLARE_METATYPE(QList) typedef std::shared_ptr DeviceInfoPtr; typedef QList DeviceList; void registerCustomTypes(); QDBusArgument &operator<<(QDBusArgument &argument, const DeviceInfo &deviceInfo); const QDBusArgument &operator>>(const QDBusArgument &argument, DeviceInfo &deviceInfo); #endif // BIODEVICEINFO_H ukui-biometric-auth/uniauth-backend/src/greeterconfig.h0000664000175000017500000000333615167732644022240 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef GREETERCONFIG_H #define GREETERCONFIG_H #include class GreeterConfig : public QObject { Q_OBJECT public: explicit GreeterConfig(QObject *parent = nullptr); void setValue(const QString &group, const QString &key, const QVariant &value, QString strUserName = ""); QVariant getValue(const QString &group, const QString &key, QVariant varDefault, QString strUserName = ""); bool resetValue(const QString &group, const QString &key, QString strUserName = ""); QString printConfig(int nType, QString strUserName = ""); Q_SIGNALS: void changed(const QString &group, const QString &key); void changedForUser(const QString &group, const QString &key, const QString &userName); private: void initData(); void loadConfigDirectory(QString strPath); void loadConfigFromFile(QString strPath); QString getUserHomePath(const QString &strUserName); private: QSettings *m_setttingsDefault; QSettings *m_settingsCustom; QString m_strHomePath; }; #endif // LOGINCONFIG_H ukui-biometric-auth/uniauth-backend/src/biodeviceinfo.cpp0000664000175000017500000000363615167732631022554 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "biodeviceinfo.h" void registerCustomTypes() { qDBusRegisterMetaType(); qDBusRegisterMetaType >(); } QDBusArgument &operator<<(QDBusArgument &argument, const DeviceInfo &deviceInfo) { argument.beginStructure(); argument << deviceInfo.device_id << deviceInfo.device_shortname << deviceInfo.device_fullname << deviceInfo.driver_enable << deviceInfo.device_available << deviceInfo.biotype << deviceInfo.stotype << deviceInfo.eigtype << deviceInfo.vertype << deviceInfo.idtype << deviceInfo.bustype << deviceInfo.dev_status << deviceInfo.ops_status; argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, DeviceInfo &deviceInfo) { argument.beginStructure(); argument >> deviceInfo.device_id >> deviceInfo.device_shortname >> deviceInfo.device_fullname >> deviceInfo.driver_enable >> deviceInfo.device_available >> deviceInfo.biotype >> deviceInfo.stotype >> deviceInfo.eigtype >> deviceInfo.vertype >> deviceInfo.idtype >> deviceInfo.bustype >> deviceInfo.dev_status >> deviceInfo.ops_status; argument.endStructure(); return argument; } ukui-biometric-auth/uniauth-backend/src/greeterconfiginterface.h0000664000175000017500000000670015167732644024117 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef GREETERCONFIGINTERFACE_H #define GREETERCONFIGINTERFACE_H #include #include #include #include "greeterconfig.h" class GreeterConfigInterface : public QObject, QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.UniauthBackend") public: explicit GreeterConfigInterface(QObject *parent = nullptr); public Q_SLOTS: // virutal keyboard enable void setVirtualKeyboardEnable(bool isEnable); bool getVirtualKeyboardEnable(); bool resetVirtualKeyboardEnable(); // user switch enable void setUserSwitchEnable(bool isEnable); bool getUserSwitchEnable(); bool resetUserSwitchEnable(); // network enable void setNetworkEnable(bool isEnable); bool getNetworkEnable(); bool resetNetworkEnable(); // power manager enable void setPowerManagerEnable(bool isEnable); bool getPowerManagerEnable(); bool resetPowerManagerEnable(); // lock screen datetime enable void setLockScreenDatetimeEnable(bool isEnable); bool getLockScreenDatetimeEnable(QString strUserName); bool resetLockScreenDatetimeEnable(); // screensaver datetime enable void setScreensaverDatetimeEnable(bool isEnable); bool getScreensaverDatetimeEnable(QString strUserName); bool resetScreensaverDatetimeEnable(); // login displayed user count void setLoginDisplayedUserCount(int count); int getLoginDisplayedUserCount(); bool resetLoginDisplayedUserCount(); // default select manual login bool getSelectManualLoginDefault(); /** * @brief printConfig 以jsonæ ¼å¼�打å�°æ‰€æœ‰æœ‰æ•ˆçš„ã€�默认的ã€�修改的é…�置项 * @param nType 1 默认é…�置;2 修改的é…�置;其他 所有有效的é…�ç½® * @return json字符串 */ QString printConfig(int nType, QString strUserName); Q_SIGNALS: void changed(const QString &group, const QString &key); void userConfigChanged(const QString &group, const QString &key, const QString &strUserName); void virtualKeyboardEnableChanged(bool isEnable); void userSwitchEnableChanged(bool isEnable); void networkEnableChanged(bool isEnable); void powerManagerEnableChanged(bool isEnable); void lockScreenDatetimeEnableChanged(bool isEnable, QString strUserName); void screensaverDatetimeChanged(bool isEnable, QString strUserName); void loginDisplayedUserCountChanged(int count); private Q_SLOTS: void onChanged(const QString &group, const QString &key); void onChangedForUser(const QString &group, const QString &key, const QString &strUserName); private: bool checkEnviron(int pid); bool isAllowedCaller(); QString getUserNameFromCaller(); private: GreeterConfig *m_config = nullptr; }; #endif // GREETERCONFIGINTERFACE_H ukui-biometric-auth/uniauth-backend/src/personalizeddata.cpp0000664000175000017500000003040215167732644023273 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "personalizeddata.h" #include #include #include #include #include #include #include #include #include #include #include #include #define LIGHTDMDATA_ROOT_PATH "/var/lib/lightdm-data/" #define ACT_DBUS_SERVICE "org.freedesktop.Accounts" #define ACT_DBUS_PATH "/org/freedesktop/Accounts" #define ACT_DBUS_INTERFACE "org.freedesktop.Accounts" #define ACT_USER_INTERFACE "org.freedesktop.Accounts.User" #define DBUS_PROP_INTERFACE "org.freedesktop.DBus.Properties" enum enum_operation { enum_operation_update = 0, enum_operation_add, enum_operation_del, }; PersonalizedData::PersonalizedData(QString user) { KyInfo() << user; m_user = user; m_usd_conf_path = QString("/var/lib/lightdm-data/%1/usd/config/ukui-settings-daemon.settings").arg(m_user); m_greeter_conf_path = QString("/var/lib/lightdm-data/%1/ukui-greeter.conf").arg(m_user); m_user_path = QString("/var/lib/lightdm-data/%1/").arg(m_user); m_file_watch = new QFileSystemWatcher(); connect(m_file_watch, &QFileSystemWatcher::fileChanged, this, &PersonalizedData::fileChanged); connect(m_file_watch, &QFileSystemWatcher::directoryChanged, this, &PersonalizedData::directoryChanged); if (this->__load_conf_ukuigreeterconf() != 0) { if (QFileInfo(m_user_path).exists()) { if (!m_file_watch->directories().contains(m_user_path)) { m_file_watch->addPath(m_user_path); } } else if (QFileInfo(LIGHTDMDATA_ROOT_PATH).exists()) { if (!m_file_watch->directories().contains(LIGHTDMDATA_ROOT_PATH)) { m_file_watch->addPath(LIGHTDMDATA_ROOT_PATH); } } qDebug() << "init ukuigreeter conf failed:" << m_user << ",monitor:" << m_file_watch->directories(); } // 无需读å�–usdé…�ç½® // this->__load_conf_usd_conf(); } PersonalizedData::~PersonalizedData() { KyInfo() << m_user; if (0 != m_conf_TimerID) { this->killTimer(m_conf_TimerID); m_conf_TimerID = 0; } if (nullptr != m_file_watch) { delete m_file_watch; m_file_watch = nullptr; } } void PersonalizedData::getJsonData(QJsonObject &json) { json["user"] = m_user; { QJsonObject json_1; json_1["dateType"] = m_dateType; json_1["fontSize"] = m_fontSize; json_1["timeType"] = m_timeType; json_1["backgroundPath"] = m_backgroundPath; json_1["color"] = m_color; json["greeter"] = json_1; } } QString PersonalizedData::getJsonData() { QJsonObject json; this->getJsonData(json); json["operation"] = enum_operation_update; QJsonDocument document; document.setObject(json); return document.toJson(QJsonDocument::Compact); } void PersonalizedData::fileChanged(const QString &path) { KyInfo() << path; if (m_greeter_conf_path == path) { m_greeter_conf_path_changed = true; } if (m_usd_conf_path == path) { m_usd_conf_path_changed = true; } if (0 != m_conf_TimerID) { this->killTimer(m_conf_TimerID); m_conf_TimerID = 0; } m_conf_TimerID = this->startTimer(100); } void PersonalizedData::directoryChanged(const QString &path) { qDebug() << "Dirctory Changed:" << path; if (LIGHTDMDATA_ROOT_PATH == path) { if (QFileInfo(m_user_path).exists()) { if (!m_file_watch->directories().contains(m_user_path)) { m_file_watch->addPath(m_user_path); } } else { QTimer::singleShot(100, this, [=]() { if (QFileInfo(m_user_path).exists()) { if (!m_file_watch->directories().contains(m_user_path)) { m_file_watch->addPath(m_user_path); } } }); } } else if (m_user_path == path) { if (QFileInfo(m_greeter_conf_path).exists()) { fileChanged(m_greeter_conf_path); } else { QTimer::singleShot(100, this, [=]() { if (QFileInfo(m_greeter_conf_path).exists()) { fileChanged(m_greeter_conf_path); } }); } } } void PersonalizedData::timerEvent(QTimerEvent *event) { KyInfo() << m_file_watch->files(); if (event->timerId() == m_conf_TimerID) { this->killTimer(m_conf_TimerID); m_conf_TimerID = 0; if (m_greeter_conf_path_changed) { m_greeter_conf_path_changed = false; this->__load_conf_ukuigreeterconf(); } if (m_usd_conf_path_changed) { m_usd_conf_path_changed = false; this->__load_conf_usd_conf(); } emit KYLINUSERDATAMNG::getInstance()->conf_changed(this->getJsonData()); } } int PersonalizedData::__load_conf_ukuigreeterconf() { if (!QFileInfo(m_greeter_conf_path).exists()) { KyWarning() << "config file not exist:" << m_greeter_conf_path; return -1; } QSettings conf(m_greeter_conf_path, QSettings::IniFormat); if (QSettings::NoError != conf.status()) { KyWarning() << m_greeter_conf_path << conf.status(); return -1; } if (conf.childGroups().contains("Greeter")) { conf.beginGroup("Greeter"); if (conf.contains("dateType")) m_dateType = conf.value("dateType", m_dateType).toString(); if (conf.contains("fontSize")) m_fontSize = conf.value("fontSize", m_fontSize).toInt(); if (conf.contains("timeType")) m_timeType = conf.value("timeType", m_timeType).toInt(); conf.endGroup(); } if (conf.childGroups().contains("greeter")) { conf.beginGroup("greeter"); if (conf.contains("backgroundPath")) { m_backgroundPath = conf.value("backgroundPath", m_backgroundPath).toString(); if (!m_backgroundPath.isEmpty()) { m_backgroundPath = this->__copy_file(m_backgroundPath); } } if (conf.contains("color")) m_color = conf.value("color", m_color).toString(); conf.endGroup(); } if (nullptr != m_file_watch && !m_file_watch->files().contains(m_greeter_conf_path)) { m_file_watch->addPath(m_greeter_conf_path); } return 0; } int PersonalizedData::__load_conf_usd_conf() { KyInfo(); QSettings conf(m_usd_conf_path, QSettings::IniFormat); if (QSettings::NoError != conf.status()) { KyWarning() << m_usd_conf_path << conf.status(); return -1; } if (conf.childGroups().contains("xsettings")) { conf.beginGroup("xsettings"); if (conf.contains("cursor-size")) m_cursor_size = conf.value("cursor-size", m_cursor_size).toInt(); if (conf.contains("cursor-theme")) m_cursor_theme = conf.value("cursor-theme", m_cursor_theme).toString(); if (conf.contains("scaling-factor")) m_scaling_factor = conf.value("scaling-factor", m_scaling_factor).toInt(); conf.endGroup(); } if (nullptr != m_file_watch && !m_file_watch->files().contains(m_usd_conf_path)) { m_file_watch->addPath(m_usd_conf_path); } return 0; } QString PersonalizedData::__copy_file(QString oldfile) { if (QFile::exists(oldfile)) { QString tempPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation); QString newfile = QString("%1/loginBackground-%2-%3-XXXXXX") .arg(tempPath) .arg(m_user) .arg(QDate::currentDate().toString("yyyy-MM-dd")); if (QFile::exists(newfile)) { QFile::remove(newfile); } if (QFile::copy(oldfile, newfile)) { return newfile; } } return ""; } /////////////////////////PersonalizedDataMng////////////////////////////////////// PersonalizedDataMng::PersonalizedDataMng() { initData(); } void PersonalizedDataMng::initData() { if (m_isDataInited) { return; } if (!m_actService) { m_actService = new QDBusInterface(ACT_DBUS_SERVICE, ACT_DBUS_PATH, ACT_DBUS_INTERFACE, QDBusConnection::systemBus()); connect( m_actService, SIGNAL(UserAdded(const QDBusObjectPath &)), this, SLOT(onUserAdded(const QDBusObjectPath &))); connect( m_actService, SIGNAL(UserDeleted(const QDBusObjectPath &)), this, SLOT(onUserDeleted(const QDBusObjectPath &))); } this->__updateUsersInfo(); m_isDataInited = true; } QString PersonalizedDataMng::getUserName(const QString &userPath) { QDBusInterface iface(ACT_DBUS_SERVICE, userPath, DBUS_PROP_INTERFACE, QDBusConnection::systemBus()); QDBusReply reply = iface.call("Get", ACT_USER_INTERFACE, "UserName"); QString strUserName = ""; if (reply.isValid()) { strUserName = reply.value().variant().toString(); } return strUserName; } PersonalizedDataMng::~PersonalizedDataMng() {} QString PersonalizedDataMng::GetConfInformation(QString name) { QJsonObject json; if (m_userPersonalizedData.contains(name)) { QJsonObject json1; m_userPersonalizedData[name]->getJsonData(json1); json[name] = json1; } else if (name.isEmpty()) { for (auto &it : m_userPersonalizedData.toStdMap()) { QJsonObject json1; it.second->getJsonData(json1); json[it.first] = json1; } } else if ("lightdm" == name) { QString tmp(m_lightdm_str); m_lightdm_str = ""; return tmp; } QJsonDocument document; document.setObject(json); QString strJson(document.toJson(QJsonDocument::Compact)); KyDebug() << strJson; return strJson; } void PersonalizedDataMng::SetLoginSynInformation(QString val) { m_lightdm_str = val; } void PersonalizedDataMng::onUserAdded(const QDBusObjectPath &path) { QString strUserName = getUserName(path.path()); if (!strUserName.isEmpty()) { m_userPersonalizedData[strUserName] = KylinUserDatePtr(new PersonalizedData(strUserName)); m_mapUserPaths[path.path()] = strUserName; QJsonObject json; m_userPersonalizedData[strUserName]->getJsonData(json); json["operation"] = enum_operation_add; QJsonDocument document; document.setObject(json); emit conf_changed(document.toJson()); } } void PersonalizedDataMng::onUserDeleted(const QDBusObjectPath &path) { QString strUserName = m_mapUserPaths[path.path()]; if (!strUserName.isEmpty()) { m_userPersonalizedData.remove(strUserName); m_mapUserPaths.remove(path.path()); QJsonObject json; json["operation"] = enum_operation_del; json["user"] = strUserName; QJsonDocument document; document.setObject(json); emit conf_changed(document.toJson()); } } void PersonalizedDataMng::__updateUsersInfo() { if (m_actService) { QDBusMessage ret = m_actService->call("ListCachedUsers"); QList outArgs = ret.arguments(); QVariant first = outArgs.at(0); const QDBusArgument &dbusArgs = first.value(); QDBusObjectPath path; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> path; QString strUserName = getUserName(path.path()); if (!strUserName.isEmpty()) { m_userPersonalizedData[strUserName] = KylinUserDatePtr(new PersonalizedData(strUserName)); m_mapUserPaths[path.path()] = strUserName; } } dbusArgs.endArray(); } } ukui-biometric-auth/uniauth-backend/src/greeterconfiginterface.cpp0000664000175000017500000002447615167732644024464 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "greeterconfiginterface.h" #include #include #include #include #include #define GROUP_FUNCTIONS "Functions" #define KEY_USER_SWITCH_ENABLE "UserSwitchEnable" #define KEY_VIRTUAL_KEYBOARD_ENABLE "VirtualKeyBoardEnable" #define KEY_NETWORK_ENABLE "NetworkEnable" #define KEY_POWERMANAGER_ENABLE "PowerManagerEnable" #define KEY_LOCKSCREEN_SHOWDATETIME_ENABLE "LockScreenShowDatetimeEnable" #define KEY_SCREENSAVER_SHOWDATETIME_ENABLE "ScreensaverShowDatetimeEnable" #define KEY_LOGIN_DISPLAYED_USER_COUNT "LoginDisplayedUserCount" #define KEY_SELECT_MANUAL_LOGIN_DEFAULT "SelectManualLoginDefault" #define GROUP_GREETER "Greeter" GreeterConfigInterface::GreeterConfigInterface(QObject *parent) : QObject(parent) { m_config = new GreeterConfig(this); connect(m_config, &GreeterConfig::changed, this, &GreeterConfigInterface::changed); connect(m_config, &GreeterConfig::changedForUser, this, &GreeterConfigInterface::userConfigChanged); connect(m_config, &GreeterConfig::changed, this, &GreeterConfigInterface::onChanged); connect(m_config, &GreeterConfig::changedForUser, this, &GreeterConfigInterface::onChangedForUser); } void GreeterConfigInterface::onChanged(const QString &group, const QString &key) { if (group == GROUP_FUNCTIONS) { if (key == KEY_VIRTUAL_KEYBOARD_ENABLE) { Q_EMIT virtualKeyboardEnableChanged(getVirtualKeyboardEnable()); } else if (key == KEY_NETWORK_ENABLE) { Q_EMIT networkEnableChanged(getNetworkEnable()); } else if (key == KEY_USER_SWITCH_ENABLE) { Q_EMIT userSwitchEnableChanged(getUserSwitchEnable()); } else if (key == KEY_POWERMANAGER_ENABLE) { Q_EMIT powerManagerEnableChanged(getPowerManagerEnable()); } else if (key == KEY_LOGIN_DISPLAYED_USER_COUNT) { Q_EMIT loginDisplayedUserCountChanged(getLoginDisplayedUserCount()); } } } void GreeterConfigInterface::onChangedForUser(const QString &group, const QString &key, const QString &strUserName) { if (group == GROUP_FUNCTIONS) { if (key == KEY_LOCKSCREEN_SHOWDATETIME_ENABLE) { Q_EMIT lockScreenDatetimeEnableChanged(getLockScreenDatetimeEnable(strUserName), strUserName); } else if (key == KEY_SCREENSAVER_SHOWDATETIME_ENABLE) { Q_EMIT screensaverDatetimeChanged(getScreensaverDatetimeEnable(strUserName), strUserName); } } } void GreeterConfigInterface::setLoginDisplayedUserCount(int count) { if (!isAllowedCaller()) { return; } qDebug() << "setLoginDisplayedUserCount:" << count; m_config->setValue(GROUP_FUNCTIONS, KEY_LOGIN_DISPLAYED_USER_COUNT, count); } int GreeterConfigInterface::getLoginDisplayedUserCount() { return m_config->getValue(GROUP_FUNCTIONS, KEY_LOGIN_DISPLAYED_USER_COUNT, -1).toInt(); } bool GreeterConfigInterface::resetLoginDisplayedUserCount() { if (!isAllowedCaller()) { return false; } qDebug() << "resetLoginDisplayedUserCount!"; return m_config->resetValue(GROUP_FUNCTIONS, KEY_LOGIN_DISPLAYED_USER_COUNT); } void GreeterConfigInterface::setVirtualKeyboardEnable(bool isEnable) { if (!isAllowedCaller()) { return; } qDebug() << "setVirtualKeyboardEnable:" << isEnable; m_config->setValue(GROUP_FUNCTIONS, KEY_VIRTUAL_KEYBOARD_ENABLE, isEnable); } bool GreeterConfigInterface::getVirtualKeyboardEnable() { return m_config->getValue(GROUP_FUNCTIONS, KEY_VIRTUAL_KEYBOARD_ENABLE, true).toBool(); } bool GreeterConfigInterface::resetVirtualKeyboardEnable() { if (!isAllowedCaller()) { return false; } qDebug() << "resetVirtualKeyboardEnable!"; return m_config->resetValue(GROUP_FUNCTIONS, KEY_VIRTUAL_KEYBOARD_ENABLE); } void GreeterConfigInterface::setUserSwitchEnable(bool isEnable) { if (!isAllowedCaller()) { return; } qDebug() << "setUserSwitchEnable:" << isEnable; m_config->setValue(GROUP_FUNCTIONS, KEY_USER_SWITCH_ENABLE, isEnable); } bool GreeterConfigInterface::getUserSwitchEnable() { return m_config->getValue(GROUP_FUNCTIONS, KEY_USER_SWITCH_ENABLE, true).toBool(); } bool GreeterConfigInterface::resetUserSwitchEnable() { if (!isAllowedCaller()) { return false; } qDebug() << "resetUserSwitchEnable!"; return m_config->resetValue(GROUP_FUNCTIONS, KEY_USER_SWITCH_ENABLE); } void GreeterConfigInterface::setNetworkEnable(bool isEnable) { if (!isAllowedCaller()) { return; } qDebug() << "setNetworkEnable:" << isEnable; m_config->setValue(GROUP_FUNCTIONS, KEY_NETWORK_ENABLE, isEnable); } bool GreeterConfigInterface::getNetworkEnable() { return m_config->getValue(GROUP_FUNCTIONS, KEY_NETWORK_ENABLE, true).toBool(); } bool GreeterConfigInterface::resetNetworkEnable() { if (!isAllowedCaller()) { return false; } qDebug() << "resetNetworkEnable!"; return m_config->resetValue(GROUP_FUNCTIONS, KEY_NETWORK_ENABLE); } void GreeterConfigInterface::setPowerManagerEnable(bool isEnable) { if (!isAllowedCaller()) { return; } qDebug() << "setPowerManagerEnable:" << isEnable; m_config->setValue(GROUP_FUNCTIONS, KEY_POWERMANAGER_ENABLE, isEnable); } bool GreeterConfigInterface::getPowerManagerEnable() { return m_config->getValue(GROUP_FUNCTIONS, KEY_POWERMANAGER_ENABLE, true).toBool(); } bool GreeterConfigInterface::resetPowerManagerEnable() { if (!isAllowedCaller()) { return false; } qDebug() << "resetPowerManagerEnable!"; return m_config->resetValue(GROUP_FUNCTIONS, KEY_POWERMANAGER_ENABLE); } // lock screen datetime enable void GreeterConfigInterface::setLockScreenDatetimeEnable(bool isEnable) { if (!isAllowedCaller()) { return; } QString userName = getUserNameFromCaller(); qDebug() << "setLockScreenDatetimeEnable:" << isEnable << "," << userName; m_config->setValue(GROUP_FUNCTIONS, KEY_LOCKSCREEN_SHOWDATETIME_ENABLE, isEnable, userName); } bool GreeterConfigInterface::getLockScreenDatetimeEnable(QString strUserName) { return m_config->getValue(GROUP_FUNCTIONS, KEY_LOCKSCREEN_SHOWDATETIME_ENABLE, true, strUserName).toBool(); } bool GreeterConfigInterface::resetLockScreenDatetimeEnable() { if (!isAllowedCaller()) { return false; } QString userName = getUserNameFromCaller(); qDebug() << "resetLockScreenDatetimeEnable:" << userName; return m_config->resetValue(GROUP_FUNCTIONS, KEY_LOCKSCREEN_SHOWDATETIME_ENABLE, userName); } // screensaver datetime enable void GreeterConfigInterface::setScreensaverDatetimeEnable(bool isEnable) { if (!isAllowedCaller()) { return; } QString userName = getUserNameFromCaller(); qDebug() << "setScreensaverDatetimeEnable:" << isEnable << "," << userName; m_config->setValue(GROUP_FUNCTIONS, KEY_SCREENSAVER_SHOWDATETIME_ENABLE, isEnable, userName); } bool GreeterConfigInterface::getScreensaverDatetimeEnable(QString strUserName) { return m_config->getValue(GROUP_FUNCTIONS, KEY_SCREENSAVER_SHOWDATETIME_ENABLE, true, strUserName).toBool(); } bool GreeterConfigInterface::resetScreensaverDatetimeEnable() { if (!isAllowedCaller()) { return false; } QString userName = getUserNameFromCaller(); qDebug() << "resetScreensaverDatetimeEnable:" << userName; return m_config->resetValue(GROUP_FUNCTIONS, KEY_SCREENSAVER_SHOWDATETIME_ENABLE, userName); } bool GreeterConfigInterface::getSelectManualLoginDefault() { return m_config->getValue(GROUP_GREETER, KEY_SELECT_MANUAL_LOGIN_DEFAULT, false).toBool(); } QString GreeterConfigInterface::printConfig(int nType, QString strUserName) { return m_config->printConfig(nType, strUserName); } bool GreeterConfigInterface::checkEnviron(int pid) { QString filePath = QString("/proc/%1/environ").arg(pid); QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "file.open failed" << filePath; return false; } QTextStream in(&file); QString data = in.readAll(); file.close(); data.replace('\0', '\n'); QStringList environVars = data.split('\n'); for (const QString &var : environVars) { if (!var.isEmpty()) { int pos = var.indexOf('='); if (pos != -1) { QString key = var.left(pos); if (key == "LD_PRELOAD" || key == "LD_LIBRARY_PATH" || key == "LD_AUDIT") { return false; } } } } return true; } bool GreeterConfigInterface::isAllowedCaller() { // QString clientService = message().service(); // QDBusConnectionInterface *intf = connection().interface(); // unsigned int pid = intf->servicePid(clientService).value(); // /*check caller environ*/ // if (!checkEnviron(pid)) { // sendErrorReply(QDBusError::ErrorType::Failed, QString("[%2] dbus method control,env // forbidden").arg((pid))); return false; // } // /*check caller info*/ // QFileInfo file(QString("/proc/%1/exe").arg(pid)); // QString execPath = ""; // if (file.exists()) { // execPath = file.canonicalFilePath(); // } // qDebug() << "Caller info(uid,pid,ppath):" << intf->serviceUid(clientService).value() << pid << execPath; return true; } QString GreeterConfigInterface::getUserNameFromCaller() { QString clientService = message().service(); QDBusConnectionInterface *intf = connection().interface(); int uid = intf->serviceUid(clientService).value(); struct passwd *pwinfo = getpwuid(uid); if (pwinfo && pwinfo->pw_name) { return QString(pwinfo->pw_name); } else { return QString(""); } } ukui-biometric-auth/uniauth-backend/src/serviceinterface.h0000664000175000017500000001673515167732644022745 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SERVICEINTERFACE_H #define SERVICEINTERFACE_H #include "biodeviceinfo.h" #include #include #include #include #include #include #include "rsac.h" #include "greeterconfiginterface.h" #define DBUS_SERVICE "org.ukui.Biometric" #define DBUS_PATH "/org/ukui/Biometric" #define DBUS_INTERFACE "org.ukui.Biometric" enum authEnableType { ENABLETYPE_BIO, // 全局总使能 ENABLETYPE_SAVER, // é”�å±� ENABLETYPE_GREETER, // 登录 ENABLETYPE_POLKIT, // 授æ�ƒ ENABLETYPE_SU, // æš‚ä¿�ç•™ ENABLETYPE_SUDO, // æš‚ä¿�ç•™ ENABLETYPE_LOGIN, // æš‚ä¿�ç•™ }; /** * @brief 用户信æ�¯ */ struct WillLoginUserInfo { QString strUserName = ""; bool isOneKeyLogin = false; }; QDBusArgument &operator<<(QDBusArgument &arg, const WillLoginUserInfo &willLoginUserInfo); const QDBusArgument &operator>>(const QDBusArgument &arg, WillLoginUserInfo &willLoginUserInfo); QDebug operator<<(QDebug stream, const WillLoginUserInfo &willLoginUserInfo); Q_DECLARE_METATYPE(WillLoginUserInfo) class ServiceInterface : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.UniauthBackend") public: ServiceInterface(); public slots: // 设置默认设备 void setDefaultDevice(int bioDevType, QString deviceName); // 获å�–默认设备 QString getDefaultDevice(QString userName, int bioDevType); // 获å�–所有默认设备 QStringList getAllDefaultDevice(QString userName); // 生物特å¾�开关接å�£ bool getBioAuthStatus(QString userName, int bioAuthType); void setBioAuthStatus(int bioAuthType, bool status); // 获å�–最大失败次数 int getMaxFailedTimes(); // 获å�–人脸识别超时å�œç”¨æ¬¡æ•° int getFTimeoutTimes(); // 设置人脸识别超时å�œç”¨æ¬¡æ•° void setFTimeoutTimes(int times); // 获å�–是å�¦ä½¿èƒ½å¾®ä¿¡æ‰«ç �登录 bool getQRCodeEnable(); // 获å�–是å�¦å�Œè®¤è¯� bool getDoubleAuth(); // 获å�–用户绑定 bool getUserBind(); // 获å�–是å�¦åœ¨æŽ§åˆ¶é�¢æ�¿æ˜¾ç¤º bool getIsShownInControlCenter(); // 获å�–是å�¦ä½¿ç”¨ç¬¬ä¸€ä¸ªè®¾å¤‡ bool getUseFirstDevice(); // 获å�–是å�¦éš�è—�切æ�¢æŒ‰é’® bool getHiddenSwitchButton(); // 记录当å‰�正在进行生物认è¯�的设备 void recordAuthDrive(QString appName, int drvid, bool insert); // 获å�–当å‰�正在进行生物认è¯�的应用 QStringList getAllAuthApp(); // 获å�–当å‰�应用在认è¯�的驱动 int getAppAuthDrive(QString appName); // 获å�–用户é…�ç½® QString GetUserInformation(QString username); // å�Œæ­¥ç™»å½•界é�¢é…�ç½® void SetLoginSynInformation(QString val); // 获å�–公钥 QString getPublicEncrypt(); // å�‘é€�用户å��和密ç � bool sendPassword(QString username, QByteArray password); // å‰�端注册到å�Žç«¯æŽ¥å�£ bool registerLoginApp(); // å�‘é€�认è¯�结果 bool sendSignalLoginFinished(QString username, bool res); /** * @brief 一键切æ�¢å¹¶ç™»å½•用户 * * @param strUserName 用户å�� * @return int 0 æˆ�功,å�¦åˆ™å¤±è´¥ */ int SwitchToUser(QString strUserName); /** * @brief 切æ�¢åˆ°ç™»å½•用户 * * @param strUserName 用户å�� * @return int 0 æˆ�功,å�¦åˆ™å¤±è´¥ */ int SwitchToGreeterUser(QString strUserName); /** * @brief 获å�–å°†è¦�登录的用户å�� * * @return WillLoginUserInfo 用户信æ�¯ */ WillLoginUserInfo getWillSwitchUser(); /** * @brief SaveLastLoginUser 记录上一次登录æˆ�功的用户 * @param strUserName 用户å�� * @return 0 æˆ�功,其他失败 */ int SaveLastLoginUser(QString strUserName); /** * @brief GetLastLoginUser 获å�–上一次登录的用户 * @return 用户å�� */ QString GetLastLoginUser(); /** * @brief SaveQuickLoginUser ä¿�存下次快速登录的用户 * @param strUserName 用户å�� * @return 0 æˆ�功,其他失败 */ int SaveQuickLoginUser(QString strUserName); /** * @brief GetQuickLoginUser 获å�–快速登录的用户å�� * @return 用户å�� */ QString GetQuickLoginUser(); private slots: void onUSBDeviceHotPlug(int drvid, int action, int deviceNum); void onBiometricDbusChanged(bool bActive); void onDbusNameOwnerChanged(QString name, QString oldOwner, QString newOwner); signals: // 默认设备改å�˜ void defaultDeviceChanged(QString userName, int bioDevType, QString deviceName); // 开关状æ€�改å�˜ void bioAuthStatusChanged(QString userName, int type, bool status); // 用户é…�置改å�˜ void updateUserInformation(QString jsonstring); // å�•点登录完æˆ�ä¿¡å�· void onSignalLoginFinished(QString username, bool res); // 登录æœ�务以å�¯åŠ¨ä¿¡å�· void onLoginServicdRegisted(); /** * @brief å°†è¦�登录的用户å��改å�˜ * * @param willLoginUser 新用户信æ�¯ï¼ˆéœ€å¯¹ç©ºç”¨æˆ·å��异常处ç�†ï¼‰ */ void userChanged(WillLoginUserInfo willLoginUser); private: // 设置默认设备 void setDefaultDevice(QString userName, int bioDevType, QString deviceName); // 设置通用默认设备 void setCommDefaultDevice(int bioDevType, QString deviceName); // 获å�–通用默认设备 QString getCommDefaultDevice(int bioDevType); // 获å�–旧版app使能值 int getOldAppStatus(); // åˆ�始化数æ�® void initData(); // 更新通用默认设备 void updateCommDefaultDevice(int nDriId); // 等待生物识别æœ�务 void waitBiometricServiceStatus(); // 判断系统是å�¦ä¸º990 void checkIs990(); // 获å�–系统是å�¦ä¸º990 bool getIs990(); // æ ¹æ�®pid获å�–进程å��ç§° QString getProcessNameFromPid(int pid); // æ ¹æ�®uid获å�–用户å�� QString getUserNameFromUid(int uid); // 获å�–登录é”�å±�界é�¢çš„公钥 QString getLoginPubKey(QString service, QString path, QString interface); // å�‘é€�密ç �到登录é”�å±�界é�¢ bool sendLoginPassword(QString service, QString path, QString interface, QString username, QByteArray array); // 处ç�†é¦–次登录逻辑 bool handleFirstSingleLogn(QString username, QByteArray decryptText); private: QDBusInterface *m_serviceInterface = nullptr; DeviceList m_listDeviceInfos; int deviceCount = 0; bool is990 = false; bool m_isDataInited = false; QMap m_AuthingDriveList; QMap loginAppList; RSAC rsac; QByteArray priKey, pubKey; bool isFirstLogin = true; bool hasSaveLogin = false; QString savedUsername; QByteArray savedPassword; GreeterConfigInterface *m_greeterConfigInterface = nullptr; WillLoginUserInfo m_willLoginUser; /** 将登录的用户信æ�¯ */ }; #endif // SERVICEINTERFACE_H ukui-biometric-auth/uniauth-backend/src/serviceinterface.cpp0000664000175000017500000012716515167732644023300 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "serviceinterface.h" #include #include #include #if QT_VERSION_MAJOR == 6 #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "servicemanager.h" #include "personalizeddata.h" #include #include #include #include #define UKUI_GREETER "/usr/sbin/ukui-greeter" #define UKUI_SCREENSAVER "/usr/bin/ukui-screensaver-backend" #define GREETER_DBUS_PATH "/" #define GREETER_DBUS_INTERFACE "org.ukui.greeter" #define SCREENSAVER_DBUS_PATH "/" #define SCREENSAVER_DBUS_INTERFACE "org.ukui.screensaver" #define COMM_CONFIG_PATH "/etc/biometric-auth/ukui-biometric.conf" #define USER_CONFIG_PATH "/home/%1/.biometric_auth/ukui_biometric.conf" #define OLD_990_USER_CONFIG_PATH "/home/%1/.biometric-auth/ukui-biometric.conf" #define PROC_CPUINFO "/proc/cpuinfo" #define LAST_LOGIN_INFO_PATH "/var/lib/lightdm/.cache/ukui-greeter.conf" /* For the type WillLoginUserInfo */ QDBusArgument &operator<<(QDBusArgument &argument, const WillLoginUserInfo &willLoginUserInfo) { argument.beginStructure(); argument << willLoginUserInfo.strUserName << willLoginUserInfo.isOneKeyLogin; argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, WillLoginUserInfo &willLoginUserInfo) { argument.beginStructure(); argument >> willLoginUserInfo.strUserName >> willLoginUserInfo.isOneKeyLogin; argument.endStructure(); return argument; } QDebug operator<<(QDebug stream, const WillLoginUserInfo &willLoginUserInfo) { stream << "WillLogUser [" << willLoginUserInfo.strUserName << willLoginUserInfo.isOneKeyLogin << "]"; return stream; } ServiceInterface::ServiceInterface() { syslog(LOG_INFO, "[uniauth-backend] ServiceInterface init begin"); bool res = QDBusConnection::systemBus().registerService("org.ukui.UniauthBackend"); if (!res) { qInfo() << "registerService org.ukui.UniauthBackend failed!!"; exit(0); } res = QDBusConnection::systemBus().registerObject( "/org/ukui/UniauthBackend", "org.ukui.UniauthBackend", this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals); if (!res) { qInfo() << "registerObject /org/ukui/UniauthBackend failed!!"; exit(0); } m_greeterConfigInterface = new GreeterConfigInterface(this); res = QDBusConnection::systemBus().registerObject( "/org/ukui/GreeterConfig", "org.ukui.UniauthBackend", m_greeterConfigInterface, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals); if (!res) { qInfo() << "registerObject /org/ukui/GreeterConfig failed!!"; } registerCustomTypes(); qRegisterMetaType("WillLoginUserInfo"); qDBusRegisterMetaType(); checkIs990(); m_serviceInterface = new QDBusInterface(DBUS_SERVICE, DBUS_PATH, DBUS_INTERFACE, QDBusConnection::systemBus(), this); m_serviceInterface->setTimeout(2147483647); connect(m_serviceInterface, SIGNAL(USBDeviceHotPlug(int, int, int)), this, SLOT(onUSBDeviceHotPlug(int, int, int))); ServiceManager *sm = ServiceManager::instance(); connect(sm, &ServiceManager::serviceStatusChanged, this, &ServiceInterface::onBiometricDbusChanged); connect( KYLINUSERDATAMNG::getInstance(), &PersonalizedDataMng::conf_changed, this, &ServiceInterface::updateUserInformation); syslog(LOG_INFO, "[uniauth-backend] ServiceInterface init end"); } void ServiceInterface::setDefaultDevice(QString userName, int bioDevType, QString deviceName) { QString configPath = QString(USER_CONFIG_PATH).arg(userName); qDebug() << configPath << bioDevType; QSettings settings(configPath, QSettings::IniFormat); switch (bioDevType) { case BIOTYPE_FACE: settings.setValue("FC_DefaultDevice", deviceName); break; case BIOTYPE_FINGERPRINT: settings.setValue("FP_DefaultDevice", deviceName); break; case BIOTYPE_FINGERVEIN: settings.setValue("FV_DefaultDevice", deviceName); break; case BIOTYPE_IRIS: settings.setValue("IR_DefaultDevice", deviceName); break; case BIOTYPE_VOICEPRINT: settings.setValue("VP_DefaultDevice", deviceName); break; case UNIT_GENERAL_UKEY: settings.setValue("GU_DefaultDevice", deviceName); break; case REMOTE_QRCODE_TYPE: settings.setValue("WC_DefaultDevice", deviceName); break; default: break; } settings.sync(); qDebug() << "setDefaultDevice:" << userName << "," << bioDevType << "," << deviceName; emit defaultDeviceChanged(userName, bioDevType, deviceName); } void ServiceInterface::setDefaultDevice(int bioDevType, QString deviceName) { QDBusConnection conn = connection(); QDBusMessage msg = message(); int uid = conn.interface()->serviceUid(msg.service()).value(); struct passwd *pwinfo = getpwuid(uid); if (pwinfo && pwinfo->pw_name) { setDefaultDevice(pwinfo->pw_name, bioDevType, deviceName); } else { qInfo() << "GetPWInfo failed!!"; } } QString ServiceInterface::getDefaultDevice(QString userName, int bioDevType) { initData(); QString defaultDevice = ""; QString configPath = QString(USER_CONFIG_PATH).arg(userName); QSettings settings(configPath, QSettings::IniFormat); // 获å�–用户旧的默认设备 if (settings.contains("DefaultDevice")) { QString strOldDefDev = settings.value("DefaultDevice").toString(); if (!strOldDefDev.isEmpty()) { for (auto devInfo : m_listDeviceInfos) { if (devInfo && devInfo->device_shortname == strOldDefDev) { QString strBioDefType = ""; switch (devInfo->biotype) { case BIOTYPE_FINGERPRINT: strBioDefType = "FP_DefaultDevice"; break; case BIOTYPE_FINGERVEIN: strBioDefType = "FV_DefaultDevice"; break; case BIOTYPE_IRIS: strBioDefType = "IR_DefaultDevice"; break; case BIOTYPE_FACE: strBioDefType = "FC_DefaultDevice"; break; case BIOTYPE_VOICEPRINT: strBioDefType = "VP_DefaultDevice"; break; case UNIT_GENERAL_UKEY: strBioDefType = "GU_DefaultDevice"; break; case REMOTE_QRCODE_TYPE: strBioDefType = "WC_DefaultDevice"; break; default: break; } if (!strBioDefType.isEmpty() && !settings.contains(strBioDefType)) { settings.setValue(strBioDefType, strOldDefDev); settings.setValue("DefaultDevice", ""); settings.sync(); } if (bioDevType == devInfo->biotype) { return strOldDefDev; } break; } } } } switch (bioDevType) { case BIOTYPE_FACE: defaultDevice = settings.value("FC_DefaultDevice").toString(); break; case BIOTYPE_FINGERPRINT: defaultDevice = settings.value("FP_DefaultDevice").toString(); break; case BIOTYPE_FINGERVEIN: defaultDevice = settings.value("FV_DefaultDevice").toString(); break; case BIOTYPE_IRIS: defaultDevice = settings.value("IR_DefaultDevice").toString(); break; case BIOTYPE_VOICEPRINT: defaultDevice = settings.value("VP_DefaultDevice").toString(); break; case UNIT_GENERAL_UKEY: defaultDevice = settings.value("GU_DefaultDevice").toString(); break; case REMOTE_QRCODE_TYPE: defaultDevice = settings.value("WC_DefaultDevice").toString(); break; default: defaultDevice = settings.value("DefaultDevice").toString(); break; } if (defaultDevice.isEmpty()) { QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat); switch (bioDevType) { case BIOTYPE_FACE: defaultDevice = settings2.value("FC_DefaultDevice").toString(); break; case BIOTYPE_FINGERPRINT: defaultDevice = settings2.value("FP_DefaultDevice").toString(); break; case BIOTYPE_FINGERVEIN: defaultDevice = settings2.value("FV_DefaultDevice").toString(); break; case BIOTYPE_IRIS: defaultDevice = settings2.value("IR_DefaultDevice").toString(); break; case BIOTYPE_VOICEPRINT: defaultDevice = settings2.value("VP_DefaultDevice").toString(); break; case UNIT_GENERAL_UKEY: defaultDevice = settings2.value("GU_DefaultDevice").toString(); break; case REMOTE_QRCODE_TYPE: defaultDevice = settings2.value("WC_DefaultDevice").toString(); break; default: defaultDevice = settings2.value("DefaultDevice").toString(); break; } } return defaultDevice; } QStringList ServiceInterface::getAllDefaultDevice(QString userName) { initData(); QStringList listDefDevice; QString configPath = QString(USER_CONFIG_PATH).arg(userName); QSettings settings(configPath, QSettings::IniFormat); int nOldDefType = -1; // 获å�–用户旧的默认设备 if (settings.contains("DefaultDevice")) { QString strOldDefDev = settings.value("DefaultDevice").toString(); if (!strOldDefDev.isEmpty()) { for (auto devInfo : m_listDeviceInfos) { if (devInfo && devInfo->device_shortname == strOldDefDev) { QString strBioDefType = ""; switch (devInfo->biotype) { case BIOTYPE_FINGERPRINT: strBioDefType = "FP_DefaultDevice"; break; case BIOTYPE_FINGERVEIN: strBioDefType = "FV_DefaultDevice"; break; case BIOTYPE_IRIS: strBioDefType = "IR_DefaultDevice"; break; case BIOTYPE_FACE: strBioDefType = "FC_DefaultDevice"; break; case BIOTYPE_VOICEPRINT: strBioDefType = "VP_DefaultDevice"; break; case UNIT_GENERAL_UKEY: strBioDefType = "GU_DefaultDevice"; break; case REMOTE_QRCODE_TYPE: strBioDefType = "WC_DefaultDevice"; break; default: break; } if (!strBioDefType.isEmpty() && !settings.contains(strBioDefType)) { nOldDefType = devInfo->biotype; listDefDevice.push_back(strOldDefDev); settings.setValue(strBioDefType, strOldDefDev); settings.setValue("DefaultDevice", ""); settings.sync(); } break; } } } } QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat); for (int nBioType = 0; nBioType <= REMOTE_QRCODE_TYPE; nBioType++) { QString defaultDevice = ""; if (nBioType == nOldDefType) continue; switch (nBioType) { case BIOTYPE_FACE: defaultDevice = settings.value("FC_DefaultDevice").toString(); break; case BIOTYPE_FINGERPRINT: defaultDevice = settings.value("FP_DefaultDevice").toString(); break; case BIOTYPE_FINGERVEIN: defaultDevice = settings.value("FV_DefaultDevice").toString(); break; case BIOTYPE_IRIS: defaultDevice = settings.value("IR_DefaultDevice").toString(); break; case BIOTYPE_VOICEPRINT: defaultDevice = settings.value("VP_DefaultDevice").toString(); break; case UNIT_GENERAL_UKEY: defaultDevice = settings.value("GU_DefaultDevice").toString(); break; case REMOTE_QRCODE_TYPE: defaultDevice = settings.value("WC_DefaultDevice").toString(); break; default: break; } if (defaultDevice.isEmpty()) { switch (nBioType) { case BIOTYPE_FACE: defaultDevice = settings2.value("FC_DefaultDevice").toString(); break; case BIOTYPE_FINGERPRINT: defaultDevice = settings2.value("FP_DefaultDevice").toString(); break; case BIOTYPE_FINGERVEIN: defaultDevice = settings2.value("FV_DefaultDevice").toString(); break; case BIOTYPE_IRIS: defaultDevice = settings2.value("IR_DefaultDevice").toString(); break; case BIOTYPE_VOICEPRINT: defaultDevice = settings2.value("VP_DefaultDevice").toString(); break; case UNIT_GENERAL_UKEY: defaultDevice = settings2.value("GU_DefaultDevice").toString(); break; case REMOTE_QRCODE_TYPE: defaultDevice = settings2.value("WC_DefaultDevice").toString(); break; default: break; } } if (!defaultDevice.isEmpty()) { listDefDevice.push_back(defaultDevice); } } return listDefDevice; } // 设置通用默认设备 void ServiceInterface::setCommDefaultDevice(int bioDevType, QString deviceName) { initData(); QSettings settings(COMM_CONFIG_PATH, QSettings::IniFormat); switch (bioDevType) { case BIOTYPE_FACE: settings.setValue("FC_DefaultDevice", deviceName); break; case BIOTYPE_FINGERPRINT: settings.setValue("FP_DefaultDevice", deviceName); break; case BIOTYPE_FINGERVEIN: settings.setValue("FV_DefaultDevice", deviceName); break; case BIOTYPE_IRIS: settings.setValue("IR_DefaultDevice", deviceName); break; case BIOTYPE_VOICEPRINT: settings.setValue("VP_DefaultDevice", deviceName); break; case UNIT_GENERAL_UKEY: settings.setValue("GU_DefaultDevice", deviceName); break; case REMOTE_QRCODE_TYPE: settings.setValue("WC_DefaultDevice", deviceName); break; default: break; } settings.sync(); qDebug() << "setCommDefaultDevice:" << bioDevType << "," << deviceName; emit defaultDeviceChanged("", bioDevType, deviceName); } // 获å�–通用默认设备 QString ServiceInterface::getCommDefaultDevice(int bioDevType) { initData(); QString defaultDevice = ""; QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat); switch (bioDevType) { case BIOTYPE_FACE: defaultDevice = settings2.value("FC_DefaultDevice").toString(); break; case BIOTYPE_FINGERPRINT: defaultDevice = settings2.value("FP_DefaultDevice").toString(); break; case BIOTYPE_FINGERVEIN: defaultDevice = settings2.value("FV_DefaultDevice").toString(); break; case BIOTYPE_IRIS: defaultDevice = settings2.value("IR_DefaultDevice").toString(); break; case BIOTYPE_VOICEPRINT: defaultDevice = settings2.value("VP_DefaultDevice").toString(); break; case UNIT_GENERAL_UKEY: defaultDevice = settings2.value("GU_DefaultDevice").toString(); break; case REMOTE_QRCODE_TYPE: defaultDevice = settings2.value("WC_DefaultDevice").toString(); break; default: defaultDevice = settings2.value("DefaultDevice").toString(); break; } return defaultDevice; } void ServiceInterface::setBioAuthStatus(int bioAuthType, bool status) { QDBusConnection conn = connection(); QDBusMessage msg = message(); int uid = conn.interface()->serviceUid(msg.service()).value(); struct passwd *pwinfo = getpwuid(uid); if (pwinfo && pwinfo->pw_name) { QString configPath = QString(USER_CONFIG_PATH).arg(pwinfo->pw_name); QSettings settings(configPath, QSettings::IniFormat); switch (bioAuthType) { case ENABLETYPE_BIO: settings.setValue("EnableAuth", status); break; case ENABLETYPE_SAVER: settings.setValue("SaverEnable", status); break; case ENABLETYPE_GREETER: settings.setValue("GreeterEnable", status); break; case ENABLETYPE_POLKIT: settings.setValue("PolkitEnable", status); break; case ENABLETYPE_SU: settings.setValue("SuEnable", status); break; case ENABLETYPE_SUDO: settings.setValue("SudoEnable", status); break; case ENABLETYPE_LOGIN: settings.setValue("LoginEnable", status); break; default: break; } settings.sync(); emit bioAuthStatusChanged(pwinfo->pw_name, bioAuthType, status); qDebug() << "setBioAuthStatus:" << pwinfo->pw_name << "," << bioAuthType << "," << status; } else { qInfo() << "GetPWInfo failed!!"; } } bool ServiceInterface::getBioAuthStatus(QString userName, int bioAuthType) { initData(); QString configPath = QString(USER_CONFIG_PATH).arg(userName); QSettings settings(configPath, QSettings::IniFormat); QString strBioAuthType = ""; switch (bioAuthType) { case ENABLETYPE_BIO: strBioAuthType = "EnableAuth"; break; case ENABLETYPE_SAVER: strBioAuthType = "SaverEnable"; break; case ENABLETYPE_GREETER: strBioAuthType = "GreeterEnable"; break; case ENABLETYPE_POLKIT: strBioAuthType = "PolkitEnable"; break; case ENABLETYPE_SU: strBioAuthType = "SuEnable"; break; case ENABLETYPE_SUDO: strBioAuthType = "SudoEnable"; break; case ENABLETYPE_LOGIN: strBioAuthType = "LoginEnable"; break; default: return false; } // å�Œæ­¥990æ—§çš„é…�置文件,然å�Žåˆ é™¤ if (getIs990() && (bioAuthType == ENABLETYPE_BIO)) { QString oldConfigPath = QString(OLD_990_USER_CONFIG_PATH).arg(userName); QSettings oldSettings(oldConfigPath, QSettings::IniFormat); if (oldSettings.contains(strBioAuthType)) { settings.setValue(strBioAuthType, oldSettings.value(strBioAuthType).toBool()); oldSettings.remove(strBioAuthType); oldSettings.sync(); } } if (settings.contains(strBioAuthType)) { return settings.value(strBioAuthType).toBool(); } else if (getIs990() && (bioAuthType == ENABLETYPE_BIO)) { // 990默认为打开 return true; } else { QSettings settings2(COMM_CONFIG_PATH, QSettings::IniFormat); if (settings2.contains(strBioAuthType)) { return settings2.value(strBioAuthType).toBool(); } else { return true; } } } int ServiceInterface::getMaxFailedTimes() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("MaxFailedTimes")) return sysSettings.value("MaxFailedTimes").toInt(); else return 3; } int ServiceInterface::getFTimeoutTimes() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("FaceTimeoutTimes")) return sysSettings.value("FaceTimeoutTimes").toInt(); else return 1; } void ServiceInterface::setFTimeoutTimes(int times) { if (times < 1) times = 1; QSettings settings(COMM_CONFIG_PATH, QSettings::IniFormat); settings.setValue("FaceTimeoutTimes", times); } bool ServiceInterface::getQRCodeEnable() { bool isEnable = false; QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); sysSettings.beginGroup("Functions"); if (sysSettings.allKeys().contains("EnableQRCode")) { isEnable = sysSettings.value("EnableQRCode").toBool(); } sysSettings.endGroup(); return isEnable; } // 获å�–是å�¦å�Œè®¤è¯� bool ServiceInterface::getDoubleAuth() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("DoubleAuth")) return sysSettings.value("DoubleAuth").toBool(); else return false; } // 获å�–用户绑定 bool ServiceInterface::getUserBind() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("UserBind")) return sysSettings.value("UserBind").toBool(); else return false; } // 获å�–是å�¦åœ¨æŽ§åˆ¶é�¢æ�¿æ˜¾ç¤º bool ServiceInterface::getIsShownInControlCenter() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("isShownInControlCenter")) return sysSettings.value("isShownInControlCenter").toBool(); else return false; } // 获å�–是å�¦ä½¿ç”¨ç¬¬ä¸€ä¸ªè®¾å¤‡ bool ServiceInterface::getUseFirstDevice() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("UseFirstDevice")) return sysSettings.value("UseFirstDevice").toBool(); else return false; } // 获å�–是å�¦éš�è—�切æ�¢æŒ‰é’® bool ServiceInterface::getHiddenSwitchButton() { QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("HiddenSwitchButton")) return sysSettings.value("HiddenSwitchButton").toBool(); else return false; } // 获å�–旧版app使能值 int ServiceInterface::getOldAppStatus() { initData(); QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("EnableAuthApp")) return sysSettings.value("EnableAuthApp").toInt(); else return 63; } void ServiceInterface::onUSBDeviceHotPlug(int drvid, int action, int deviceNum) { if (action > 0) { qDebug() << "onUSBDeviceHotPlug in:" << drvid; updateCommDefaultDevice(drvid); } } // 记录当å‰�生物认è¯�ä¿¡æ�¯ void ServiceInterface::recordAuthDrive(QString appName, int drvid, bool insert) { if (insert) { m_AuthingDriveList.insert(appName, drvid); } else { m_AuthingDriveList.remove(appName); } } // 获å�–当å‰�正在认è¯�的应用 QStringList ServiceInterface::getAllAuthApp() { return m_AuthingDriveList.keys(); } // æ ¹æ�®åº”用å��称获å�–认è¯�的驱动 int ServiceInterface::getAppAuthDrive(QString appName) { if (m_AuthingDriveList.contains(appName)) { return m_AuthingDriveList.value(appName); } return -1; } QString ServiceInterface::GetUserInformation(QString username) { KyInfo() << username; return KYLINUSERDATAMNG::getInstance()->GetConfInformation(username); } void ServiceInterface::SetLoginSynInformation(QString val) { KyInfo() << val; KYLINUSERDATAMNG::getInstance()->SetLoginSynInformation(val); } void ServiceInterface::waitBiometricServiceStatus() { qDebug() << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` get biometric status"; QDBusInterface iface( "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", QDBusConnection::systemBus()); QDBusReply bioPath = iface.call("GetUnit", "biometric-authentication.service"); if (!bioPath.isValid()) { return; } QDBusInterface bioface( "org.freedesktop.systemd1", bioPath.value().path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); QDBusReply sessionReply = bioface.call("Get", "org.freedesktop.systemd1.Unit", "UnitFileState"); if (!sessionReply.isValid()) qWarning() << sessionReply.error(); else { QString res = sessionReply.value().variant().toString(); if (res == "disable") return; } qDebug() << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ get activeState"; int times = 0; while (times < 20) { QDBusReply sessionReply = bioface.call("Get", "org.freedesktop.systemd1.Unit", "ActiveState"); if (!sessionReply.isValid()) { qWarning() << sessionReply.error(); return; } else { QString res = sessionReply.value().variant().toString(); if (res == "activating") { times++; usleep(100000); } else { break; } } } qDebug() << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ times = " << times; } void ServiceInterface::updateCommDefaultDevice(int nDriId) { if (!m_serviceInterface) { return; } QVariant variant; QDBusArgument argument; QList qlist; QDBusVariant item; DeviceInfoPtr deviceInfo = nullptr; /* 返回值为 i -- int å’Œ av -- array of variant */ QDBusPendingReply> reply = m_serviceInterface->call("GetDrvList"); reply.waitForFinished(); if (reply.isError()) { qDebug() << "GUI:" << reply.error(); deviceCount = 0; return; } /* è§£æž� DBus 返回值,reply 有两个返回值,都是 QVariant 类型 */ variant = reply.argumentAt(0); /* 得到第一个返回值 */ deviceCount = variant.value(); /* è§£å°�装得到设备个数 */ variant = reply.argumentAt(1); /* 得到第二个返回值 */ argument = variant.value(); /* è§£å°�装,获å�–QDBusArgument对象 */ argument >> qlist; /* 使用è¿�算符é‡�è½½æ��å�– argument 对象里é�¢å­˜å‚¨çš„列表对象 */ if (nDriId != -1) { // 指定设备接入 for (int i = 0; i < deviceCount; i++) { item = qlist[i]; /* å�–出一个元素 */ variant = item.variant(); /* 转为普通QVariant对象 */ /* è§£å°�装得到 QDBusArgument 对象 */ argument = variant.value(); deviceInfo = std::make_shared(); argument >> *deviceInfo; /* æ��å�–最终的 DeviceInfo 结构体 */ if (nDriId == deviceInfo->device_id) { if (getCommDefaultDevice(deviceInfo->biotype).isEmpty()) { setCommDefaultDevice(deviceInfo->biotype, deviceInfo->device_shortname); } break; } } } else { m_listDeviceInfos.clear(); for (int i = 0; i < deviceCount; i++) { item = qlist[i]; /* å�–出一个元素 */ variant = item.variant(); /* 转为普通QVariant对象 */ /* è§£å°�装得到 QDBusArgument 对象 */ argument = variant.value(); deviceInfo = std::make_shared(); argument >> *deviceInfo; /* æ��å�–最终的 DeviceInfo 结构体 */ m_listDeviceInfos.push_back(deviceInfo); } } } void ServiceInterface::initData() { if (m_isDataInited) { return; } updateCommDefaultDevice(-1); // 沿用旧app enable QSettings sysSettings(COMM_CONFIG_PATH, QSettings::IniFormat); if (sysSettings.contains("EnableAuthApp") || sysSettings.contains("Functions/EnableAuthApp")) { int nAppOldStatus = 0; if (sysSettings.contains("Functions/EnableAuthApp")) { nAppOldStatus = sysSettings.value("Functions/EnableAuthApp").toInt(); } else { nAppOldStatus = sysSettings.value("EnableAuthApp").toInt(); } if ((nAppOldStatus & 0x01) && !sysSettings.contains("GreeterEnable")) { // greeter sysSettings.setValue("GreeterEnable", true); } if ((nAppOldStatus & 0x02) && !sysSettings.contains("SaverEnable")) { // saver sysSettings.setValue("SaverEnable", true); } if ((nAppOldStatus & 0x04) && !sysSettings.contains("PolkitEnable")) { // polkit sysSettings.setValue("PolkitEnable", true); } if ((nAppOldStatus & 0x08) && !sysSettings.contains("SudoEnable")) { // sudo sysSettings.setValue("SudoEnable", true); } if ((nAppOldStatus & 0x10) && !sysSettings.contains("SuEnable")) { // su sysSettings.setValue("SuEnable", true); } if ((nAppOldStatus & 0x20) && !sysSettings.contains("LoginEnable")) { // login sysSettings.setValue("LoginEnable", true); } } // 沿用旧的默认设备 if (sysSettings.contains("DefaultDevice")) { QString strOldDefDev = sysSettings.value("DefaultDevice").toString(); if (!strOldDefDev.isEmpty()) { for (auto devInfo : m_listDeviceInfos) { if (devInfo && devInfo->device_shortname == strOldDefDev) { QString strBioDefType = ""; switch (devInfo->biotype) { case BIOTYPE_FINGERPRINT: strBioDefType = "FP_DefaultDevice"; break; case BIOTYPE_FINGERVEIN: strBioDefType = "FV_DefaultDevice"; break; case BIOTYPE_IRIS: strBioDefType = "IR_DefaultDevice"; break; case BIOTYPE_FACE: strBioDefType = "FC_DefaultDevice"; break; case BIOTYPE_VOICEPRINT: strBioDefType = "VP_DefaultDevice"; break; case UNIT_GENERAL_UKEY: strBioDefType = "GU_DefaultDevice"; break; case REMOTE_QRCODE_TYPE: strBioDefType = "WC_DefaultDevice"; break; default: break; } if (!strBioDefType.isEmpty() && !sysSettings.contains(strBioDefType)) { sysSettings.setValue(strBioDefType, strOldDefDev); sysSettings.setValue("DefaultDevice", ""); } break; } } } } // 设置未设置过默认设备的类型,如果驱动已打开且已连接 for (auto devInfo : m_listDeviceInfos) { if (devInfo && devInfo->device_available > 0 && devInfo->driver_enable > 0) { QString strBioDefType = ""; switch (devInfo->biotype) { case BIOTYPE_FINGERPRINT: strBioDefType = "FP_DefaultDevice"; break; case BIOTYPE_FINGERVEIN: strBioDefType = "FV_DefaultDevice"; break; case BIOTYPE_IRIS: strBioDefType = "IR_DefaultDevice"; break; case BIOTYPE_FACE: strBioDefType = "FC_DefaultDevice"; break; case BIOTYPE_VOICEPRINT: strBioDefType = "VP_DefaultDevice"; break; case UNIT_GENERAL_UKEY: strBioDefType = "GU_DefaultDevice"; break; case REMOTE_QRCODE_TYPE: strBioDefType = "WC_DefaultDevice"; break; default: break; } if (!strBioDefType.isEmpty() && !sysSettings.contains(strBioDefType)) { sysSettings.setValue(strBioDefType, devInfo->device_shortname); } } } sysSettings.sync(); m_isDataInited = true; } void ServiceInterface::onBiometricDbusChanged(bool bActive) { qDebug() << "BiometricDbus:" << bActive; if (bActive) { updateCommDefaultDevice(-1); initData(); } } void ServiceInterface::checkIs990() { #if QT_VERSION_MAJOR == 6 QRegularExpression r1("kirin.*9.0", QRegularExpression::CaseInsensitiveOption); QRegularExpression r2("pangu.*m900", QRegularExpression::CaseInsensitiveOption); #else QRegExp r1("kirin.*9.0"); r1.setCaseSensitivity(Qt::CaseInsensitive); QRegExp r2("pangu.*m900"); r2.setCaseSensitivity(Qt::CaseInsensitive); #endif QFile file(PROC_CPUINFO); if (!file.exists()) { is990 = false; } file.open(QFile::ReadOnly); QString str(file.readAll()); #if QT_VERSION_MAJOR == 6 is990 = (r1.match(str).hasMatch() || r2.match(str).hasMatch()); #else is990 = (str.contains(r1) || str.contains(r2)); #endif file.close(); } bool ServiceInterface::getIs990() { return is990; } QString ServiceInterface::getPublicEncrypt() { if (pubKey.isEmpty()) { rsac.generateKeyPair(priKey, pubKey, 1024); } return pubKey; } bool ServiceInterface::sendPassword(QString username, QByteArray password) { if (priKey.isEmpty()) { rsac.generateKeyPair(priKey, pubKey, 1024); } QByteArray decryptText; QByteArray encryptText; rsac.decrypt(password, decryptText, priKey); // 解密 // 如果处于登录状æ€� qDebug() << "sendPassword" << loginAppList.count() << loginAppList; if (loginAppList.contains("lightdm")) { qDebug() << "login:"; isFirstLogin = false; QString publicKey = getLoginPubKey(loginAppList.value("lightdm"), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE); rsac.encrypt(decryptText, encryptText, publicKey.toLatin1()); return sendLoginPassword( loginAppList.value("lightdm"), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE, username, encryptText); } // 处于é”�å±�状æ€� if (loginAppList.contains(username)) { qDebug() << "unlock:"; isFirstLogin = false; QString publicKey = getLoginPubKey(loginAppList.value(username), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE); rsac.encrypt(decryptText, encryptText, publicKey.toLatin1()); return sendLoginPassword( loginAppList.value(username), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE, username, encryptText); } if (loginAppList.count() > 0) { qDebug() << "login by screensaver:"; isFirstLogin = false; QString publicKey = getLoginPubKey( loginAppList.value(loginAppList.firstKey()), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE); rsac.encrypt(decryptText, encryptText, publicKey.toLatin1()); return sendLoginPassword( loginAppList.value(loginAppList.firstKey()), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE, username, encryptText); } // 如果是第一次调用,则é…�置自动登录 if (isFirstLogin) { qDebug() << "isFirstLogin:"; isFirstLogin = false; hasSaveLogin = true; return handleFirstSingleLogn(username, decryptText); } isFirstLogin = false; return false; } bool ServiceInterface::handleFirstSingleLogn(QString username, QByteArray decryptText) { QEventLoop loopTemp; bool ret = false; QByteArray encryptText; qDebug() << "handleFirstSingleLogn wait"; QMetaObject::Connection connection = QObject::connect(this, &ServiceInterface::onLoginServicdRegisted, [&loopTemp]() { if (loopTemp.isRunning()) { loopTemp.quit(); } }); QTimer::singleShot(10000, &loopTemp, SLOT(quit())); loopTemp.exec(); qDebug() << "handleFirstSingleLogn finished"; disconnect(connection); qDebug() << loginAppList.count(); if (loginAppList.contains("lightdm")) { isFirstLogin = false; QString publicKey = getLoginPubKey(loginAppList.value("lightdm"), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE); if (publicKey.isEmpty()) { qDebug() << "get Login PubKey failed!"; return false; } rsac.encrypt(decryptText, encryptText, publicKey.toLatin1()); return sendLoginPassword( loginAppList.value("lightdm"), SCREENSAVER_DBUS_PATH, SCREENSAVER_DBUS_INTERFACE, username, encryptText); } return ret; } QString ServiceInterface::getLoginPubKey(QString service, QString path, QString interface) { QDBusInterface iface(service, path, interface, QDBusConnection::systemBus()); QDBusReply stateReply = iface.call("getPublicEncrypt"); if (!stateReply.isValid()) { qWarning() << "Get state error:" << stateReply.error(); qDebug() << "getPublicEncrypt failed"; return ""; } return stateReply.value(); } bool ServiceInterface::sendSignalLoginFinished(QString username, bool res) { qDebug() << "sendSignalLoginFinished " << username << res; emit onSignalLoginFinished(username, res); return true; } bool ServiceInterface::sendLoginPassword( QString service, QString path, QString interface, QString username, QByteArray array) { QEventLoop loopTemp; bool ret = false; qDebug() << "sendLoginPassword"; QMetaObject::Connection connection = QObject::connect( this, &ServiceInterface::onSignalLoginFinished, [&loopTemp, &ret](QString username, bool res) { qDebug() << "onSignalLoginFinished:" << username << res; ret = res; if (loopTemp.isRunning()) { loopTemp.quit(); } }); QDBusInterface iface(service, path, interface, QDBusConnection::systemBus()); QDBusReply stateReply = iface.call("sendPassword", username, array); if (!stateReply.isValid()) { disconnect(connection); return false; } if (!stateReply.value()) { disconnect(connection); return stateReply.value(); } QTimer::singleShot(30000, &loopTemp, SLOT(quit())); loopTemp.exec(); disconnect(connection); return ret; } QString ServiceInterface::getProcessNameFromPid(int pid) { QString filename = "/proc/" + QString::number(pid) + "/cmdline"; qDebug() << "filename is " << filename; QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Can't open the file!"; return ""; } QByteArray text = file.readAll(); return QString(text); } QString ServiceInterface::getUserNameFromUid(int uid) { struct passwd *pw = NULL; pw = getpwuid(uid); if (pw) { return QString(pw->pw_name); } return ""; } void ServiceInterface::onDbusNameOwnerChanged(QString name, QString oldOwner, QString newOwner) { if (newOwner.isEmpty()) { for (QString str : loginAppList.keys()) { if (name == loginAppList.value(str)) { qDebug() << "remove name " << name; loginAppList.remove(str); } } } } bool ServiceInterface::registerLoginApp() { QDBusConnection conn = connection(); QDBusMessage msg = message(); qDebug() << "Sender Name" << conn.interface()->serviceOwner(msg.service()).value(); qDebug() << "Sender Pid " << conn.interface()->servicePid(msg.service()).value(); qDebug() << "Sender uid " << conn.interface()->serviceUid(msg.service()).value(); int pid = conn.interface()->servicePid(msg.service()).value(); QString serviceOwner = conn.interface()->serviceOwner(msg.service()).value(); int uid = conn.interface()->serviceUid(msg.service()).value(); QString appName = getProcessNameFromPid(pid); qDebug() << "appName = " << appName; if (appName != UKUI_GREETER && appName != UKUI_SCREENSAVER) { return false; } QString appUser = getUserNameFromUid(uid); if (appUser.isEmpty()) return false; qDebug() << "insert " << appUser << serviceOwner; loginAppList.insert(appUser, serviceOwner); if (appUser == "lightdm" && hasSaveLogin) { QTimer::singleShot(1000, this, [=]() { emit onLoginServicdRegisted(); }); } return true; } int ServiceInterface::SwitchToUser(QString strUserName) { m_willLoginUser.strUserName = strUserName; m_willLoginUser.isOneKeyLogin = true; Q_EMIT userChanged(m_willLoginUser); return 0; } int ServiceInterface::SwitchToGreeterUser(QString strUserName) { m_willLoginUser.strUserName = strUserName; m_willLoginUser.isOneKeyLogin = false; Q_EMIT userChanged(m_willLoginUser); return 0; } WillLoginUserInfo ServiceInterface::getWillSwitchUser() { return m_willLoginUser; } int ServiceInterface::SaveLastLoginUser(QString strUserName) { QSettings settings(LAST_LOGIN_INFO_PATH, QSettings::IniFormat); settings.beginGroup("Greeter"); settings.setValue("lastLoginUser", strUserName); settings.endGroup(); settings.sync(); return 0; } QString ServiceInterface::GetLastLoginUser() { QSettings settings(LAST_LOGIN_INFO_PATH, QSettings::IniFormat); settings.beginGroup("Greeter"); QString lastLoginUser = settings.value("lastLoginUser").toString(); settings.endGroup(); return lastLoginUser; } int ServiceInterface::SaveQuickLoginUser(QString strUserName) { QSettings settings(LAST_LOGIN_INFO_PATH, QSettings::IniFormat); settings.beginGroup("Greeter"); settings.setValue("lastLoginUser1", strUserName); settings.endGroup(); settings.sync(); return 0; } QString ServiceInterface::GetQuickLoginUser() { QSettings settings(LAST_LOGIN_INFO_PATH, QSettings::IniFormat); settings.beginGroup("Greeter"); QString lastLoginUser = settings.value("lastLoginUser1").toString(); settings.endGroup(); return lastLoginUser; } ukui-biometric-auth/uniauth-backend/src/greeterconfig.cpp0000664000175000017500000002200715167732644022567 0ustar fengfeng/* * Copyright (C) 2024 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "greeterconfig.h" #include #include #include #include #include #include #include #define GREETER_CONFIG_DEFAULT_FILE "/var/cache/ukui-greeter/default.conf" #define GREETER_CONFIG_CUSTOM_FILE "/var/cache/ukui-greeter/custom.conf" #define GREETER_CONFIG_ETC_DIR "/etc/ukui/ukui-greeter/ukui-greeter.conf.d/" #define GREETER_CONFIG_ETC_FILE "/etc/ukui/ukui-greeter/ukui-greeter.conf" #define GREETER_CONFIG_USER_FILE "%1/.config/ukui-greeter/ukui-greeter.conf" GreeterConfig::GreeterConfig(QObject *parent) : QObject(parent), m_setttingsDefault(nullptr), m_settingsCustom(nullptr) { initData(); } void GreeterConfig::initData() { m_strHomePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); if (!m_setttingsDefault) { m_setttingsDefault = new QSettings(GREETER_CONFIG_DEFAULT_FILE, QSettings::IniFormat, this); m_setttingsDefault->clear(); } // read config from conf.d directory loadConfigDirectory(GREETER_CONFIG_ETC_DIR); // read config from conf file loadConfigFromFile(GREETER_CONFIG_ETC_FILE); if (!m_settingsCustom) { m_settingsCustom = new QSettings(GREETER_CONFIG_CUSTOM_FILE, QSettings::IniFormat, this); } } void GreeterConfig::loadConfigDirectory(QString strPath) { QDir confDir(strPath); QStringList filePathList = confDir.entryList(QDir::Files, QDir::Name); for (const QString &filePath : filePathList) { if (filePath.endsWith(".conf")) { loadConfigFromFile(strPath + filePath); } } if (m_setttingsDefault) { m_setttingsDefault->sync(); } } void GreeterConfig::loadConfigFromFile(QString strPath) { if (!m_setttingsDefault) { return; } qDebug() << "conf file:" << strPath; QSettings *settingsConf = new QSettings(strPath, QSettings::IniFormat, this); QStringList groups = settingsConf->childGroups(); foreach (const QString &group, groups) { settingsConf->beginGroup(group); QStringList keys = settingsConf->childKeys(); foreach (const QString &key, keys) { m_setttingsDefault->beginGroup(group); m_setttingsDefault->setValue(key, settingsConf->value(key)); m_setttingsDefault->endGroup(); } settingsConf->endGroup(); } settingsConf->deleteLater(); settingsConf = nullptr; } void GreeterConfig::setValue( const QString &group, const QString &key, const QVariant &value, QString strUserName /* = ""*/) { if ((strUserName.isEmpty() && !m_settingsCustom) || group.isEmpty() || key.isEmpty()) { return; } if (!strUserName.isEmpty()) { QString strHomePath = getUserHomePath(strUserName); if (strHomePath.isEmpty()) { qDebug() << "GetUserHomePath failed!"; return; } QSettings userSettings(QString(GREETER_CONFIG_USER_FILE).arg(strHomePath), QSettings::IniFormat); userSettings.beginGroup(group); userSettings.setValue(key, value); userSettings.endGroup(); userSettings.sync(); Q_EMIT changedForUser(group, key, strUserName); } else if (m_settingsCustom) { m_settingsCustom->beginGroup(group); m_settingsCustom->setValue(key, value); m_settingsCustom->endGroup(); m_settingsCustom->sync(); Q_EMIT changed(group, key); } } QVariant GreeterConfig::getValue(const QString &group, const QString &key, QVariant varDefault, QString strUserName /*= ""*/) { QVariant varValue; if (!strUserName.isEmpty()) { QString strHomePath = getUserHomePath(strUserName); if (!strHomePath.isEmpty()) { QSettings userSettings(QString(GREETER_CONFIG_USER_FILE).arg(strHomePath), QSettings::IniFormat); if (userSettings.contains(group + "/" + key)) { userSettings.beginGroup(group); varValue = userSettings.value(key); userSettings.endGroup(); return varValue; } } } if (m_settingsCustom) { if (m_settingsCustom->contains(group + "/" + key)) { m_settingsCustom->beginGroup(group); varValue = m_settingsCustom->value(key); m_settingsCustom->endGroup(); return varValue; } } if (m_setttingsDefault) { if (m_setttingsDefault->contains(group + "/" + key)) { m_setttingsDefault->beginGroup(group); varValue = m_setttingsDefault->value(key); m_setttingsDefault->endGroup(); return varValue; } } return varDefault; } bool GreeterConfig::resetValue(const QString &group, const QString &key, QString strUserName /*= ""*/) { bool bRet = false; if (!strUserName.isEmpty()) { QString strHomePath = getUserHomePath(strUserName); if (!strHomePath.isEmpty()) { QSettings userSettings(QString(GREETER_CONFIG_USER_FILE).arg(strHomePath), QSettings::IniFormat); if (userSettings.contains(group + "/" + key)) { userSettings.beginGroup(group); userSettings.remove(key); userSettings.endGroup(); Q_EMIT changedForUser(group, key, strUserName); bRet = true; } } } if (m_settingsCustom) { if (m_settingsCustom->contains(group + "/" + key)) { m_settingsCustom->beginGroup(group); m_settingsCustom->remove(key); m_settingsCustom->endGroup(); Q_EMIT changed(group, key); bRet = true; } } return bRet; } QString GreeterConfig::printConfig(int nType, QString strUserName /*= ""*/) { // 创建一个空的QJsonObject QJsonObject jsonObject; switch (nType) { case 2: { if (m_settingsCustom) { QStringList keys = m_settingsCustom->allKeys(); for (const QString &key : keys) { jsonObject[key] = m_settingsCustom->value(key).toString(); } } if (!strUserName.isEmpty()) { QString strHomePath = getUserHomePath(strUserName); if (!strHomePath.isEmpty()) { QSettings userSettings(QString(GREETER_CONFIG_USER_FILE).arg(strHomePath), QSettings::IniFormat); QStringList keys = userSettings.allKeys(); for (const QString &key : keys) { jsonObject[key] = userSettings.value(key).toString(); } } } } break; case 1: { if (m_setttingsDefault) { QStringList keys = m_setttingsDefault->allKeys(); for (const QString &key : keys) { jsonObject[key] = m_setttingsDefault->value(key).toString(); } } } break; case 0: default: { if (m_setttingsDefault) { QStringList keys = m_setttingsDefault->allKeys(); for (const QString &key : keys) { jsonObject[key] = m_setttingsDefault->value(key).toString(); } } if (m_settingsCustom) { QStringList keys = m_settingsCustom->allKeys(); for (const QString &key : keys) { jsonObject[key] = m_settingsCustom->value(key).toString(); } } if (!strUserName.isEmpty()) { QString strHomePath = getUserHomePath(strUserName); if (!strHomePath.isEmpty()) { QSettings userSettings(QString(GREETER_CONFIG_USER_FILE).arg(strHomePath), QSettings::IniFormat); QStringList keys = userSettings.allKeys(); for (const QString &key : keys) { jsonObject[key] = userSettings.value(key).toString(); } } } } break; } // 创建QJsonDocument QJsonDocument jsonDoc(jsonObject); return jsonDoc.toJson(); } QString GreeterConfig::getUserHomePath(const QString &strUserName) { if (strUserName.isEmpty()) { return QString(""); } struct passwd *pwdInfo = getpwnam(strUserName.toLatin1().data()); if (pwdInfo) { return QString(pwdInfo->pw_dir); } return QString(""); } ukui-biometric-auth/uniauth-backend/org.ukui.UniauthBackend.yaml0000664000175000017500000000160115167732644023761 0ustar fengfengorg:ukui:UniauthBackend: 1.0.0.1: audit: _type: b _default: false whitelist: _type: as _default: '["/usr/sbin/ukui-greeter","/usr/bin/ukui-screensaver-backend","/usr/bin/ukui-screensaver-dialog","/usr/sbin/lightdm","/usr/bin/ukui-control-center","/usr/bin/ukui-session-tools","/usr/bin/ukui-session","/usr/lib/x86_64-linux-gnu/ukui-polkit/polkit-ukui-authentication-agent-1","/usr/lib/aarch64-linux-gnu/ukui-polkit/polkit-ukui-authentication-agent-1","/usr/lib/loongarch64-linux-gnu/ukui-polkit/polkit-ukui-authentication-agent-1","/usr/lib/mips64el-linux-gnu/ukui-polkit/polkit-ukui-authentication-agent-1","/usr/lib/sw_64-linux-gnu/ukui-polkit/polkit-ukui-authentication-agent-1","/usr/bin/bioauth","/usr/bin/biometric-manager","/usr/bin/ukui-biometric-manager","/usr/sbin/box-manager","/usr/share/kare/plugins/kare-polkit/polkit-kare-authentication-agent-1"]' ukui-biometric-auth/uniauth-backend/org.ukui.UniauthBackend.conf0000664000175000017500000000156515167732631023751 0ustar fengfeng ukui-biometric-auth/uniauth-backend/CMakeLists.txt0000664000175000017500000000253415167732644021214 0ustar fengfengproject(uniauth-backend) set(CMAKE_AUTOMOC ON) # 定义æº�文件 set(bin_SRCS src/main.cpp src/biodeviceinfo.h src/biodeviceinfo.cpp src/serviceinterface.h src/serviceinterface.cpp src/servicemanager.h src/servicemanager.cpp src/personalizeddata.h src/CSingleton.h src/personalizeddata.cpp src/rsac.h src/rsac.cpp src/greeterconfiginterface.h src/greeterconfiginterface.cpp src/greeterconfig.h src/greeterconfig.cpp ) # æ ¹æ�®Qt版本设置包å�«ç›®å½•和链接库 if(QT_VERSION_MAJOR EQUAL 6) include_directories( ${Qt6Core_INCLUDE_DIRS} ${Qt6DBus_INCLUDE_DIRS} ) add_executable(uniauth-backend ${bin_SRCS}) target_link_libraries(uniauth-backend Qt6::Core Qt6::DBus -lukui-log4qt -lcrypto) else() include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ) add_executable(uniauth-backend ${bin_SRCS}) target_link_libraries(uniauth-backend Qt5::Core Qt5::DBus -lukui-log4qt -lcrypto) endif() install(TARGETS uniauth-backend DESTINATION bin) install(FILES org.ukui.UniauthBackend.conf DESTINATION /usr/share/dbus-1/system.d/) install(FILES org.ukui.UniauthBackend.service DESTINATION /usr/share/dbus-1/system-services/) install(FILES org.ukui.UniauthBackend.yaml DESTINATION /usr/share/libpam-biometric/kylin-config/) ukui-biometric-auth/uniauth-backend/org.ukui.UniauthBackend.service0000664000175000017500000000012515167732631024453 0ustar fengfeng[D-BUS Service] Name=org.ukui.UniauthBackend Exec=/usr/bin/uniauth-backend User=root ukui-biometric-auth/bioauth/0000775000175000017500000000000015167732644015041 5ustar fengfengukui-biometric-auth/bioauth/src/0000775000175000017500000000000015167732644015630 5ustar fengfengukui-biometric-auth/bioauth/src/uniauthservice.cpp0000664000175000017500000002162515167732630021373 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "uniauthservice.h" #include #include #define UNIAUTH_DBUS_SERVICE "org.ukui.UniauthBackend" #define UNIAUTH_DBUS_PATH "/org/ukui/UniauthBackend" #define UNIAUTH_DBUS_INTERFACE "org.ukui.UniauthBackend" #define FD_DBUS_SERVICE "org.freedesktop.DBus" #define FD_DBUS_PATH "/org/freedesktop/DBus" #define FD_DBUS_INTERFACE "org.freedesktop.DBus" UniAuthService::UniAuthService(QObject *parent) : QDBusAbstractInterface(UNIAUTH_DBUS_SERVICE, UNIAUTH_DBUS_PATH, UNIAUTH_DBUS_INTERFACE, QDBusConnection::systemBus(), parent) , m_isActivatable(false) { setTimeout(2147483647); QDBusInterface *dbusService = new QDBusInterface(FD_DBUS_SERVICE, FD_DBUS_PATH, FD_DBUS_INTERFACE, QDBusConnection::systemBus()); if (dbusService) { QDBusReply result = dbusService->call(QStringLiteral("ListActivatableNames")); if(!result.isValid()) { qWarning() << "ListActivatableNames error:" << result.error().message(); } else { QStringList listNames = result.value(); if (listNames.contains(UNIAUTH_DBUS_INTERFACE)) { m_isActivatable = true; } } } } // 设置默认设备 void UniAuthService::setDefaultDevice(int bioDevType, QString deviceName) { qDebug() << " bioType : " << bioDevType << "deviceName : " << deviceName; QDBusMessage result = call(QStringLiteral("setDefaultDevice"), bioDevType, deviceName); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "setDefaultDevice error:" << result.errorMessage(); return ; } return ; } // 获å�–默认设备 QString UniAuthService::getDefaultDevice(QString userName, int bioDevType) { QDBusMessage result = call(QStringLiteral("getDefaultDevice"), userName, bioDevType); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getDefaultDevice error:" << result.errorMessage(); return ""; } QList varResult = result.arguments(); if (varResult.size() > 0) { QString strDefDevice = varResult.takeFirst().toString(); return strDefDevice; } else { return ""; } } // 获å�–所有默认设备 QStringList UniAuthService::getAllDefaultDevice(QString userName) { QStringList listDefDevices; QDBusReply result = call(QStringLiteral("getAllDefaultDevice"), userName); if(!result.isValid()) { qWarning() << "getAllDefaultDevice error:" << result.error().message(); } else { listDefDevices = result.value(); } return listDefDevices; } //生物特å¾�开关接å�£ bool UniAuthService::getBioAuthStatus(QString userName, int bioAuthType) { QDBusMessage bioResult = call(QStringLiteral("getBioAuthStatus"), userName, bioAuthType); if(bioResult.type() == QDBusMessage::ErrorMessage) { qWarning() << "getBioStatus error:" << bioResult.errorMessage(); return false; } QList varResult = bioResult.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } void UniAuthService::setBioAuthStatus(int bioAuthType, bool status) { qDebug() << "setBioAuthStatus bioAuthType : " << bioAuthType << "status : " << status; QDBusMessage result = call(QStringLiteral("setBioAuthStatus"), bioAuthType, status); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "setBioAuthStatus error:" << result.errorMessage(); return ; } return ; } // 获å�–最大失败次数 int UniAuthService::getMaxFailedTimes() { QDBusMessage result = call(QStringLiteral("getMaxFailedTimes")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getMaxFailedTimes error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toInt(); } else { return 3; } } // 获å�–是å�¦ä½¿èƒ½å¾®ä¿¡æ‰«ç �登录 bool UniAuthService::getQRCodeEnable() { QDBusMessage result = call(QStringLiteral("getQRCodeEnable")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getQRCodeEnable error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } // 获å�–是å�¦å�Œè®¤è¯� bool UniAuthService::getDoubleAuth() { QDBusMessage result = call(QStringLiteral("getDoubleAuth")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getDoubleAuth error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } // 获å�–用户绑定 bool UniAuthService::getUserBind() { QDBusMessage result = call(QStringLiteral("getUserBind")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getUserBind error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } // 获å�–是å�¦åœ¨æŽ§åˆ¶é�¢æ�¿æ˜¾ç¤º bool UniAuthService::getIsShownInControlCenter() { QDBusMessage result = call(QStringLiteral("getIsShownInControlCenter")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getIsShownInControlCenter error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } // 获å�–是å�¦ä½¿ç”¨ç¬¬ä¸€ä¸ªè®¾å¤‡ bool UniAuthService::getUseFirstDevice() { QDBusMessage result = call(QStringLiteral("getUseFirstDevice")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getUseFirstDevice error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } // 获å�–是å�¦éš�è—�切æ�¢æŒ‰é’® bool UniAuthService::getHiddenSwitchButton() { QDBusMessage result = call(QStringLiteral("getHiddenSwitchButton")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getHiddenSwitchButton error:" << result.errorMessage(); return false; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toBool(); } else { return false; } } // 获å�–正在认è¯�的应用 QStringList UniAuthService::getAuthingApp() { QDBusMessage result = call(QStringLiteral("getAllAuthApp")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getAuthingApp error:" << result.errorMessage(); return QStringList(); } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toStringList(); } else { return QStringList(); } } // 获å�–应用认è¯�的驱动 int UniAuthService::getAuthingAppDrivd(QString appName) { QDBusMessage result = call(QStringLiteral("getAppAuthDrive"),appName); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "getAuthingAppDrivd error:" << result.errorMessage(); return -1; } QList varResult = result.arguments(); if (varResult.size() > 0) { return varResult.takeFirst().toInt(); } else { return -1; } } void UniAuthService::recordAuthDrive(QString appName,int drvid,bool insert) { call(QStringLiteral("recordAuthDrive"),appName,drvid,insert); } bool UniAuthService::isActivatable() { return m_isActivatable; } ukui-biometric-auth/bioauth/src/bioauthwidget.cpp0000664000175000017500000001503715167732630021174 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "bioauthwidget.h" #include "ui_bioauthwidget.h" #include #include "generic.h" #include #include #include "giodbus.h" #include #include #include #include #include "biodeviceswidget.h" int BioAuthWidget::failedCount = 0; BioAuthWidget::BioAuthWidget(QWidget *parent) : QWidget(parent), ui(new Ui::BioAuthWidget), bioAuth(nullptr) { nMaxFailCnt = GetFailedTimes(); ui->setupUi(this); ui->btnRetry->setFlat(true); ui->btnRetry->setVisible(false); ui->btnRetry->setText(tr("Retry")); //ui->btnMore->setVisible(false); } BioAuthWidget::~BioAuthWidget() { delete ui; } void BioAuthWidget::emitSwithToPassword() { Q_EMIT switchToPassword(); } void BioAuthWidget::on_btnPasswdAuth_clicked() { stopAuth(); //Q_EMIT switchToPassword(); QTimer::singleShot(100,this,SLOT(emitSwithToPassword())); } void BioAuthWidget::on_btnMore_clicked() { Q_EMIT selectDevice(); } void BioAuthWidget::on_btnRetry_clicked() { if(bioAuth && !bioAuth->isAuthenticating()) { setMovie(); bioAuth->startAuth(); } } void BioAuthWidget::onBioAuthNotify(const QString ¬ifyMsg) { ui->lblBioNotify->setText(notifyMsg); } void BioAuthWidget::onBioAuthComplete(uid_t uid, bool ret, int retErrNo) { if (!device) return ; if (ret == true) { BioAuthWidget::failedCount = 0; }else{ BioAuthWidget::failedCount++; } setImage(); dup_fd = -1; if(BioAuthWidget::failedCount >= nMaxFailCnt) { // ui->lblBioWarnNotify->setText(tr("Too many unsuccessful attempts,please enter password.")); ui->lblBioWarnNotify->setText(tr("%1 too many unsuccessful attempts,please enter password.").arg(BioDevices::bioTypeToString_tr(device->biotype))); } else { ui->btnRetry->setVisible(true); // ui->lblBioWarnNotify->setText(tr("Authentication failure,there are still %1 remaining opportunities").arg(nMaxFailCnt - BioAuthWidget::failedCount)); ui->lblBioWarnNotify->setText(tr("%1 authentication failure,there are still %2 remaining opportunities").arg(BioDevices::bioTypeToString_tr(device->biotype)).arg(nMaxFailCnt - BioAuthWidget::failedCount)); } Q_EMIT authComplete(uid, ret); } void BioAuthWidget::setMovie() { if(!device || device->biotype == BIOTYPE_FACE) return ; QString typeString = bioTypeToString(device->biotype); QString moviePath = QString("%1/images/%2.gif").arg(GET_STR(UKUI_BIOMETRIC)).arg(typeString); QMovie *movie = new QMovie(moviePath); movie->setScaledSize(QSize(ui->lblBioImage->width(), ui->lblBioImage->height())); ui->lblBioImage->setMovie(movie); movie->start(); ui->btnRetry->setVisible(false); qDebug() << "set movie " << moviePath; } void BioAuthWidget::setImage() { if(!device || device->biotype == BIOTYPE_FACE) return ; QString typeString = bioTypeToString(device->biotype); QString pixmapPath = QString("%1/images/%2.png").arg(GET_STR(UKUI_BIOMETRIC)).arg(typeString); QPixmap pixmap(pixmapPath); pixmap = pixmap.scaled(ui->lblBioImage->width(), ui->lblBioImage->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); ui->lblBioImage->setPixmap(pixmap); if(BioAuthWidget::failedCount >= nMaxFailCnt) { ui->btnRetry->setVisible(false); } else{ ui->btnRetry->setVisible(true); } qDebug() << "set pixmap " << typeString; } void BioAuthWidget::onFrameWritten(int deviceId) { if(dup_fd == -1){ dup_fd = get_server_gvariant_stdout(deviceId); } cv::Mat img; lseek(dup_fd, 0, SEEK_SET); char base64_bufferData[1024*1024]; int rc = read(dup_fd, base64_bufferData, 1024*1024); printf("rc = %d\n", rc); cv::Mat mat2(1, sizeof(base64_bufferData), CV_8U, base64_bufferData); img = cv::imdecode(mat2, cv::IMREAD_COLOR); cv::cvtColor(img,img,cv::COLOR_BGR2RGB); QImage srcQImage = QImage((uchar*)(img.data), img.cols, img.rows, QImage::Format_RGB888); ui->lblBioImage->setPixmap(QPixmap::fromImage(srcQImage).scaled(ui->lblBioImage->size())); ui->btnRetry->setVisible(false); } void BioAuthWidget::hidePasswdButton() { //ui->btnPasswdAuth->hide(); } bool BioAuthWidget::isAuthenticating() { if(bioAuth){ return bioAuth->isAuthenticating(); } return false; } void BioAuthWidget::stopAuth() { if(bioAuth){ bioAuth->stopAuth(); } } void BioAuthWidget::startAuth(uid_t uid, const DeviceInfoPtr device) { if (!device) { qDebug()<<"Device is invalid!!"; return ; } this->uid = uid; this->device = device; //ui->lblBioDevice->setText(tr("Current Device: ") + device.device_shortname); if(bioAuth) { bioAuth->stopAuth(); delete bioAuth; bioAuth = nullptr; } setMovie(); if(BioAuthWidget::failedCount >= nMaxFailCnt) { // ui->lblBioWarnNotify->setText(tr("Too many unsuccessful attempts,please enter password.")); ui->lblBioWarnNotify->setText(tr("%1 too many unsuccessful attempts,please enter password.").arg(BioDevices::bioTypeToString_tr(device->biotype))); return; } else { ui->lblBioWarnNotify->setText(""); } bioAuth = new BioAuth(uid, device, this); connect(bioAuth, &BioAuth::notify, this, &BioAuthWidget::onBioAuthNotify); connect(bioAuth, &BioAuth::authComplete, this, &BioAuthWidget::onBioAuthComplete); connect(bioAuth, &BioAuth::frameWritten,this,&BioAuthWidget::onFrameWritten); if (device->biotype == REMOTE_QRCODE_TYPE) { onBioAuthNotify(tr("Please use wechat to scan the code")); } dup_fd = -1; fd = -1; bioAuth->startAuth(); } void BioAuthWidget::setMoreDevices(bool hasMore) { //ui->btnMore->setVisible(hasMore); } ukui-biometric-auth/bioauth/src/biodeviceswidget.cpp0000664000175000017500000001071015167732630021646 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "biodeviceswidget.h" #include "ui_biodeviceswidget.h" BioDevicesWidget::BioDevicesWidget(QWidget *parent) : QWidget(parent), ui(new Ui::BioDevicesWidget) { ui->setupUi(this); connect(&bioDevices, &BioDevices::deviceCountChanged, this, &BioDevicesWidget::onDeviceCountChanged); } BioDevicesWidget::~BioDevicesWidget() { delete ui; } void BioDevicesWidget::init(uid_t uid) { this->uid = uid; devicesMap = bioDevices.getUserDevices(uid); ui->cmbDeviceTypes->clear(); for(auto i : devicesMap.keys()) { ui->cmbDeviceTypes->addItem(BioDevices::bioTypeToString_tr(i), i); } /* set the default device as current device */ DeviceInfoPtr device = bioDevices.getDefaultDevice(uid); if(device) { int index = ui->cmbDeviceTypes->findData(device->biotype); QList &deviceList = devicesMap[index]; auto iter = std::find_if(deviceList.constBegin(), deviceList.constEnd(), [&](const DeviceInfo &deviceInfo){ return deviceInfo.device_shortname == device->device_shortname; }); int row = iter - deviceList.constBegin(); //qDebug() << "row==" <lwDevices->currentIndex(); int type = ui->cmbDeviceTypes->itemData(ui->cmbDeviceTypes->currentIndex()).toInt(); qDebug() << "row==" <. * **/ #include "loginoptionswidget.h" #include #include #include #include "giodbus.h" #include "generic.h" #include "biotypes.h" #include #include #include #include #include #include #include #include #include #include #if QT_VERSION_MAJOR == 6 // Qt6中æŸ�些头文件路径å�¯èƒ½ä¸�å�Œ #include #include #else #include #include #endif #include "../common/qt_matrix_compat.h" #include #include #include #include #include LoginOptionsWidget::LoginOptionsWidget(QWidget *parent) : QWidget(parent), m_biomericProxy(new BioAuth(this)), m_bioDevices(new BioDevices()), w_timer(nullptr) { m_bioDevices->recordAuthDrive("polkit", 0, false); initUI(); initConnections(); initStyleTheme(); m_mapDisableDev.clear(); } LoginOptionsWidget::~LoginOptionsWidget() {} void LoginOptionsWidget::initUI() { // åˆ�始化UI m_layoutMain = new QVBoxLayout(); m_layoutMain->setContentsMargins(0, 0, 0, 30); m_layoutMain->setSpacing(12); m_layoutMain->setAlignment(Qt::AlignTop); m_widgetImage = new QWidget(); m_widgetImage->setFixedSize(154, 154); m_layoutImage = new QHBoxLayout(); m_layoutImage->setContentsMargins(0, 8, 0, 16); m_layoutImage->setSpacing(0); m_layoutImage->setAlignment(Qt::AlignCenter); m_layoutImage->addSpacerItem(new QSpacerItem(109, 0, QSizePolicy::Expanding)); m_layoutImage->addWidget(m_widgetImage); m_layoutImage->addSpacerItem(new QSpacerItem(109, 0, QSizePolicy::Expanding)); m_widgetImage->hide(); // 人脸识别 m_labelFace = new QLabel(m_widgetImage); m_labelFace->setObjectName("faceLabel"); m_labelFace->setAlignment(Qt::AlignCenter); m_labelFace->setFixedSize(154, 154); QHBoxLayout *layoutFace = new QHBoxLayout(); layoutFace->setContentsMargins(0, 0, 0, 0); layoutFace->setAlignment(Qt::AlignCenter); m_labelFace->setLayout(layoutFace); m_labelFace->hide(); m_labelFaceLoad = new QLabel(); m_labelFaceLoad->setAlignment(Qt::AlignCenter); m_labelFaceLoad->setFixedSize(142, 142); m_labelFaceLoad->setStyleSheet( QString("QLabel{background-color: rgba(230,230,230,0.39); border-radius: %1px; border: 8px solid white;}") .arg(71)); layoutFace->addWidget(m_labelFaceLoad, 0, Qt::AlignVCenter); // 二维ç �窗å�£ m_labelQRCode = new QLabel(m_widgetImage); m_labelQRCode->setObjectName("qrCodeLabel"); m_labelQRCode->setAlignment(Qt::AlignCenter); m_labelQRCode->setFixedSize(154, 154); m_labelQRCode->hide(); QVBoxLayout *layoutQRCode = new QVBoxLayout(); layoutQRCode->setAlignment(Qt::AlignCenter); layoutQRCode->setSpacing(5); m_labelQRCode->setLayout(layoutQRCode); m_labelQRCodeTip = new QLabel(); m_labelQRCodeTip->setFixedSize(22, 22); m_labelQRCodeTip->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(QSize(22, 22))); layoutQRCode->addWidget(m_labelQRCodeTip, 0, Qt::AlignHCenter); m_labelQRCodeMsg = new QLabel(); m_labelQRCodeMsg->setFixedHeight(24); QFont font = m_labelQRCodeMsg->font(); font.setPixelSize(16); m_labelQRCodeMsg->setStyleSheet("QLabel{background-color:rgba(255,255,255,0);color:rgb(255,0,0)}"); m_labelQRCodeMsg->setFont(font); layoutQRCode->addWidget(m_labelQRCodeMsg, 0, Qt::AlignHCenter); // 生物特å¾�等待验è¯�动画 m_labelBioWaiting = new QLabel(m_widgetImage); m_labelBioWaiting->setAlignment(Qt::AlignCenter); m_labelBioWaiting->setFixedSize(154, 154); m_labelBioWaiting->hide(); m_layoutMain->addLayout(m_layoutImage); m_layoutOptBtns = new QHBoxLayout(); m_layoutOptBtns->setContentsMargins(0, 0, 0, 0); m_layoutOptBtns->setSpacing(16); m_labelOptTitle = new QLabel(); m_labelOptTitle->setFixedHeight(30); m_labelOptTitle->setAlignment(Qt::AlignLeft); m_labelOptTitle->setText(tr("Login Options")); m_layoutMain->addWidget(m_labelOptTitle); m_btnGroup = new QButtonGroup(this); m_btnGroup->setExclusive(true); m_layoutOptBtns->setAlignment(Qt::AlignLeft); m_layoutMain->addLayout(m_layoutOptBtns); this->setLayout(m_layoutMain); // 设置水平扩展 QSizePolicy sizePolicy = this->sizePolicy(); sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); this->setSizePolicy(sizePolicy); } void LoginOptionsWidget::SetExtraInfo(QString extra_info, QString info_type) { if (!m_biomericProxy) { qWarning() << "BiometricProxy doesn't exist."; return; } m_biomericProxy->SetExtraInfo(info_type, extra_info); } void LoginOptionsWidget::initConnections() { if (m_biomericProxy) { connect(m_biomericProxy, &BioAuth::notifyDetail, this, &LoginOptionsWidget::onStatusChanged); connect(m_biomericProxy, &BioAuth::frameWritten, this, &LoginOptionsWidget::onFrameWritten); connect(m_biomericProxy, &BioAuth::authComplete, this, &LoginOptionsWidget::onIdentifyComplete); connect(m_biomericProxy, &BioAuth::authFinished, this, &LoginOptionsWidget::onAuthFinished); } if (m_bioDevices) { connect(m_bioDevices, &BioDevices::deviceCountChanged, this, &LoginOptionsWidget::onUSBDeviceCountChange); // readDevicesInfo(); } connect(m_btnGroup, SIGNAL(buttonClicked(int)), this, SLOT(onOptionSelected(int))); } void LoginOptionsWidget::initStyleTheme() { const QByteArray idd("org.ukui.style"); if (QGSettings::isSchemaInstalled(idd)) { m_styleSettings = new QGSettings(idd); } if (m_styleSettings) { connect(m_styleSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { auto styleNameValue = m_styleSettings->get("styleName"); if (styleNameValue.isValid()) { m_strThemeName = styleNameValue.toString(); } } }); auto styleNameValue = m_styleSettings->get("styleName"); if (styleNameValue.isValid()) { m_strThemeName = styleNameValue.toString(); } } } bool LoginOptionsWidget::getCurLoginOpt(int &nLoginOptType, int &nDrvId) { if (m_curDevInfo) { nLoginOptType = convertDeviceType(m_curDevInfo->biotype); nDrvId = m_curDevInfo->device_id; return true; } return false; } unsigned LoginOptionsWidget::getLoginOptCount() { return m_mapDevices.size(); } DeviceInfoPtr LoginOptionsWidget::getFirstDevInfo() { DeviceInfoPtr devInfo = nullptr; struct passwd *pwdInfo = getpwuid(m_uid); if (!pwdInfo) return devInfo; int nDrvId = m_bioDevices->GetLastDevice(pwdInfo->pw_name); if (nDrvId >= 0) { qDebug() << "GetLastDevice:" << nDrvId; DeviceMap::iterator itDevInfo = m_mapDevices.begin(); for (; itDevInfo != m_mapDevices.end(); itDevInfo++) { for (auto devinfo : itDevInfo.value()) { if (devinfo && devinfo->device_id == nDrvId) { if (!isDeviceDisable(devinfo->device_id)) { devInfo = devinfo; break; } } } if (devInfo) { break; } } } if (!devInfo) { DeviceMap::iterator itDevInfo = m_mapDevices.begin(); for (; itDevInfo != m_mapDevices.end(); itDevInfo++) { for (auto devinfo : itDevInfo.value()) { if (devinfo && !isDeviceDisable(devinfo->device_id)) { devInfo = devinfo; break; } } if (devInfo) { break; } } } return devInfo; } bool LoginOptionsWidget::getHasUkeyOptions() { return isShowUkey; } void LoginOptionsWidget::addOptionButton(unsigned uLoginOptType, int nDrvId, QString strDrvName) { if (m_mapOptBtns.contains(nDrvId)) { return; } QToolButton *newButton = new QToolButton(); newButton->setCheckable(true); newButton->setChecked(false); newButton->setFocusPolicy(Qt::NoFocus); newButton->setContentsMargins(16, 16, 16, 16); int nLength = m_btnGroup->buttons().length(); m_btnGroup->addButton(newButton, nLength); m_listDriveId.append(nDrvId); QIcon icon; switch (uLoginOptType) { case LOGINOPT_TYPE_PASSWORD: icon = QIcon(QString("%1/images/ukui-loginopt-password.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_GENERAL_UKEY: icon = QIcon(QString("%1/images/ukui-loginopt-ukey.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_FACE: icon = QIcon(QString("%1/images/ukui-loginopt-face.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_FINGERPRINT: icon = QIcon(QString("%1/images/ukui-loginopt-finger.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_IRIS: icon = QIcon(QString("%1/images/ukui-loginopt-iris.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_VOICEPRINT: icon = QIcon(QString("%1/images/ukui-loginopt-voice.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_FINGERVEIN: icon = QIcon(QString("%1/images/ukui-loginopt-fingervein.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; case LOGINOPT_TYPE_QRCODE: icon = QIcon(QString("%1/images/ukui-loginopt-qrcode.svg").arg(GET_STR(UKUI_BIOMETRIC))); break; } newButton->setIcon(icon); newButton->setToolTip(strDrvName); newButton->setFixedSize(36, 36); if (isDeviceDisable(nDrvId)) { newButton->setDisabled(true); } else { newButton->setDisabled(false); } m_layoutOptBtns->addWidget(newButton); m_mapOptBtns[nDrvId] = newButton; } void LoginOptionsWidget::clearOptionButtons() { QMap::iterator itMapBtn = m_mapOptBtns.begin(); for (; itMapBtn != m_mapOptBtns.end(); itMapBtn++) { if (itMapBtn.value()) { m_btnGroup->removeButton(itMapBtn.value()); m_layoutOptBtns->removeWidget(itMapBtn.value()); itMapBtn.value()->deleteLater(); } } m_listDriveId.clear(); m_mapOptBtns.clear(); } void LoginOptionsWidget::updateOptionButtons() { isShowUkey = false; clearOptionButtons(); addOptionButton(LOGINOPT_TYPE_PASSWORD, -1, tr("Password")); DeviceMap::iterator itMapDev = m_mapDevices.begin(); for (; itMapDev != m_mapDevices.end(); itMapDev++) { for (DeviceInfoPtr devPtr : itMapDev.value()) { if (devPtr) { if (devPtr->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { // ukey 设备类型排在二维ç �å‰�,但实际上应该显示在二维ç �之å�Žï¼Œå› æ­¤æš‚æ—¶ä¸�添加 isShowUkey = true; continue; } addOptionButton(itMapDev.key(), devPtr->device_id, BioDevices::bioTypeToString_tr(devPtr->biotype)); } } } itMapDev = m_mapDevices.begin(); if (isShowUkey) { for (; itMapDev != m_mapDevices.end(); itMapDev++) { for (DeviceInfoPtr devPtr : itMapDev.value()) { if (devPtr && devPtr->biotype == LOGINOPT_TYPE_GENERAL_UKEY) { // 此处æ‰�添加ukey addOptionButton(itMapDev.key(), devPtr->device_id, BioDevices::bioTypeToString_tr(devPtr->biotype)); } } } } // 存在特å¾�但没有æ�’å…¥ukey if (!isShowUkey && m_biomericProxy->GetHasUkeyFeature(m_uid)) { addOptionButton(LOGINOPT_TYPE_GENERAL_UKEY, -2, BioDevices::bioTypeToString_tr(LOGINOPT_TYPE_GENERAL_UKEY)); isShowUkey = true; } m_labelOptTitle->show(); QMap::iterator itMapBtn = m_mapOptBtns.begin(); for (; itMapBtn != m_mapOptBtns.end(); itMapBtn++) { if (itMapBtn.value()) { itMapBtn.value()->show(); } } } void LoginOptionsWidget::setUser(int uid) { bool bNeedUpdateDevInfo = false; if (uid != m_uid) { bNeedUpdateDevInfo = true; } m_uid = uid; if (bNeedUpdateDevInfo) { if (m_bioDevices) { m_bioDevices->setUId(m_uid); } readDevicesInfo(); } } void LoginOptionsWidget::readDevicesInfo() { m_mapDevices.clear(); bool isAuthEnable = m_bioDevices->GetBioAuthEnable(); bool isQRCodeEnable = m_bioDevices->GetQRCodeEnable(); DeviceList deviceList = m_bioDevices->GetDevList(); QStringList listDefDevices = m_bioDevices->getAllDefDevices(); FeatureMap mapFeatures = m_bioDevices->GetUserFeatures(m_uid); qDebug() << m_uid << ",count:" << mapFeatures.size(); for (auto pDeviceInfo : deviceList) { int nDevFeatureCount = 0; if (m_isInAuth && m_curDevInfo && m_curDevInfo->device_id == pDeviceInfo->device_id) { nDevFeatureCount = 1; } else { if (m_uid == -1) { nDevFeatureCount = 0; } else if (mapFeatures.contains(pDeviceInfo->device_shortname)) { nDevFeatureCount = mapFeatures[pDeviceInfo->device_shortname].size(); } } qDebug() << *pDeviceInfo << ",FeatureCount:" << nDevFeatureCount; if (nDevFeatureCount > 0) { if (!isAuthEnable && pDeviceInfo->biotype <= BIOTYPE_VOICEPRINT) continue; if (!isQRCodeEnable && pDeviceInfo->biotype == REMOTE_QRCODE_TYPE) continue; int nDevType = LOGINOPT_TYPE_OTHERS; nDevType = convertDeviceType(pDeviceInfo->biotype); if ((pDeviceInfo->biotype == REMOTE_QRCODE_TYPE || listDefDevices.contains(pDeviceInfo->device_shortname)) && !m_mapDevices.contains(nDevType)) { m_mapDevices[nDevType].push_back(pDeviceInfo); } } } updateOptionButtons(); updateUIStatus(false); // Q_EMIT notifyOptionsChange(m_mapDevices.size()); } void LoginOptionsWidget::startAuth(DeviceInfoPtr device, int uid) { if (!device || !m_biomericProxy || is_Lock) { qWarning() << "BiometricProxy doesn't exist."; return; } if (m_isInAuth) { qDebug() << "Identification is currently under way, stop it"; stopAuth(); } qDebug() << "deviceInfo:" << device->device_id; this->m_curDevInfo = device; this->m_uid = uid; struct passwd *pwdInfo = getpwuid(uid); if (pwdInfo) { this->m_strUserName = pwdInfo->pw_name; } this->m_isStopped = false; this->m_curLoginOptType = convertDeviceType(this->m_curDevInfo->biotype); updateUIStatus(true); if (pwdInfo) { m_bioDevices->SetLastDevice(pwdInfo->pw_name, this->m_curDevInfo->device_id); } startAuth_(); } void LoginOptionsWidget::setSelectedPassword() { if (m_mapOptBtns.contains(-1)) { QToolButton *btn = m_mapOptBtns[-1]; if (btn && btn->isVisible()) { btn->setChecked(true); } m_curDevInfo = nullptr; } } void LoginOptionsWidget::startAuth_() { if (!m_curDevInfo) return; qDebug().noquote() << QString("Identify:[drvid: %1, uid: %2]").arg(m_curDevInfo->device_id).arg(m_uid); m_isInAuth = true; m_dupFD = -1; if (!w_timer) { w_timer = new QTimer(this); w_timer->setInterval(150); connect(w_timer, &QTimer::timeout, this, &LoginOptionsWidget::updatePixmap); } m_waitingPixmap = QIcon::fromTheme("ukui-loading-0-symbolic").pixmap(24, 24); if (m_curLoginOptType == LOGINOPT_TYPE_QRCODE) { m_labelQRCodeTip->setPixmap(m_waitingPixmap); m_labelQRCodeTip->show(); m_labelQRCodeMsg->hide(); } else if (m_curLoginOptType == LOGINOPT_TYPE_FACE) { m_labelFace->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(230,230,230,0.39);").arg(77)); m_labelFace->setPixmap(QPixmap("")); m_labelFaceLoad->setPixmap(m_waitingPixmap); m_labelFaceLoad->show(); } w_timer->start(); m_bioDevices->recordAuthDrive("polkit", m_curDevInfo->device_id, true); m_biomericProxy->startAuth(m_uid, m_curDevInfo); } void LoginOptionsWidget::stopAuth() { m_isStopped = true; if (!m_isInAuth || !m_curDevInfo) { return; } m_biomericProxy->stopAuth(); if (m_retrytimer && m_retrytimer->isActive()) { m_retrytimer->stop(); delete m_retrytimer; m_retrytimer = nullptr; } m_isInAuth = false; Q_EMIT updateImage(QImage()); QImage img; setFaceImg(img); } void LoginOptionsWidget::updatePixmap() { QMatrix matrix; matrix.rotate(90.0); m_waitingPixmap = QtPixmapCompat::transformedPixmap(m_waitingPixmap, matrix, Qt::FastTransformation); if (m_curLoginOptType == LOGINOPT_TYPE_QRCODE) m_labelQRCodeTip->setPixmap(m_waitingPixmap); else if (m_curLoginOptType == LOGINOPT_TYPE_FACE) { m_labelFaceLoad->setPixmap(m_waitingPixmap); } } void LoginOptionsWidget::onAuthFinished() { if (m_bioDevices) { m_bioDevices->recordAuthDrive("polkit", 0, false); } } void LoginOptionsWidget::onIdentifyComplete(int uid, bool ret, int retErrNo) { if (m_isStopped == true) return; if (uid < 0) { readDevicesInfo(); Q_EMIT authComplete(uid, false, -1); return; } qDebug() << retErrNo << uid << m_uid; // 特å¾�识别æˆ�功,而且用户id匹é…� if (retErrNo == DBUS_RESULT_SUCCESS && uid == m_uid) { qDebug() << "Identify success"; Q_EMIT authComplete(uid, true, 0); } else if (retErrNo == -1) { // 特å¾�识别ä¸�匹é…� qDebug() << "Identify failed"; Q_EMIT authComplete(uid, false, 2); } else if (retErrNo == -2) { // 识别å�‘生错误 StatusReslut ret = m_bioDevices->UpdateStatus(m_curDevInfo->device_id); qDebug() << "StatusReslut:" << ret.result << "," << ret.enable << "," << ret.devNum << "," << ret.devStatus << "," << ret.opsStatus << "," << ret.notifyMessageId; // 识别æ“�作超时 if (ret.result == 0 && ret.opsStatus == 10) { // 10 当å‰�时间错误导致网络错误 Q_EMIT authComplete(uid, false, -4); } else if ( ret.result == 0 && (ret.opsStatus == 404 || ret.opsStatus == 304 || ret.opsStatus == 8)) { // 304认è¯�超时, 8网络异常 Q_EMIT authComplete(uid, false, 1); } else if (ret.opsStatus == OPS_IDENTIFY_STOP_BY_USER || ret.opsStatus == OPS_VERIFY_STOP_BY_USER) { Q_EMIT authComplete(uid, false, -2); // 主动å�œæ­¢ï¼Œç›´æŽ¥é‡�试 } else if ( ret.opsStatus == OPS_OPEN_FAIL || ret.opsStatus == OPS_OPEN_ERROR) { // 无法打开设备(设备是å��çš„/被å� ç”¨ï¼‰ï¼Œç›´æŽ¥ç¦�用 Q_EMIT authComplete(uid, false, 5); } else { Q_EMIT authComplete(uid, false, 2); } } else { Q_EMIT authComplete(uid, false, 2); } } QPixmap LoginOptionsWidget::PixmapToRound(const QPixmap &src, int radius) { if (src.isNull()) { return QPixmap(); } QPixmap pixmapa(src); QPixmap pixmap(radius * 2, radius * 2); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); QPainterPath path; path.addEllipse(0, 0, radius * 2, radius * 2); painter.setClipPath(path); painter.drawPixmap(0, 0, radius * 2, radius * 2, pixmapa); return pixmap; } /** * @brief scaledPixmap * @param width * @param height * @param url * @return * 图片缩放 */ QPixmap LoginOptionsWidget::scaledPixmap(int width, int height, QString url) { QFile imgFile(url); if (!imgFile.exists()) { qDebug() << "not find the pixmap file"; return QPixmap(); } QImage image(url); QPixmap pixmap = QPixmap::fromImage(image); if (pixmap.isNull()) { qDebug() << "pixmap is null"; QProcess exec; QString program("file " + url); exec.start(program); exec.waitForFinished(1000); QString output = exec.readAllStandardOutput(); qDebug() << output; if (output.contains("SVG")) { qDebug() << "image format is SVG"; QSvgRenderer render(url); QImage image(width, height, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); render.render(&painter, image.rect()); pixmap.convertFromImage(image); } else if (output.contains("TIFF")) { qDebug() << "image format is TIFF"; } } return pixmap.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); } void LoginOptionsWidget::onFrameWritten(int drvid) { if (!m_curDevInfo) return; if (m_curDevInfo && m_curDevInfo->device_id != drvid || !m_isInAuth) { return; } if (m_dupFD == -1) { m_dupFD = get_server_gvariant_stdout(drvid); } if (m_dupFD <= 0) return; cv::Mat img; lseek(m_dupFD, 0, SEEK_SET); char base64_bufferData[1024 * 1024]; int rc = read(m_dupFD, base64_bufferData, 1024 * 1024); Q_UNUSED(rc); // printf("rc = %d\n", rc); cv::Mat mat2(1, sizeof(base64_bufferData), CV_8U, base64_bufferData); img = cv::imdecode(mat2, cv::IMREAD_COLOR); if (!img.data) return; cv::cvtColor(img, img, cv::COLOR_BGR2RGB); QImage srcQImage = QImage((uchar *)(img.data), img.cols, img.rows, QImage::Format_RGB888); if (isAuthenticating()) { if (m_curLoginOptType == LOGINOPT_TYPE_FACE) { m_labelFace->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(255,255,255,10%);") .arg(77)); setFaceImg(srcQImage); m_labelFace->show(); m_labelQRCode->hide(); } else if (m_curLoginOptType == LOGINOPT_TYPE_QRCODE) { m_labelQRCode->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(255,255,255,100%);") .arg(6)); setQRCode(srcQImage); m_labelQRCode->show(); m_labelQRCodeTip->hide(); m_labelFace->hide(); } else { m_labelFace->hide(); m_labelQRCode->hide(); } } else { m_labelFace->hide(); m_labelQRCode->hide(); } if (w_timer && w_timer->isActive()) { w_timer->stop(); } Q_EMIT updateImage(srcQImage); } void LoginOptionsWidget::setQRCode(QImage &imgQRCode) { if (imgQRCode.isNull()) { imgQRCode.load(QString("%1/images/ukui-qrcode-null.svg").arg(GET_STR(UKUI_BIOMETRIC))); } imgQRCode = imgQRCode.scaled(QSize(150, 150)); m_labelQRCode->setAlignment(Qt::AlignCenter); m_labelQRCode->setPixmap(QPixmap::fromImage(imgQRCode)); } void LoginOptionsWidget::setQRCodeMsg(QString strMsg) { if (strMsg.isEmpty()) { m_labelQRCodeMsg->hide(); // m_labelQRCodeTip->hide(); } else { // 一开始认è¯�时就没有网,直接å�œæ­¢åŠ è½½çŠ¶æ€� if (w_timer && w_timer->isActive()) { w_timer->stop(); } m_labelQRCodeMsg->setText(strMsg); m_labelQRCodeMsg->show(); m_labelQRCodeTip->show(); m_labelQRCodeTip->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(QSize(22, 22))); } } void LoginOptionsWidget::setFaceImg(QImage &imgFace, int nStatus) { QPixmap faceImage; m_labelFace->setFixedSize(154, 154); // 如果头åƒ�文件ä¸�存在,则使用默认头åƒ� if (!imgFace.isNull()) { faceImage = PixmapToRound(QPixmap::fromImage(imgFace), 77); } else { switch (nStatus) { case 1: faceImage = loadSvg(QString("%1/images/ukui-loginopt-lose.svg").arg(GET_STR(UKUI_BIOMETRIC)), "black", 48); m_labelFace->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(230,230,230,40%);") .arg(77)); break; case 2: faceImage = loadSvg(QString("%1/images/ukui-loginopt-smile.svg").arg(GET_STR(UKUI_BIOMETRIC)), "gray", 48); m_labelFace->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(230,230,230,100%);") .arg(77)); break; default: faceImage = loadSvg(QString("%1/images/ukui-loginopt-smile.svg").arg(GET_STR(UKUI_BIOMETRIC)), "black", 48); m_labelFace->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(230,230,230,40%);") .arg(77)); break; } } m_labelFace->setAlignment(Qt::AlignCenter); m_labelFace->setPixmap(faceImage); m_labelFaceLoad->hide(); } void LoginOptionsWidget::onStatusChanged(int drvid, const QString &message) { if (!m_isInAuth || !m_curDevInfo) { return; } if (drvid != m_curDevInfo->device_id) { return; } // Q_EMIT updateAuthMsg(message); } void LoginOptionsWidget::setCurrentDevice(int drvid) { DeviceInfoPtr pDeviceInfo = findDeviceById(drvid); if (pDeviceInfo) { setCurrentDevice(pDeviceInfo); } } void LoginOptionsWidget::setCurrentDevice(const QString &deviceName) { DeviceInfoPtr pDeviceInfo = findDeviceByName(deviceName); if (pDeviceInfo) { setCurrentDevice(pDeviceInfo); } } void LoginOptionsWidget::setCurrentDevice(const DeviceInfoPtr &pDeviceInfo) { this->m_curDevInfo = pDeviceInfo; } DeviceInfoPtr LoginOptionsWidget::findDeviceById(int drvid) { for (int type : m_mapDevices.keys()) { DeviceList &deviceList = m_mapDevices[type]; auto iter = std::find_if( deviceList.begin(), deviceList.end(), [&](DeviceInfoPtr ptr) { return ptr->device_id == drvid; }); if (iter != deviceList.end()) { return *iter; } } return DeviceInfoPtr(); } DeviceInfoPtr LoginOptionsWidget::findDeviceByName(const QString &name) { for (int type : m_mapDevices.keys()) { DeviceList &deviceList = m_mapDevices[type]; auto iter = std::find_if( deviceList.begin(), deviceList.end(), [&](DeviceInfoPtr ptr) { return ptr->device_shortname == name; }); if (iter != deviceList.end()) { return *iter; } } return DeviceInfoPtr(); } QString LoginOptionsWidget::GetDefaultDevice(uid_t uid, int bioType) { QString defaultDeviceName = ""; DeviceInfoPtr pDeviceInfo = m_bioDevices->getDefaultDevice(uid, bioType); if (pDeviceInfo) { defaultDeviceName = pDeviceInfo->device_shortname; } qDebug() << "default device: " << defaultDeviceName; return defaultDeviceName; } QString LoginOptionsWidget::GetDefaultDevice(uid_t uid) { QString defaultDeviceName = ""; DeviceInfoPtr pDeviceInfo = m_bioDevices->getDefaultDevice(uid); if (pDeviceInfo) { defaultDeviceName = pDeviceInfo->device_shortname; } qDebug() << "default device: " << defaultDeviceName; return defaultDeviceName; } void LoginOptionsWidget::onUSBDeviceCountChange(int newNum) { qDebug() << "deviceNewNum:" << newNum; int savedCount = 0; for (int type : m_mapDevices.keys()) savedCount += m_mapDevices.value(type).count(); readDevicesInfo(); int count = 0; for (int type : m_mapDevices.keys()) count += m_mapDevices.value(type).count(); // 设备数é‡�å�‘生了å�˜åŒ– if (count != savedCount) { updateOptionButtons(); Q_EMIT notifyOptionsChange(count); } updateUIStatus(false); } void LoginOptionsWidget::updateUkeyUIStatus(int type) { m_labelFace->hide(); m_labelQRCode->hide(); m_widgetImage->hide(); setFixedHeight(m_labelOptTitle->height() + 12 + 36); Q_EMIT this->updateWndSize(this->m_curLoginOptType, this->m_mapOptBtns.size()); } void LoginOptionsWidget::updateUIStatus(bool update, int nPreOptType /* = -1*/) { if (m_mapOptBtns.contains(-1)) { QToolButton *btn = m_mapOptBtns[-1]; if (btn && btn->isVisible()) { btn->setChecked(true); } } if (m_curDevInfo) { if (m_mapOptBtns.contains(m_curDevInfo->device_id)) { QToolButton *btn = m_mapOptBtns[m_curDevInfo->device_id]; if (btn) { btn->setChecked(true); } } } if (update) { bool isSameType = false; if (nPreOptType != -1) { isSameType = (m_curLoginOptType == nPreOptType); m_curLoginOptType = nPreOptType; } if (m_curLoginOptType == LOGINOPT_TYPE_FACE) { m_labelFace->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(255,255,255,10%);") .arg(77)); m_labelFace->show(); m_labelQRCode->hide(); m_widgetImage->show(); setFixedHeight(m_labelOptTitle->height() + 12 + 36 + 12 + 154 + 48); } else if (m_curLoginOptType == LOGINOPT_TYPE_QRCODE) { if (!isSameType) { m_labelQRCode->setStyleSheet( QString("border-radius: %1px; border:0px solid white;background-color: rgba(255,255,255,100%);") .arg(6)); QImage img; setQRCode(img); m_labelQRCode->show(); m_labelFace->hide(); m_widgetImage->show(); setFixedHeight(m_labelOptTitle->height() + 12 + 36 + 12 + 154 + 48); } } else { m_labelFace->hide(); m_labelQRCode->hide(); if (m_curLoginOptType == LOGINOPT_TYPE_FINGERPRINT || m_curLoginOptType == LOGINOPT_TYPE_FINGERVEIN || m_curLoginOptType == LOGINOPT_TYPE_IRIS || m_curLoginOptType == LOGINOPT_TYPE_VOICEPRINT) { m_widgetImage->show(); setFixedHeight(m_labelOptTitle->height() + 12 + 36 + 12 + 154 + 48); } else { m_widgetImage->hide(); setFixedHeight(m_labelOptTitle->height() + 12 + 36 + 24); } } Q_EMIT this->updateWndSize(this->m_curLoginOptType, this->m_mapOptBtns.size()); } } void LoginOptionsWidget::onOptionSelected(int nIndex) { if (nIndex < 0) return; if (nIndex < m_listDriveId.size()) { DeviceInfoPtr info = findDeviceById(m_listDriveId[nIndex]); if (info && !isDeviceDisable(info->device_id)) { Q_EMIT optionSelected(convertDeviceType(info->biotype), info); this->m_curLoginOptType = convertDeviceType(info->biotype); } else if (nIndex == 0 && m_listDriveId[nIndex] == -1) { stopAuth(); m_curDevInfo = nullptr; Q_EMIT optionSelected(LOGINOPT_TYPE_PASSWORD, nullptr); this->m_curLoginOptType = LOGINOPT_TYPE_PASSWORD; } else if (m_listDriveId[nIndex] == -2) { // 存在ukey特å¾�,但未æ�’å…¥ukey stopAuth(); m_curDevInfo = nullptr; Q_EMIT optionSelected(LOGINOPT_TYPE_GENERAL_UKEY, nullptr); this->m_curLoginOptType = LOGINOPT_TYPE_GENERAL_UKEY; } } } int LoginOptionsWidget::convertDeviceType(int nDevType) { int nLoginOptType = LOGINOPT_TYPE_OTHERS; switch (nDevType) { case BIOTYPE_FINGERPRINT: nLoginOptType = LOGINOPT_TYPE_FINGERPRINT; break; case BIOTYPE_FINGERVEIN: nLoginOptType = LOGINOPT_TYPE_FINGERVEIN; break; case BIOTYPE_IRIS: nLoginOptType = LOGINOPT_TYPE_IRIS; break; case BIOTYPE_FACE: nLoginOptType = LOGINOPT_TYPE_FACE; break; case BIOTYPE_VOICEPRINT: nLoginOptType = LOGINOPT_TYPE_VOICEPRINT; break; case UniT_General_Ukey: nLoginOptType = LOGINOPT_TYPE_GENERAL_UKEY; break; case UniT_Advanced_Ukey: nLoginOptType = LOGINOPT_TYPE_ADVANCED_UKEY; break; case REMOTE_QRCODE_TYPE: nLoginOptType = LOGINOPT_TYPE_QRCODE; break; default: nLoginOptType = LOGINOPT_TYPE_OTHERS; break; } return nLoginOptType; } void LoginOptionsWidget::setDeviceDisable(int nDevId, bool bDisable) { if (bDisable) { m_mapDisableDev[m_uid][nDevId] = true; QMap::iterator itMapBtn = m_mapOptBtns.begin(); for (; itMapBtn != m_mapOptBtns.end(); itMapBtn++) { if (itMapBtn.key() == nDevId && itMapBtn.value()) { itMapBtn.value()->setDisabled(true); break; } } } else { m_mapDisableDev[m_uid][nDevId] = false; QMap::iterator itMapBtn = m_mapOptBtns.begin(); for (; itMapBtn != m_mapOptBtns.end(); itMapBtn++) { if (itMapBtn.key() == nDevId && itMapBtn.value()) { itMapBtn.value()->setDisabled(false); break; } } } } void LoginOptionsWidget::setAllDeviceDisable(bool bDisable) { if (bDisable) { QMap::iterator itMapBtn = m_mapOptBtns.begin(); for (; itMapBtn != m_mapOptBtns.end(); itMapBtn++) { m_mapDisableDev[m_uid][itMapBtn.key()] = true; if (itMapBtn.value()) { itMapBtn.value()->setDisabled(true); } } } else { QMap::iterator itMapBtn = m_mapOptBtns.begin(); for (; itMapBtn != m_mapOptBtns.end(); itMapBtn++) { m_mapDisableDev[m_uid][itMapBtn.key()] = false; if (itMapBtn.value()) { itMapBtn.value()->setDisabled(false); } } } } bool LoginOptionsWidget::isDeviceDisable(int nDevId) { if (m_mapDisableDev[m_uid].contains(nDevId)) { return m_mapDisableDev[m_uid][nDevId]; } return false; } void LoginOptionsWidget::lockStatusChanged(bool locked) { if (locked) { is_Lock = true; stopAuth(); } else { is_Lock = false; readDevicesInfo(); } } QPixmap LoginOptionsWidget::loadSvg(QString path, QString color, int size) { int origSize = size; const auto ratio = qApp->devicePixelRatio(); if (2 == ratio) { size += origSize; } else if (3 == ratio) { size += origSize; } QPixmap pixmap(size, size); QSvgRenderer renderer(path); pixmap.fill(Qt::transparent); QPainter painter; painter.begin(&pixmap); renderer.render(&painter); painter.end(); pixmap.setDevicePixelRatio(ratio); return drawSymbolicColoredPixmap(pixmap, color); } QPixmap LoginOptionsWidget::drawSymbolicColoredPixmap(QPixmap &source, QString cgColor) { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if ("white" == cgColor) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else if ("black" == cgColor) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } else if ("gray" == cgColor) { color.setRed(152); color.setGreen(163); color.setBlue(164); img.setPixelColor(x, y, color); } else if ("blue" == cgColor) { color.setRed(61); color.setGreen(107); color.setBlue(229); img.setPixelColor(x, y, color); } else { return source; } } } } return QPixmap::fromImage(img); } QPixmap LoginOptionsWidget::scaledSmoothPixmap(const QPixmap &src, int nWidth, int nHeight) { if (src.isNull()) { return QPixmap(); } QPixmap pixmapa(src); QPixmap pixmap(nWidth, nHeight); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); painter.drawPixmap(0, 0, nWidth, nHeight, pixmapa); return pixmap; } void LoginOptionsWidget::startBioWaiting(unsigned uCurLoginOptType) { if (uCurLoginOptType == m_nCurBioWaitingType || (uCurLoginOptType != LOGINOPT_TYPE_FINGERPRINT && uCurLoginOptType != LOGINOPT_TYPE_FINGERVEIN && uCurLoginOptType != LOGINOPT_TYPE_IRIS && uCurLoginOptType != LOGINOPT_TYPE_VOICEPRINT)) { return; } m_nCurBioWaitingType = uCurLoginOptType; if (!m_timerBioWaiting) { m_timerBioWaiting = new QTimer(this); m_timerBioWaiting->setInterval(100); } if (m_timerBioWaiting) { if (m_timerBioWaiting->isActive()) { m_timerBioWaiting->stop(); } // é‡�新连接信å�·æ§½ disconnect(m_timerBioWaiting, nullptr, this, nullptr); connect(m_timerBioWaiting, &QTimer::timeout, this, [&, this, uCurLoginOptType]() { m_nBioWaitingFrame += 1; QString strPicName = ""; QString strBasePath = ":/image/assets/biowaiting"; if (m_strThemeName == "ukui-dark" || m_strThemeName == "ukui-black") { strBasePath = ":/image/assets/biowaiting/dark"; } switch (uCurLoginOptType) { case LOGINOPT_TYPE_FINGERPRINT: { if (m_nBioWaitingFrame >= 15) { m_nBioWaitingFrame = 0; } strPicName = QString("%1/fingerprint%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_FINGERVEIN: { if (m_nBioWaitingFrame >= 12) { m_nBioWaitingFrame = 0; } strPicName = QString("%1/fingervein%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_IRIS: { if (m_nBioWaitingFrame >= 12) { m_nBioWaitingFrame = 0; } strPicName = QString("%1/iris%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_VOICEPRINT: { if (m_nBioWaitingFrame >= 8) { m_nBioWaitingFrame = 0; } strPicName = QString("%1/voiceprint%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; default: break; } if (!strPicName.isEmpty()) { QPixmap pixmap; if (QPixmapCache::find(strPicName, &pixmap)) { m_labelBioWaiting->setPixmap(pixmap); } else { pixmap = scaledSmoothPixmap(QPixmap(strPicName), 154, 154); if (!pixmap.isNull()) { QPixmapCache::insert(strPicName, pixmap); m_labelBioWaiting->setPixmap(pixmap); } } m_labelBioWaiting->show(); } }); m_timerBioWaiting->start(); m_nBioWaitingFrame = 0; QString strPicName = ""; QString strBasePath = ":/image/assets/biowaiting"; if (m_strThemeName == "ukui-dark" || m_strThemeName == "ukui-black") { strBasePath = ":/image/assets/biowaiting/dark"; } switch (uCurLoginOptType) { case LOGINOPT_TYPE_FINGERPRINT: { strPicName = QString("%1/fingerprint%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_FINGERVEIN: { strPicName = QString("%1/fingervein%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_IRIS: { strPicName = QString("%1/iris%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_VOICEPRINT: { strPicName = QString("%1/voiceprint%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; default: break; } if (!strPicName.isEmpty()) { QPixmap pixmap; if (QPixmapCache::find(strPicName, &pixmap)) { m_labelBioWaiting->setPixmap(pixmap); } else { pixmap = scaledSmoothPixmap(QPixmap(strPicName), 154, 154); if (!pixmap.isNull()) { QPixmapCache::insert(strPicName, pixmap); m_labelBioWaiting->setPixmap(pixmap); } } m_labelBioWaiting->show(); } } } void LoginOptionsWidget::stopBioWaiting(bool isDisable /* = false*/) { if (m_timerBioWaiting) { if (m_timerBioWaiting->isActive()) { m_timerBioWaiting->stop(); } } m_nBioWaitingFrame = 0; if (isDisable) { QString strPicName = ""; QString strBasePath = ":/image/assets/biowaiting"; if (m_strThemeName == "ukui-dark" || m_strThemeName == "ukui-black") { strBasePath = ":/image/assets/biowaiting/dark"; } switch (m_nCurBioWaitingType) { case LOGINOPT_TYPE_FINGERPRINT: { strPicName = QString("%1/fingerprint%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_FINGERVEIN: { strPicName = QString("%1/fingervein%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_IRIS: { strPicName = QString("%1/iris%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; case LOGINOPT_TYPE_VOICEPRINT: { strPicName = QString("%1/voiceprint%2.svg").arg(strBasePath).arg(m_nBioWaitingFrame); } break; default: break; } if (!strPicName.isEmpty()) { QPixmap pixmap; if (QPixmapCache::find(strPicName, &pixmap)) { m_labelBioWaiting->setPixmap(pixmap); } else { pixmap = scaledSmoothPixmap(QPixmap(strPicName), 154, 154); if (!pixmap.isNull()) { QPixmapCache::insert(strPicName, pixmap); m_labelBioWaiting->setPixmap(pixmap); } } } } else { m_labelBioWaiting->hide(); } m_nCurBioWaitingType = -1; } ukui-biometric-auth/bioauth/src/bioauth.cpp0000664000175000017500000001651615167732644020000 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "bioauth.h" #include #include #include BioAuth::BioAuth(qint32 uid, const DeviceInfoPtr deviceInfo, QObject *parent) : QObject(parent), uid(uid), deviceInfo(deviceInfo), isInAuthentication(false) { init(); } BioAuth::BioAuth(QObject *parent) : QObject(parent) , isInAuthentication(false) { init(); } void BioAuth::init() { serviceInterface = new QDBusInterface(BIO_DBUS_SERVICE, BIO_DBUS_PATH, BIO_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(serviceInterface, SIGNAL(StatusChanged(int, int)), this, SLOT(onStatusChanged(int,int))); connect(serviceInterface, SIGNAL(FrameWritten(int)), this, SLOT(onFrameWritten(int))); serviceInterface->setTimeout(2147483647); } BioAuth::~BioAuth() { // stopAuth(); } void BioAuth::setDevice(const DeviceInfoPtr deviceInfo) { this->deviceInfo = deviceInfo; } void BioAuth::setUid(qint32 uid) { this->uid = uid; } void BioAuth::startUkeyAuth() { // stopAuth(); if (!deviceInfo) { qDebug()<<"DeviceInfo not valid!!"; return; } /* 开始认è¯�识别 */ LOG() << "start biometric verification"; QList args; args << QVariant(deviceInfo->device_id) << QVariant(2) << QVariant(uid); isInAuthentication = true; QDBusPendingCall call = serviceInterface->asyncCallWithArgumentList("UkeyIdentify", args); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BioAuth::onIdentityComplete); } DeviceInfoPtr BioAuth::getDevice() { return this->deviceInfo; } void BioAuth::startAuth() { // stopAuth(); if (!deviceInfo) { qDebug()<<"DeviceInfo not valid!!"; return; } /* 开始认è¯�识别 */ LOG() << "start biometric verification"; QList args; args << QVariant(deviceInfo->device_id) << QVariant(uid) << QVariant(0) << QVariant(-1); isInAuthentication = true; qDebug()<biotype == LOGINOPT_TYPE_GENERAL_UKEY){ QList args1; args1 << QVariant(deviceInfo->device_id) << QVariant(2) << QVariant(uid); QDBusPendingCall call = serviceInterface->asyncCallWithArgumentList("UkeyIdentify", args1); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BioAuth::onIdentityComplete); }else{ //使用sudo等命令时,ä¸�å�œæ­¢è®¾å¤‡ï¼Œå½“存在其他å�¯è®¤è¯�设备时,使用其他å�¯è®¤è¯�设备,å�¦åˆ™ä½¿ç”¨å¯†ç � if(qAppName() != "bioauth"){ //stopops在identify之å‰�使用时,ä¸�è¦�调用getFeaturelist,å�¦åˆ™ä¼šå‡ºçްidentify被å�œæ­¢çš„现象,应该时框架的bug。 serviceInterface->call("StopOps", QVariant(deviceInfo->device_id), QVariant(3000)); } QDBusPendingCall call = serviceInterface->asyncCallWithArgumentList("Identify", args); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BioAuth::onIdentityComplete); } } bool BioAuth::GetHasUkeyFeature(int uid, int indexStart, int indexEnd) { QList qlist; FeatureInfo *featureInfo; int listsize; QDBusMessage result = serviceInterface->call(QStringLiteral("GetAllFeatureList"),uid,indexStart,indexEnd); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return false; } QList variantList = result.arguments(); listsize = variantList[0].value(); variantList[1].value() >> qlist; for (int i = 0; i < listsize; i++) { featureInfo = new FeatureInfo; qlist[i].variant().value() >> *featureInfo; if(featureInfo->biotype == LOGINOPT_TYPE_GENERAL_UKEY){ delete featureInfo; return true; } delete featureInfo; } return false; } int BioAuth::SetExtraInfo(QString info_type,QString extra_info) { QDBusReply reply = serviceInterface->call(QStringLiteral("SetExtraInfo"), info_type, extra_info); if(!reply.isValid()) { qWarning() << "SetExtraInfo error:" << reply.error(); return -1; } return reply.value(); } void BioAuth::startAuth(qint32 uid, const DeviceInfoPtr deviceInfo) { if (!deviceInfo) { return ; } this->uid = uid; this->deviceInfo = deviceInfo; startAuth(); } void BioAuth::stopAuth() { if(!isInAuthentication) return ; if (!deviceInfo) { qDebug()<<"DeviceInfo not valid!!"; return; } QDBusReply reply = serviceInterface->call("StopOps", QVariant(deviceInfo->device_id), QVariant(3000)); emit authFinished(); if(!reply.isValid()) qWarning() << "StopOps error: " << reply.error(); isInAuthentication = false; } bool BioAuth::isAuthenticating() { return isInAuthentication; } void BioAuth::onIdentityComplete(QDBusPendingCallWatcher *watcher) { emit authFinished(); QDBusPendingReply reply = *watcher; if(reply.isError()){ isInAuthentication = false; LOG() << reply.error(); Q_EMIT authComplete(-1, false, -1); return; } qint32 result = reply.argumentAt(0).toInt(); qint32 retUid = reply.argumentAt(1).toInt(); LOG() << "Identify complete: " << result << " " << retUid << " " << uid; /* 识别生物特å¾�æˆ�功,å�‘é€�认è¯�结果 */ if(isInAuthentication){ isInAuthentication = false; if(result == DBUS_RESULT_SUCCESS && retUid == uid){ Q_EMIT authComplete(retUid, true, result); }else { Q_EMIT authComplete(uid, false, result); } } } void BioAuth::onFrameWritten(int deviceId) { Q_EMIT frameWritten(deviceId); } void BioAuth::onStatusChanged(int deviceId, int statusType) { if(statusType != STATUS_NOTIFY) return; LOG() << "status changed " << deviceId << " " << statusType; QDBusMessage msg = serviceInterface->call("GetNotifyMesg", QVariant(deviceId)); if(msg.type() == QDBusMessage::ErrorMessage){ LOG() << msg.errorMessage(); return; } if(deviceInfo && deviceInfo->device_id != deviceId){ return ; } QString message = msg.arguments().at(0).toString(); LOG() << message; Q_EMIT notify(message); Q_EMIT notifyDetail(deviceId, message); } ukui-biometric-auth/bioauth/src/biotypes.cpp0000664000175000017500000000726215167732630020174 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "biotypes.h" #include QDBusArgument &operator<<(QDBusArgument &argument, const DeviceInfo &deviceInfo) { argument.beginStructure(); argument << deviceInfo.device_id << deviceInfo.device_shortname << deviceInfo.device_fullname << deviceInfo.driver_enable << deviceInfo.device_available << deviceInfo.biotype << deviceInfo.stotype << deviceInfo.eigtype << deviceInfo.vertype << deviceInfo.idtype << deviceInfo.bustype << deviceInfo.dev_status << deviceInfo.ops_status; argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, DeviceInfo &deviceInfo) { argument.beginStructure(); argument >> deviceInfo.device_id >> deviceInfo.device_shortname >> deviceInfo.device_fullname >> deviceInfo.driver_enable >> deviceInfo.device_available >> deviceInfo.biotype >> deviceInfo.stotype >> deviceInfo.eigtype >> deviceInfo.vertype >> deviceInfo.idtype >> deviceInfo.bustype >> deviceInfo.dev_status >> deviceInfo.ops_status; argument.endStructure(); return argument; } bool DeviceInfo::operator==(const DeviceInfo& deviceInfo) const { if(this->device_shortname == deviceInfo.device_shortname && this->device_available == deviceInfo.device_available) return true; return false; } QDebug& operator<<(QDebug &stream, const DeviceInfo &deviceInfo) { stream << deviceInfo.device_id << deviceInfo.device_shortname << deviceInfo.biotype << deviceInfo.device_available; return stream; } QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo) { stream << "[" << deviceInfo.device_id << deviceInfo.device_shortname << deviceInfo.device_fullname << deviceInfo.biotype << deviceInfo.driver_enable << deviceInfo.device_available << "]"; return stream; } /* For the type FeatureInfo */ QDBusArgument &operator<<(QDBusArgument &argument, const FeatureInfo &featureInfo) { argument.beginStructure(); argument << featureInfo.uid << featureInfo.biotype << featureInfo.device_shortname << featureInfo.index << featureInfo.index_name; argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, FeatureInfo &featureInfo) { argument.beginStructure(); argument >> featureInfo.uid >> featureInfo.biotype >> featureInfo.device_shortname >> featureInfo.index >> featureInfo.index_name; argument.endStructure(); return argument; } QString bioTypeToString(int type) { switch(type) { case BIOTYPE_FINGERPRINT: return ("FingerPrint"); case BIOTYPE_FINGERVEIN: return ("FingerVein"); case BIOTYPE_IRIS: return ("Iris"); case BIOTYPE_FACE: return ("Face"); case LOGINOPT_TYPE_GENERAL_UKEY: return ("ukey"); case BIOTYPE_VOICEPRINT: return ("VoicePrint"); } return QString(); } ukui-biometric-auth/bioauth/src/biodevices.cpp0000664000175000017500000006263715167732644020466 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "biodevices.h" #include #include #include #include #include #include #include #include "generic.h" BioDevices::BioDevices(bool isIgnoreQrCode, QObject *parent) : QObject(parent) , m_uniAuthService(new UniAuthService(this)) , isShowHotPlug(false) , useFirstDevice(false) , m_isIgnoreQrCode(isIgnoreQrCode) { connectToService(); m_listPriority.clear(); m_listPriority.push_back(BIOTYPE_FACE); m_listPriority.push_back(BIOTYPE_FINGERPRINT); m_listPriority.push_back(BIOTYPE_IRIS); m_listPriority.push_back(BIOTYPE_VOICEPRINT); m_listPriority.push_back(BIOTYPE_FINGERVEIN); m_listPriority.push_back(REMOTE_QRCODE_TYPE); m_listPriority.push_back(LOGINOPT_TYPE_GENERAL_UKEY); } void BioDevices::setUId(int nUId) { m_nUId = nUId; getDevicesList(); } void BioDevices::connectToService() { qRegisterMetaType(); qDBusRegisterMetaType(); serviceInterface = new QDBusInterface(BIO_DBUS_SERVICE, BIO_DBUS_PATH, BIO_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(serviceInterface, SIGNAL(USBDeviceHotPlug(int, int, int)), this, SLOT(onUSBDeviceHotPlug(int, int, int))); serviceInterface->setTimeout(2147483647); } void BioDevices::onUSBDeviceHotPlug(int deviceId, int action, int devNumNow) { qDebug() << deviceId << action << devNumNow; QString text = ""; if (action == -1) { DeviceInfoPtr device = findDevice(deviceId); if (device) text = tr("Unplugging of %1 device detected").arg(bioTypeToString_tr(device->biotype)); } getDevicesList(); emit deviceCountChanged(deviceInfos.size()); if (action == 1) { DeviceInfoPtr device = findDevice(deviceId); if (device) text = tr("%1 device insertion detected").arg(bioTypeToString_tr(device->biotype)); } if (isShowHotPlug && text != "") { QDBusInterface iface( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", QDBusConnection::sessionBus()); QList args; args << (tr("Biometric Manager")) << ((unsigned int)0) << "biometric-manager" << tr("biometric") << text << QStringList() << QVariantMap() << (int)-1; iface.callWithArgumentList(QDBus::AutoDetect, "Notify", args); } } bool BioDevices::GetBioAuthEnable(uid_t uid) { if (m_uniAuthService && m_uniAuthService->isActivatable()) { struct passwd *pwd = getpwuid(uid); if (pwd) { return m_uniAuthService->getBioAuthStatus(pwd->pw_name, ENABLETYPE_BIO); } else { return false; } } else { QString configPath = "/etc/biometric-auth/ukui-biometric.conf"; QSettings settings(configPath, QSettings::IniFormat); qDebug() << "configure path: " << settings.fileName(); if (settings.allKeys().contains("EnableAuth")) { return settings.value("EnableAuth").toBool(); } else { QSettings sysSettings(GET_STR(CONFIG_FILE), QSettings::IniFormat); if (sysSettings.contains("EnableAuth")) return sysSettings.value("EnableAuth").toBool(); else return true; } } } /** * 获å�–设备列表 */ void BioDevices::getDevicesList() { /* 返回值为 i -- int å’Œ av -- array of variant */ QDBusMessage msg = serviceInterface->call("GetDevList"); if (msg.type() == QDBusMessage::ErrorMessage) { LOG() << msg.errorMessage(); return; } /* 设备数é‡� */ int deviceNum = msg.arguments().at(0).toInt(); bool bEnableBioAuth = GetBioAuthEnable(); /* 读å�–设备详细信æ�¯ï¼Œå¹¶å­˜å‚¨åˆ°åˆ—表中 */ QDBusArgument argument = msg.arguments().at(1).value(); QList infos; argument >> infos; deviceInfos.clear(); for (int i = 0; i < deviceNum; i++) { DeviceInfoPtr pDeviceInfo = std::make_shared(); infos.at(i).value() >> *pDeviceInfo; if (pDeviceInfo->device_available > 0) { // 设备å�¯ç”¨ if (pDeviceInfo->biotype == REMOTE_QRCODE_TYPE && m_isIgnoreQrCode) continue; if (!bEnableBioAuth && pDeviceInfo->biotype <= BIOTYPE_VOICEPRINT) continue; deviceInfos.push_back(pDeviceInfo); } } } int BioDevices::count() { return deviceInfos.size(); } int BioDevices::GetUserDevCount(int uid) { int count = 0; QDBusMessage msg = serviceInterface->call("GetDevList"); if (msg.type() == QDBusMessage::ErrorMessage) { LOG() << msg.errorMessage(); return 0; } int deviceNum = msg.arguments().at(0).toInt(); QDBusArgument argument = msg.arguments().at(1).value(); QList infos; argument >> infos; for (int i = 0; i < deviceNum; i++) { DeviceInfoPtr pDeviceInfo = std::make_shared(); infos.at(i).value() >> *pDeviceInfo; if (pDeviceInfo->device_available > 0 && GetUserDevFeatureCount(uid, pDeviceInfo->device_id) > 0) // 设备å�¯ç”¨ count++; } return count; } FeatureMap BioDevices::GetUserFeatures(int uid) { FeatureMap featureMap; QList qlist; int listsize; QDBusMessage result = serviceInterface->call(QStringLiteral("GetAllFeatureList"), uid, 0, -1); if (result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return featureMap; } QList variantList = result.arguments(); listsize = variantList[0].value(); variantList[1].value() >> qlist; for (int i = 0; i < listsize; i++) { FeatureInfoPtr pFeatureInfo = std::make_shared(); qlist[i].variant().value() >> *pFeatureInfo; featureMap[pFeatureInfo->device_shortname].append(pFeatureInfo); } return featureMap; } int BioDevices::GetUserDevFeatureCount(int uid, int drvid) { QDBusMessage FeatureResult = serviceInterface->call(QStringLiteral("GetFeatureList"), drvid, uid, 0, -1); if (FeatureResult.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetFeatureList error:" << FeatureResult.errorMessage(); return 0; } return FeatureResult.arguments().takeFirst().toInt(); } int BioDevices::getFeatureCount(int uid, int indexStart, int indexEnd) { int res = 0; for (int i = 0; i < deviceInfos.count(); i++) { DeviceInfoPtr deviceInfo = deviceInfos.at(i); QDBusMessage featurecount = serviceInterface->call("GetFeatureList", deviceInfo->device_id, uid, indexStart, indexEnd); if (featurecount.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetFeatureList error:" << featurecount.errorMessage(); } else { res += featurecount.arguments().takeFirst().toInt(); } } return res; } QMap> BioDevices::getAllDevices() { QMap> devices; for (auto deviceInfo : deviceInfos) { if (deviceInfo->biotype == REMOTE_QRCODE_TYPE) // 终端ä¸�使用扫ç � continue; if (!GetDirveIsIdle(deviceInfo->device_id)) continue; devices[deviceInfo->biotype].push_back(*deviceInfo); } return devices; } QMap> BioDevices::getUserDevices(int uid) { QMap> devices; bool isQRCodeEnable = GetQRCodeEnable(); for (auto deviceInfo : deviceInfos) { if (GetUserDevFeatureCount(uid, deviceInfo->device_id) > 0) { if (!isQRCodeEnable && deviceInfo->biotype == REMOTE_QRCODE_TYPE) // 关闭了二维ç �功能 continue; devices[deviceInfo->biotype].push_back(*deviceInfo); } } return devices; } QList BioDevices::getDevices(int type) { QList devices; for (auto deviceInfo : deviceInfos) { if (deviceInfo->biotype == type) devices.push_back(*deviceInfo); } return devices; } void BioDevices::setIsShowHotPlug(bool isShow) { isShowHotPlug = isShow; } bool BioDevices::getUseFirstDevice() { if (m_uniAuthService && m_uniAuthService->isActivatable()) { return m_uniAuthService->getUseFirstDevice(); } else { QSettings settings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); return settings.value("UseFirstDevice").toBool(); } } bool BioDevices::GetHiddenSwitchButton() { if (m_uniAuthService && m_uniAuthService->isActivatable()) { return m_uniAuthService->getHiddenSwitchButton(); } else { QSettings sysSettings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); if (sysSettings.contains("HiddenSwitchButton")) return sysSettings.value("HiddenSwitchButton").toBool(); else return false; } } int BioDevices::getFailedTimes() { if (m_uniAuthService && m_uniAuthService->isActivatable()) { return m_uniAuthService->getMaxFailedTimes(); } else { QSettings sysSettings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); if (sysSettings.contains("MaxFailedTimes")) return sysSettings.value("MaxFailedTimes").toInt(); else return 3; } } bool BioDevices::GetQRCodeEnable() { if (m_uniAuthService && m_uniAuthService->isActivatable()) { return m_uniAuthService->getQRCodeEnable(); } else { bool isEnable = false; QSettings sysSettings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); sysSettings.beginGroup("Functions"); if (sysSettings.allKeys().contains("EnableQRCode")) { isEnable = sysSettings.value("EnableQRCode").toBool(); } sysSettings.endGroup(); return isEnable; } } /** * ukui-greeter 1 * ukui-screensaver 1<<1 * ukui-polkit 1<<2 * sudo 1<<3 * su 1<<4 * login 1<<5 **/ bool BioDevices::GetBioAuthEnable() { if (m_uniAuthService && m_uniAuthService->isActivatable()) { bool isEnable = false; struct passwd *pwd = getpwuid(m_nUId); if (pwd) { isEnable = m_uniAuthService->getBioAuthStatus(pwd->pw_name, ENABLETYPE_BIO); } if (isEnable && !isShowHotPlug) { if (qAppName() == "polkit-ukui-authentication-agent-1") // 获å�–polkit开关是å�¦æ‰“å¼€ isEnable = m_uniAuthService->getBioAuthStatus(pwd->pw_name, ENABLETYPE_POLKIT); if (qAppName() == "bioauth") { // 获å�–父进程å��称为sudo,su,或者login int ppid = getppid(); // 获å�–父进程pid QString filename = "/proc/" + QString::number(ppid) + "/cmdline"; QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Can't open the file!"; } QByteArray text = file.readAll(); file.close(); if (text.contains("sudo")) { isEnable = m_uniAuthService->getBioAuthStatus(pwd->pw_name, ENABLETYPE_SUDO); } else if (text.contains("su")) { isEnable = m_uniAuthService->getBioAuthStatus(pwd->pw_name, ENABLETYPE_SU); } else if (text.contains("login")) { isEnable = m_uniAuthService->getBioAuthStatus(pwd->pw_name, ENABLETYPE_LOGIN); } } } return isEnable; } else { bool isEnable = false; int isEnableApp = 0; QSettings sysSettings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); if (sysSettings.allKeys().contains("EnableAuth")) { isEnable = sysSettings.value("EnableAuth").toBool(); } if (isEnable && sysSettings.allKeys().contains("EnableAuthApp")) { isEnableApp = sysSettings.value("EnableAuthApp").toInt(); if (qAppName() == "polkit-ukui-authentication-agent-1") // 获å�–polkit开关是å�¦æ‰“å¼€ isEnable = isEnableApp & (1 << 2); if (qAppName() == "bioauth") { // 获å�–父进程å��称为sudo,su,或者login int ppid = getppid(); // 获å�–父进程pid QString filename = "/proc/" + QString::number(ppid) + "/cmdline"; QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Can't open the file!"; } QByteArray text = file.readAll(); file.close(); if (text.contains("sudo")) { isEnable = isEnableApp & (1 << 3); } else if (text.contains("su")) { isEnable = isEnableApp & (1 << 4); } else if (text.contains("login")) { isEnable = isEnableApp & (1 << 5); } } } return isEnable; } } DeviceInfoPtr BioDevices::getDefaultDevice(uid_t uid, int bioType) { if (deviceInfos.size() <= 0) return nullptr; FeatureMap mapFeatures = GetUserFeatures(uid); if (m_uniAuthService && m_uniAuthService->isActivatable()) { QString defaultDeviceName = ""; struct passwd *pwdInfo = getpwuid(uid); DeviceInfoPtr ptrDevInfo = nullptr; if (pwdInfo) { QString strDeviceName = m_uniAuthService->getDefaultDevice(pwdInfo->pw_name, bioType); qDebug() << strDeviceName; if (!strDeviceName.isEmpty()) { ptrDevInfo = findDevice(strDeviceName); if (ptrDevInfo) { int isIdle = GetDirveIsIdle(ptrDevInfo->device_id); if (isIdle && mapFeatures.contains(ptrDevInfo->device_shortname)) { defaultDeviceName = strDeviceName; } } } } if (defaultDeviceName.isEmpty()) { return nullptr; } return ptrDevInfo; } else { QString defaultDeviceName; struct passwd *pwd = getpwuid(uid); QString userConfigFile = QString(pwd->pw_dir) + "/.biometric_auth/ukui_biometric.conf"; QSettings userConfig(userConfigFile, QSettings::IniFormat); qDebug() << userConfig.fileName(); defaultDeviceName = userConfig.value(DEFAULT_DEVICE).toString(); qDebug() << defaultDeviceName; if (defaultDeviceName.isEmpty() || !findDevice(defaultDeviceName)) { QSettings sysConfig(GET_STR(CONFIG_FILE), QSettings::IniFormat); defaultDeviceName = sysConfig.value(DEFAULT_DEVICE).toString(); } if (defaultDeviceName.isEmpty() || !findDevice(defaultDeviceName)) { QString userConfigFile = QString(pwd->pw_dir) + "/.biometric_auth/ukui_biometric.conf"; QSettings userConfig(userConfigFile, QSettings::IniFormat); defaultDeviceName = userConfig.value(DEFAULT_DEVICE).toString(); } qDebug() << "default device: " << defaultDeviceName; // 终端ä¸�默认使用第一个设备 if (defaultDeviceName.isEmpty()) { return nullptr; } bool defValid = false; DeviceInfoPtr ptrDevInfo = findDevice(defaultDeviceName); if (ptrDevInfo) { int isIdle = GetDirveIsIdle(ptrDevInfo->device_id); if (isIdle && mapFeatures.contains(ptrDevInfo->device_shortname)) { defValid = true; } } if (!defValid) { ptrDevInfo = nullptr; } return ptrDevInfo; } } void BioDevices::recordAuthDrive(QString appName, int drvid, bool insert) { if (m_uniAuthService && m_uniAuthService->isActivatable()) { m_uniAuthService->recordAuthDrive(appName, drvid, insert); } } bool BioDevices::GetDirveIsIdle(int drvid) { if (m_uniAuthService && m_uniAuthService->isActivatable()) { QStringList appList = m_uniAuthService->getAuthingApp(); for (QString appName : appList) { int id = m_uniAuthService->getAuthingAppDrivd(appName); if (id == drvid) { return false; } } } return true; } DeviceInfoPtr BioDevices::getDefaultDevice(uid_t uid) { if (deviceInfos.size() <= 0) return nullptr; FeatureMap mapFeatures = GetUserFeatures(uid); if (m_uniAuthService && m_uniAuthService->isActivatable()) { QString defaultDeviceName = ""; struct passwd *pwdInfo = getpwuid(uid); DeviceInfoPtr ptrDevInfo = nullptr; if (pwdInfo) { for (auto bioType : m_listPriority) { if (bioType == REMOTE_QRCODE_TYPE) { DeviceList listDevice = findDeviceByType(bioType); for (auto device : listDevice) { int isIdle = GetDirveIsIdle(device->device_id); if (isIdle && mapFeatures.contains(device->device_shortname)) { defaultDeviceName = device->device_shortname; ptrDevInfo = device; break; } } qDebug() << "defaultDevice:" << defaultDeviceName; if (!defaultDeviceName.isEmpty()) { break; } } else { QString strDeviceName = m_uniAuthService->getDefaultDevice(pwdInfo->pw_name, bioType); qDebug() << strDeviceName; if (!strDeviceName.isEmpty()) { ptrDevInfo = findDevice(strDeviceName); if (ptrDevInfo) { int isIdle = GetDirveIsIdle(ptrDevInfo->device_id); if (isIdle && mapFeatures.contains(ptrDevInfo->device_shortname)) { defaultDeviceName = strDeviceName; break; } } } } } } if (defaultDeviceName.isEmpty()) { return nullptr; } return ptrDevInfo; } else { QString defaultDeviceName; struct passwd *pwd = getpwuid(uid); QString userConfigFile = QString(pwd->pw_dir) + "/.biometric_auth/ukui_biometric.conf"; QSettings userConfig(userConfigFile, QSettings::IniFormat); qDebug() << userConfig.fileName(); defaultDeviceName = userConfig.value(DEFAULT_DEVICE).toString(); qDebug() << defaultDeviceName; if (defaultDeviceName.isEmpty() || !findDevice(defaultDeviceName)) { QSettings sysConfig(GET_STR(CONFIG_FILE), QSettings::IniFormat); defaultDeviceName = sysConfig.value(DEFAULT_DEVICE).toString(); } if (defaultDeviceName.isEmpty() || !findDevice(defaultDeviceName)) { QString userConfigFile = QString(pwd->pw_dir) + "/.biometric_auth/ukui_biometric.conf"; QSettings userConfig(userConfigFile, QSettings::IniFormat); defaultDeviceName = userConfig.value(DEFAULT_DEVICE).toString(); } qDebug() << "default device: " << defaultDeviceName; // 终端ä¸�默认使用第一个设备 if (defaultDeviceName.isEmpty()) { return nullptr; } bool defValid = false; DeviceInfoPtr ptrDevInfo = findDevice(defaultDeviceName); if (ptrDevInfo) { if (mapFeatures.contains(ptrDevInfo->device_shortname)) { defValid = true; } } if (!defValid) { ptrDevInfo = nullptr; } return ptrDevInfo; } } QStringList BioDevices::getAllDefDevices() { QStringList listDefDevices; if (m_uniAuthService && m_uniAuthService->isActivatable()) { struct passwd *pwdInfo = getpwuid(m_nUId); if (pwdInfo) { listDefDevices = m_uniAuthService->getAllDefaultDevice(pwdInfo->pw_name); } } else { QString defaultDeviceName; struct passwd *pwd = getpwuid(m_nUId); QString userConfigFile = QString(pwd->pw_dir) + "/.biometric_auth/ukui_biometric.conf"; QSettings userConfig(userConfigFile, QSettings::IniFormat); qDebug() << userConfig.fileName(); defaultDeviceName = userConfig.value(DEFAULT_DEVICE).toString(); qDebug() << defaultDeviceName; if (defaultDeviceName.isEmpty() || !findDevice(defaultDeviceName)) { QSettings sysConfig(GET_STR(CONFIG_FILE), QSettings::IniFormat); defaultDeviceName = sysConfig.value(DEFAULT_DEVICE).toString(); } if (defaultDeviceName.isEmpty() || !findDevice(defaultDeviceName)) { QString userConfigFile = QString(pwd->pw_dir) + "/.biometric_auth/ukui_biometric.conf"; QSettings userConfig(userConfigFile, QSettings::IniFormat); defaultDeviceName = userConfig.value(DEFAULT_DEVICE).toString(); } qDebug() << "default device: " << defaultDeviceName; if (!defaultDeviceName.isEmpty()) { listDefDevices.push_back(defaultDeviceName); } } return listDefDevices; } int BioDevices::GetLastDevice(const QString &userName) { int nLastDevId = -1; QSettings sysSettings(QString(SHARE_BIOMETRIC_CONFIG_PATH).arg(userName), QSettings::IniFormat); sysSettings.beginGroup("Common"); if (sysSettings.allKeys().contains("LastDeviceId")) { nLastDevId = sysSettings.value("LastDeviceId").toInt(); } sysSettings.endGroup(); return nLastDevId; } void BioDevices::SetLastDevice(const QString &userName, int drvid) { if (drvid < 0) { return; } QString desConfPath = QString(SHARE_BIOMETRIC_CONFIG_PATH).arg(userName); QFile fileConf(desConfPath); if (fileConf.exists()) { QSettings sysSettings(desConfPath, QSettings::IniFormat); sysSettings.beginGroup("Common"); sysSettings.setValue("LastDeviceId", drvid); sysSettings.endGroup(); } else { QSettings sysSettings(desConfPath, QSettings::IniFormat); sysSettings.beginGroup("Common"); sysSettings.setValue("LastDeviceId", drvid); sysSettings.endGroup(); sysSettings.sync(); QFile file(desConfPath); file.setPermissions(QFile::WriteUser | QFile::ReadUser | QFile::WriteOther | QFile::ReadOther); } } DeviceInfoPtr BioDevices::findDevice(const int id) { for (auto deviceInfo : deviceInfos) { if (deviceInfo->device_id == id) return deviceInfo; } // qDebug() << deviceName << "doesn't exists"; return nullptr; } DeviceInfoPtr BioDevices::findDevice(const QString &deviceName) { for (auto deviceInfo : deviceInfos) { if (deviceInfo->device_shortname == deviceName) return deviceInfo; } qDebug() << deviceName << "doesn't exists"; return nullptr; } DeviceList BioDevices::findDeviceByType(int nBioType) { DeviceList listDevice; for (auto deviceInfo : deviceInfos) { if (deviceInfo->biotype == nBioType) { listDevice.append(deviceInfo); } } return listDevice; } DeviceInfoPtr BioDevices::getFirstDevice(int uid) { for (DeviceInfoPtr devInfo : deviceInfos) { if (devInfo && GetUserDevFeatureCount(uid, devInfo->device_id) > 0) { return devInfo; } } return nullptr; } QString BioDevices::bioTypeToString_tr(int type) { switch (type) { case BIOTYPE_FINGERPRINT: return tr("FingerPrint"); case BIOTYPE_FINGERVEIN: return tr("FingerVein"); case BIOTYPE_IRIS: return tr("Iris"); case BIOTYPE_FACE: return tr("Face"); case BIOTYPE_VOICEPRINT: return tr("VoicePrint"); case LOGINOPT_TYPE_GENERAL_UKEY: return tr("Ukey"); case REMOTE_QRCODE_TYPE: return tr("QRCode"); } return QString(); } DeviceList BioDevices::GetDevList() { return deviceInfos; } StatusReslut BioDevices::UpdateStatus(int drvid) { StatusReslut status; QDBusMessage result = serviceInterface->call(QStringLiteral("UpdateStatus"), drvid); if (result.type() == QDBusMessage::ErrorMessage) { qWarning() << "UpdateStatus error:" << result.errorMessage(); status.result = -1; return status; } status.result = result.arguments().at(0).toInt(); status.enable = result.arguments().at(1).toInt(); status.devNum = result.arguments().at(2).toInt(); status.devStatus = result.arguments().at(3).toInt(); status.opsStatus = result.arguments().at(4).toInt(); status.notifyMessageId = result.arguments().at(5).toInt(); return status; } ukui-biometric-auth/bioauth/src/biodeviceswidget.ui0000664000175000017500000000273615167732630021512 0ustar fengfeng BioDevicesWidget 0 0 530 99 Form 0 0 0 0 0 36 16777215 36 ukui-biometric-auth/bioauth/src/bioauthwidget.ui0000664000175000017500000001057015167732630021024 0ustar fengfeng BioAuthWidget 0 0 404 282 Form 20 10 Qt::Horizontal 40 20 130 130 128 128 Qt::AlignCenter Qt::Horizontal 40 20 0 20 Qt::AlignCenter true 0 20 Qt::AlignCenter true 8 Qt::Horizontal 40 20 80 28 QPushButton:hover{border:none;color:#3E6CE5;}QPushButton:pressed{border:none;} QPushButton{font-size:14px;} Retry Qt::Horizontal 40 20 ukui-biometric-auth/bioauth/src/giodbus.cpp0000664000175000017500000000544015167732630017766 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "giodbus.h" #include #include #include int get_server_gvariant_stdout (int drvid) { GDBusMessage *method_call_message; GDBusMessage *method_reply_message; GUnixFDList *fd_list; GError **error = NULL; gint fd,dup_fd; const gchar * response; fd = -1; dup_fd = -1; method_call_message = NULL; method_reply_message = NULL; GDBusConnection *con = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL,NULL); method_call_message = g_dbus_message_new_method_call ("org.ukui.Biometric", "/org/ukui/Biometric", "org.ukui.Biometric", "GetFrameFd"); g_dbus_message_set_body (method_call_message, g_variant_new ("(i)", drvid)); method_reply_message = g_dbus_connection_send_message_with_reply_sync (con, method_call_message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, /* out_serial */ NULL, /* cancellable */ error); if (method_reply_message == NULL) goto out; if (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) { g_dbus_message_to_gerror (method_reply_message, error); goto out; } //g_print("%s",g_dbus_message_print(method_reply_message,0)); fd_list = g_dbus_message_get_unix_fd_list(method_reply_message); fd = g_unix_fd_list_get(fd_list,0,error); //g_print("get fd : %d\n", fd); dup_fd = dup(fd); //g_print("dup fd : %d\n", dup_fd); out: g_object_unref (method_call_message); g_object_unref (method_reply_message); return fd; } ukui-biometric-auth/bioauth/CMakeLists.txt0000664000175000017500000000573515167732644017613 0ustar fengfeng# æ ¹æ�®Qt版本使用相应的wrap函数 if(QT_VERSION_MAJOR EQUAL 6) pkg_check_modules(QGS REQUIRED gsettings-qt6) qt6_wrap_ui(BioAuthWidgets_SRC src/bioauthwidget.ui src/biodeviceswidget.ui ) qt6_wrap_cpp(BioAuth_SRC include/bioauth.h include/biodevices.h include/uniauthservice.h ) qt6_wrap_cpp(BioAuthWidgets_SRC include/bioauthwidget.h include/biodeviceswidget.h include/giodbus.h include/loginoptionswidget.h ) else() pkg_check_modules(QGS REQUIRED gsettings-qt) qt5_wrap_ui(BioAuthWidgets_SRC src/bioauthwidget.ui src/biodeviceswidget.ui ) qt5_wrap_cpp(BioAuth_SRC include/bioauth.h include/biodevices.h include/uniauthservice.h ) qt5_wrap_cpp(BioAuthWidgets_SRC include/bioauthwidget.h include/biodeviceswidget.h include/giodbus.h include/loginoptionswidget.h ) endif() set(BioAuth_SRC ${BioAuth_SRC} src/bioauth.cpp src/biodevices.cpp src/biotypes.cpp src/uniauthservice.cpp ) set(BioAuthWidgets_SRC ${BioAuthWidgets_SRC} src/bioauthwidget.cpp src/biodeviceswidget.cpp src/giodbus.cpp src/loginoptionswidget.cpp ) # æ ¹æ�®Qt版本设置包å�«ç›®å½•和链接库 if(QT_VERSION_MAJOR EQUAL 6) include_directories( ${Qt6Core_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6DBus_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ${GIOUNIX2_INCLUDE_DIRS} ${QGS_INCLUDE_DIRS} include ../common ) add_library(BioAuth STATIC ${BioAuth_SRC}) target_link_libraries(BioAuth Qt6::Core Qt6::DBus Qt6::Svg) add_library(BioAuthWidgets STATIC ${BioAuthWidgets_SRC}) target_link_libraries(BioAuthWidgets BioAuth Qt6::Widgets ${OpenCV_LIBS} ${GIOUNIX2_LIBRARIES} ${QGS_LIBRARIES}) else() include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ${GIOUNIX2_INCLUDE_DIRS} ${QGS_INCLUDE_DIRS} include ../common ) add_library(BioAuth STATIC ${BioAuth_SRC}) target_link_libraries(BioAuth Qt5::Core Qt5::DBus Qt5::Svg) add_library(BioAuthWidgets STATIC ${BioAuthWidgets_SRC}) target_link_libraries(BioAuthWidgets BioAuth Qt5::Widgets ${OpenCV_LIBS} ${GIOUNIX2_LIBRARIES} ${QGS_LIBRARIES}) endif() #add_library(BioAuth OBJECT ${BioAuth_SRC}) #add_library(BioAuthWidgets OBJECT ${BioAuth_SRC} ${BioAuthWidgets_SRC}) file(GLOB ts_files i18n_ts/*.ts) # æ ¹æ�®Qt版本使用相应的翻译函数 if(QT_VERSION_MAJOR EQUAL 6) qt6_add_translation(qm_files ${ts_files}) else() qt5_add_translation(qm_files ${ts_files}) endif() add_custom_target(bioauth_i18n DEPENDS ${qm_files} SOURCES ${ts_files}) add_dependencies(BioAuth bioauth_i18n) install(FILES ${qm_files} DESTINATION ${UKUI_BIOMETRIC_DIR}/i18n_qm) ukui-biometric-auth/bioauth/i18n_ts/0000775000175000017500000000000015167732644016326 5ustar fengfengukui-biometric-auth/bioauth/i18n_ts/ru.ts0000664000175000017500000000776515167732644017343 0ustar fengfeng BioAuthWidget Form форма TextLabel TextLabel More Больше Retry Retry Password пароль %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code BioDevices FingerPrint FingerPrint FingerVein FingerVein Iris ИриÑ� Face Лицо VoicePrint Voiceprint Unplugging of %1 device detected %1 device insertion detected biometric QRCode Biometric Manager Ukey BioDevicesWidget Form форма Device types: Типы уÑ�тройÑ�тв: Back назад OK ОК LoginOptionsWidget Login Options Password пароль ukui-biometric-auth/bioauth/i18n_ts/ky.ts0000664000175000017500000001702115167732644017322 0ustar fengfeng BioAuthWidget Form جادىبال More 更多 Retry قايرا قايرا سىنوو Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password 密ç � Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. جەڭىلۉۉ بولۇش ىرەت سانى ارتىقچا ÙƒÛ…Ù¾ بولۇپ كەتتى، جاشىرۇۇن نومۇردۇ كىرگىزىڭ %1 authentication failure,there are still %2 remaining opportunities تولۇمدۇۇلۇق دالىلدۅ جەڭىلۉۉ بولدۇ ØŒ داعى ەكى ىرەت وڭۇتۇڭۇز قالدى Please use wechat to scan the code ئۈندىداردا ىسكاننىردوو BioDevices Unplugging of %1 device detected تەكشەرىپ بايقاعان 1 اسپاپتى تارتىپ چىعارۇۇ %1 device insertion detected 1 جابدۇۇسۇنۇن كىرگىزىلگەندىگىن تەكشەرىپ چىعىش Biometric Manager بىيولوگىيەلىك ۅزگۅچۅلۉگۉ باشقارىش قۇرالى biometric بىيولوگىيەلىك ۅزگۅچۅلۉك FingerPrint بارماق ئزى FingerVein بارماق Û‹Û�نا تومۇرى Iris كۅز ئالمىسى رەڭدار پەردىسى Face جۉز VoicePrint قووپسۇزدۇق شىڧىرلىق اچقىچى Ukey ەسەپتىك كۉبۅلۉك QRCode ەكىلىك قۇپۇيا نومۇر Wechat 微信 BioDevicesWidget Form جادىبال Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options كىرۉۉ تاندالمالارى Password جاشىرۇۇن اچقىچ Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 ukui-biometric-auth/bioauth/i18n_ts/zh_CN.ts0000664000175000017500000001547615167732644017714 0ustar fengfeng BioAuthWidget Form More 更多 Retry é‡�试 Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password 密ç � Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code 请使用微信扫ç � BioDevices Unplugging of %1 device detected 检测到%1设备拔出 %1 device insertion detected 检测到%1设备æ�’å…¥ Biometric Manager 生物特å¾�管ç�†å·¥å…· biometric 生物特å¾� FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸识别 VoicePrint 声纹 Ukey 安全密钥 QRCode 二维ç � Wechat 微信 BioDevicesWidget Form Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options 登录选项 Password 密ç � Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 ukui-biometric-auth/bioauth/i18n_ts/kk.ts0000664000175000017500000001672215167732644017313 0ustar fengfeng BioAuthWidget Form كەستە More 更多 Retry قاتە قاتە سىناۋ Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password 密ç � Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. جەڭىلىپ بولۋ رەت سانى اسقىن كوپ بولىپ كەتتى، قۇپيا نۇمىردى كىرگىزىڭىز %1 authentication failure,there are still %2 remaining opportunities سالاۋاتىن دالەلدەۋ جەڭىلىپ قالدى، جانە ەكٸ رەت ورايڭىز قالدى Please use wechat to scan the code ئۈندىداردا كەسكىندەۋىش BioDevices Unplugging of %1 device detected تەكسەرٸپ بايقاعان 1 اسبابٸن تارتىپ شىعارماق %1 device insertion detected 1 اسبابٸتٸڭ كىرگىزىلگەنىن تەكسەرٸپ شىقپاق Biometric Manager بىيولوگىيەلىك ەرەكشەلىكتى باسقارۋ قۇرالى biometric بىيولوگىيەلىك ەرەكشەلىك FingerPrint بارماقشى ٴٸزٸ FingerVein بارماقشى Û‹Û�نا تومۇرى Iris كوز ئالمىسى تۇستى پەردىسى Face جۇز VoicePrint حاۋىپسىزدىك شىڧىرلىق يٸندەكٸسٸ Ukey ساندىق كۋالىك QRCode ەكٸلٸك رازمەر Wechat 微信 BioDevicesWidget Form كەستە Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options كىرۋ تالدانبالارٸ Password قۇپيا كىلت Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 ukui-biometric-auth/bioauth/i18n_ts/tr.ts0000664000175000017500000001410015167732644017317 0ustar fengfeng BioAuthWidget Form More Daha Fazla Retry Yeniden Dene Password Parola Current Device: Åžuanki Aygıt: %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code BioDevices Unplugging of %1 device detected %1 device insertion detected Biometric Manager biometric FingerPrint Parmak İzi FingerVein Damar İzi Iris Göz Face Yüz VoicePrint Ses İzi Ukey QRCode BioDevicesWidget Form Device types: Aygıt türü: Back Geri OK Tamam FingerPrint Parmak İzi LoginOptionsWidget Login Options Password Parola QObject FingerPrint Parmak İzi FingerVein Damar İzi Iris Göz Face Yüz VoicePrint Ses İzi ukui-biometric-auth/bioauth/i18n_ts/bo.ts0000664000175000017500000001121615167732644017277 0ustar fengfeng BioAuthWidget Form Retry %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code BioDevices Unplugging of %1 device detected %1 device insertion detected Biometric Manager biometric FingerPrint FingerVein Iris Face VoicePrint Ukey QRCode BioDevicesWidget Form LoginOptionsWidget Login Options Password ukui-biometric-auth/bioauth/i18n_ts/ug.ts0000664000175000017500000001672315167732644017322 0ustar fengfeng BioAuthWidget Form جەدۋەل More 更多 Retry قايتا قايتا تىرشىش Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password 密ç � Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. مەغلۇپ بولۇش Ù‚Û�تىم سانى زىيادە ÙƒÛ†Ù¾ بولۇپ كەتتى، مەخپىي نومۇرنى كىرگۈزۈڭ %1 authentication failure,there are still %2 remaining opportunities سالاھىيىتىنى دەلىللەش مەغلۇپ بولدى، ÙŠÛ•Ù†Û• ئىككى Ù‚Û�تىم پۇرسىتىڭىز قالدى Please use wechat to scan the code ئۈندىداردا سىكانىرلاڭ BioDevices Unplugging of %1 device detected تەكشۈرۈپ بايقىغان 1 ئۈسكۈنىنى تارتىپ چىقارماق %1 device insertion detected 1 ئۈسكۈنىنىڭ كىرگۈزۈلگەنلىكىنى تەكشۈرۈپ چىقماق Biometric Manager بىئولەگىيەلىك ئالاھىدىلىكنى باشقۇرۇش قورالى biometric بىئولوگىيەلىك ئالاھىدىلىك FingerPrint بارماق ئىزى FingerVein بارماقVein Iris ئÛ�رسى Face يۈز VoicePrint بىخەتەرلىك شىڧىرلىق ئاچقۇچى Ukey رەقەملىك گۇۋاھنامە QRCode ئىككىلىك كود Wechat 微信 BioDevicesWidget Form جەدۋەل Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options كىرىش تاللانمىلىرى Password مەخپىي ئاچقۇچ Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 ukui-biometric-auth/bioauth/i18n_ts/pt.ts0000664000175000017500000000773615167732644017336 0ustar fengfeng BioAuthWidget Form Formato TextLabel TextLabel More Mais Retry Tente novamente Password Senha %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code BioDevices FingerPrint Impressão digital FingerVein FingerVein Iris Ã�ris Face Cara VoicePrint VoicePrint Unplugging of %1 device detected %1 device insertion detected biometric QRCode Biometric Manager Ukey BioDevicesWidget Form Formato Device types: Tipos de dispositivos: Back Costas OK Está bem LoginOptionsWidget Login Options Password Senha ukui-biometric-auth/bioauth/i18n_ts/bo_CN.ts0000664000175000017500000001263515167732644017665 0ustar fengfeng BioAuthWidget Form རེའུ་མིག More དེ་ལས་མང་བà¼� Retry ཡང་བསà¾�ྱར་ཚོད་ལེནà¼� Current Device: 当å‰�设备: Password གསང་ཨང་à¼� TextLabel ཡིག་རà¾�ྱང་ཕྲེང་བà¼� %1 too many unsuccessful attempts,please enter password. %1ལ་ལེགས་འགྲུབ་མ་བྱུང་བའི་ཚོད་ལྟ་མང་དྲགས་པས་གསང་གྲངས་ནང་འཇུག་གནང་རོགསà¼� %1 authentication failure,there are still %2 remaining opportunities %1 བདེན་དཔང་ར་སྤྲོད་བྱེད་མ་à½�ུབ་ནà¼� ད་དུང་%2ལྷག་པའི་གོ་སà¾�བས་ཡོདà¼� Please use wechat to scan the code སà¾�ད་འཕྲིན་གྱི་ཨང་བཤེར་སྤྱོད་ཅིག BioDevices Face མིའི་གདོང་ངོས་འཛིནà¼� Iris འཇའ་སà¾�ྱིà¼� biometric སà¾�ྱེ་དངོས་སྒྲིག་ཆསà¼� VoicePrint སྒྲ་རིམà¼� Unplugging of %1 device detected ཞིབ་དཔྱད་ཚད་ལེན་བྱས་པའི་%1སྒྲིག་ཆས་ཀྱི་à½�་པར་རྒྱག་པà¼� %1 device insertion detected %1སྒྲིག་ཆས་ནང་དུ་བཅུག་ནས་ཞིབ་དཔྱད་ཚད་ལེན་བྱས་པ་རེདà¼� FingerPrint མཛུབ་རིསà¼� FingerVein མཛུབ་སྡོད་རྩà¼� Biometric Manager སà¾�ྱེ་དངོས་à½�ྱད་རྟགས་དོ་དམ་ཡོ་བྱདà¼� QRCode རྩ་གཉིས་ཨང་གྲངསà¼� Ukey བདེ་འཇགས་གསང་ལྡེ་ BioDevicesWidget OK གà½�ན་འà½�ེལ་བྱེད་པà¼� Back ཕྱིར་འà½�ེནà¼� Form རེའུ་མིག Device types: 设备类型: LoginOptionsWidget Login Options à½�ོ་འགོད་ཀྱི་བསལ་འདེམས་ཀྱི་དབང་ཆà¼� Password ཕར་འགྲོ་ཚུར་འོང་བྱེད་མà½�ནà¼� ukui-biometric-auth/bioauth/i18n_ts/vi.ts0000664000175000017500000001604315167732644017320 0ustar fengfeng BioAuthWidget Form More 更多 Retry Thá»­ lại Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password 密ç � Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 quá nhiá»�u lần thá»­ không thành công, vui lòng nhập mật khẩu. %1 authentication failure,there are still %2 remaining opportunities %1 xác thá»±c thất bại, còn %2 lần thá»­ Please use wechat to scan the code Vui lòng sá»­ dụng WeChat để quét mã BioDevices Unplugging of %1 device detected Phát hiện rút phích cắm%1 thiết bị %1 device insertion detected Phát hiện thiết bị %1 đã cắm vào Biometric Manager Trình quản lý sinh trắc há»�c biometric Ä�ặc Ä‘iểm sinh trắc há»�c FingerPrint Vân tay FingerVein TÄ©nh mạch ngón tay Iris Mống mắt Face Mặt VoicePrint Sinh trắc giá»�ng nói Ukey Ukey QRCode Mã QR Wechat 微信 BioDevicesWidget Form Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options Tùy chá»�n đăng nhập Password Mật khẩu Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 ukui-biometric-auth/bioauth/i18n_ts/mn.ts0000664000175000017500000002030515167732644017310 0ustar fengfeng BioAuthWidget Form ᠬᠡᠯᠪᠡᠷᠢ More 更多 Retry ᠳᠠᠬᠢᠨ ᠳᠤᠷᠰᠢᠬᠤ Too many unsuccessful attempts,please enter password. 验è¯�失败达最大次数,请使用密ç �è§£é”� Bioauth authentication failed, you still have %1 verification opportunities 生物认è¯�失败,您还有%1次å°�试机会 Password ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ Current Device: 当å‰�设备: %1 too many unsuccessful attempts,please enter password. %1 ᠢᠯᠠᠭᠳᠠᠭᠰᠠᠨ ᠲᠤᠷᠰᠢᠬᠤ ᠤᠳᠠᠭ᠎ᠠ ᠲᠣᠭ᠎ᠠ ᠬᠡᠳᠦ ᠣᠯᠠᠨ᠂ ᠨᠢᠭᠤᠴᠠ ᠺᠣᠳ᠋ ᠣᠷᠣᠭᠤᠯᠤᠭᠠᠷᠠᠢ᠃ %1 authentication failure,there are still %2 remaining opportunities %1 ᠪᠡᠶ᠎ᠡ᠎ᠶ᠋ᠢᠨ ᠬᠢᠷᠢ᠎ᠶ᠋ᠢᠨ ᠰᠢᠯᠭᠠᠨ ᠪᠠᠲᠤᠯᠠᠯᠲᠠ ᠢᠯᠠᠭᠳᠠᠪᠠ á ‚ ᠮᠥᠨ %2 ᠦᠯᠡᠳᠡᠬᠦ ᠲᠣᠬᠢᠶᠠᠯ ᠪᠣᠢ Please use wechat to scan the code ᠸᠢᠴᠠᠲ᠎ᠢ᠋ᠶ᠋ᠠᠷ ᠦᠰᠦᠭ ᠰᠢᠷᠪᠢᠬᠦ ᠪᠣᠯᠪᠠᠤ BioDevices Unplugging of %1 device detected %1 ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ ᠰᠤᠭᠤᠯᠤᠭᠳᠠᠭᠰᠠᠨ ᠢ᠋ ᠪᠠᠢᠴᠠᠭᠠᠵᠤ ᠤᠯᠪᠠ %1 device insertion detected %1 ᠳᠦᠬᠦᠬᠡᠷᠦᠮᠵᠢ ᠵᠢ ᠬᠠᠪᠴᠢᠭᠤᠯᠤᠭᠰᠠᠨ ᠢ᠋ ᠬᠢᠨᠠᠨ ᠪᠠᠢᠴᠠᠭᠠᠵᠤ ᠤᠯᠪᠠ Biometric Manager ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ᠎ᠤ᠋ᠨ ᠣᠨᠴᠠᠯᠢᠭ ᠬᠠᠮᠢᠶᠠᠷᠤᠯᠲᠠ᠎ᠶ᠋ᠢᠨ ᠪᠠᠭᠠᠵᠢ biometric ᠪᠢᠤᠯᠤᠬᠢ ᠵᠢᠨ ᠣᠨᠴᠠᠯᠢᠭ FingerPrint ᠬᠤᠷᠤᠭᠤᠨ ᠤᠷᠤᠮ FingerVein ᠬᠤᠷᠤᠭᠤᠨ ᠨᠠᠮᠵᠢᠭᠤᠨ ᠰᠤᠳᠠᠰᠤ Iris ᠰᠣᠯᠣᠩᠭ᠎ᠠ ᠪᠦᠷᠬᠦᠭᠦᠯ Face ᠴᠢᠷᠠᠢ ᠪᠡᠷ ᠲᠠᠨᠢᠬᠤ VoicePrint ᠳᠠᠭᠤᠨ ᠣᠷᠣᠮ Ukey ᠠᠶᠤᠯᠭᠦᠢ ᠨᠢᠭᠤᠴᠠ ᠲᠦᠯᠬᠢᠭᠦᠷ ukey ᠠᠶᠤᠯᠭᠦᠢ ᠨᠢᠭᠤᠴᠠ ᠲᠦᠯᠬᠢᠭᠦᠷ QRCode ᠬᠤᠶᠠᠷ ᠬᠡᠮᠵᠢᠯᠳᠡᠳᠦ ᠺᠤᠳ᠋ Wechat 微信 BioDevicesWidget Form ᠬᠡᠯᠪᠡᠷᠢ Device types: 设备类型: Back 返回 OK 确定 FingerPrint 指纹 LoginOptionsWidget Login Options ᠨᠡᠪᠳᠡᠷᠡᠬᠦ ᠰᠤᠩᠭᠤᠭᠳᠠᠬᠤᠨ Password ᠨᠢᠭᠤᠴᠠ ᠺᠤᠳ᠋ Wechat 微信 Biometric 生物识别 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 ukui-biometric-auth/bioauth/i18n_ts/fr.ts0000664000175000017500000000775415167732644017322 0ustar fengfeng BioAuthWidget Form Forme TextLabel TextLabel More Plus Retry Recommencez Password Mot de passe %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code BioDevices FingerPrint Empreinte digitale FingerVein FingerVein Iris Iris Face Visage VoicePrint VoicePrint Unplugging of %1 device detected %1 device insertion detected biometric QRCode Biometric Manager Ukey BioDevicesWidget Form Forme Device types: Types d'appareils: Back Arrière OK D'accord LoginOptionsWidget Login Options Password Mot de passe ukui-biometric-auth/bioauth/i18n_ts/es.ts0000664000175000017500000000775715167732644017325 0ustar fengfeng BioAuthWidget Form Formar TextLabel TextLabel More Más Retry Procesar de nuevo Password Contraseña %1 too many unsuccessful attempts,please enter password. %1 authentication failure,there are still %2 remaining opportunities Please use wechat to scan the code BioDevices FingerPrint Huella dactilar FingerVein FingerVein Iris Iris Face Cara VoicePrint Impresión de voz Unplugging of %1 device detected %1 device insertion detected biometric QRCode Biometric Manager Ukey BioDevicesWidget Form Formar Device types: Tipos de dispositivos: Back Espalda OK DE ACUERDO LoginOptionsWidget Login Options Password Contraseña ukui-biometric-auth/bioauth/i18n_ts/zh_HK.ts0000664000175000017500000005241615167732644017711 0ustar fengfeng BioAuthWidget Retry é‡�试 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 Please use wechat to scan the code 请使用微信扫ç � BioDevices FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Wechat 微信 QRCode 二维ç � FullScreenBackground Authentication 授權 LoginOptionsWidget Login Options 登录选项 Wechat 微信 MainWindow Authentication 授權 Fingerprint authentication failed, you still have %1 verification opportunities 指纹验è¯�失败,您还有%1次å°�试机会 Form More 更多 Restart é‡�新开始 Password 密ç � Biometric 使用生物識別 use password 使用密碼驗證 DeviceType: 设备类型: Back 返回 Details 详细 Action Id: 动作: Description: æ��述: Polkit.subject-pid: Polkit.subject-pid: Retry é‡�试 Device types: 设备类型: Vendor: å�‘行商: Action: 动作: Polkit.caller-pid: Polkit.caller-pid: Cancel å�–消 Authenticate 授權 Use password 使用密碼驗證 Auth 授æ�ƒ Too many unsuccessful attempts,please enter password. 指纹验è¯�失败达最大次数,请使用密ç �è§£é”� %1 authentication failure,there are still %2 remaining opportunities %1认è¯�失败,还剩%2次å°�试机会 %1 too many unsuccessful attempts,please enter password. %1验è¯�失败达最大次数,请使用密ç �登录 in authentication, please wait... 认è¯�中,请ç¨�ç­‰... Please try again in %1 minutes. è«‹%1分é�˜å�Žå†�試 Please try again in %1 seconds. è«‹%1秒後å†�試 Account locked permanently. 帳號已被永久鎖定 Password cannot be empty 密碼ä¸�能為空 Failed to verify %1, please enter password. 验è¯�%1失败,请输入密ç �. Unable to verify %1, please enter password. 无法验è¯�%1,请输入密ç �. Failed to verify %1, you still have %2 verification opportunities é©—è­‰%1失敗,您還有%2次嘗試機會 An application is attempting to perform an action that requires privileges. Authentication is required to perform this action. 一个程åº�正试图执行一个需è¦�特æ�ƒçš„动作。è¦�求授æ�ƒä»¥æ‰§è¡Œè¯¥åŠ¨ä½œã€‚ Password: 密碼: Please enter your password or enroll your fingerprint 請輸入密碼或者錄入指紋 wechat 微信 Use the bound %1 scanning code to authorization %1掃碼以授權 Abnormal network 網路異常 This operation requires the administrator's authorization. Please enter your password to allow this operation. 本次æ“�作需è¦�通é�Žç®¡ç�†å“¡çš„æŽˆæ¬Šæ‰�能繼續執行,請輸入密碼以å…�許本次æ“�作。 _Password: 密碼: _Password: 密碼: Authentication failed, please try again. èª�證失敗,請é‡�試。 days left 天å�Žè§£éŽ– Biometric/code scan authentication failed too many times, please enter the password. 生物/扫ç �验è¯�失败达最大次数,请使用密ç �è§£é”�. Bioauth/code scan authentication failed, you still have %1 verification opportunities 生物/扫ç �验è¯�失败,您还有%1次å°�试机会 Failed to verify %1, please enter password to unlock é©—è­‰%1失敗,請輸入密碼解鎖 Unable to verify %1, please enter password to unlock 無法驗證%1,請輸入密碼解鎖 NET Exception 网络异常 A program is attempting to perform an action that requires privileges.It requires authorization to perform the action. 一個程å¼�正試圖執行一個需è¦�特權的動作,è¦�求授權以執行該動作。 Input Password 輸入密碼 Insert the ukey into the USB port 請將安全金鑰æ�’å…¥USB埠 Enter the ukey password 輸入安全金鑰密碼 Close 關閉 Enter the two-factor authentication (2FA) OTP token for the administrator "%1" Enter the two-factor authentication (2FA) OTP dynamic token for the user "%1" Enter the two-factor authentication (2FA) security key for the administrator "%1" Enter the two-factor authentication (2FA) security key for the user "%1" Facial recognition to authorization 識別人臉以授權 Fingerprint recognition to authorization 識別指紋以授權 Voiceprint recognition to authorization 識別è�²ç´‹ä»¥æŽˆæ¬Š Finger veins recognition to authorization 識別指é�œè„ˆä»¥æŽˆæ¬Š Iris recognition to authorization 識別虹膜以授權 Use the bound wechat scanning code to authorization 微信掃碼以授權 Acquisition failure ç�²å�–失敗 hours left å°�時後解鎖 minutes left 分é�˜å¾Œè§£éŽ– seconds left 秒後解鎖 Input your password to authentication 輸入密碼以èª�è­‰ Verify face recognition or enter password to unlock 驗證人臉識別或輸入密碼解鎖 Press fingerprint or enter password to unlock 按壓指紋或輸入密碼解鎖 Verify voiceprint or enter password to unlock é©—è­‰è�²ç´‹æˆ–輸入密碼解鎖 Verify finger vein or enter password to unlock 驗證指é�œè„ˆæˆ–輸入密碼解鎖 Verify iris or enter password to unlock 驗證虹膜或輸入密碼解鎖 Use the bound wechat scanning code or enter the password to unlock 使用ç¶�定的微信掃碼或輸入密碼解鎖 Use the bound wechat scanning code or enter the password to log in 使用绑定的微信扫ç �或输入密ç �登录 Account locked, 帳戶已鎖定, Authentication failed, please try again 认è¯�失败,请é‡�试 PolkitListener Another client is already authenticating, please try again later. 有å�¦å¤–一個用戶端正在èª�證,請ç¨�後é‡�試。 Authentication failure, please try again. èª�證失敗,請é‡�試。 Password input error! 密碼輸入錯誤ï¼� Account locked %1 minutes due to %2 fail attempts 账户é”�定%1分钟由于%2次错误å°�试 Authentication failure,there are still %1 remaining opportunities 认è¯�失败,还剩余%1次å°�试机会 QObject FingerPrint 指纹 FingerVein 指é�™è„‰ Iris 虹膜 Face 人脸 VoicePrint 声纹 Cancel å�–消 ukui-biometric-auth/bioauth/include/0000775000175000017500000000000015167732644016464 5ustar fengfengukui-biometric-auth/bioauth/include/loginoptionswidget.h0000664000175000017500000001463715167732644022600 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef LOGINOPTIONSWIDGET_H #define LOGINOPTIONSWIDGET_H #include #include #include "bioauth.h" #include "biodevices.h" #include class QLabel; class QButtonGroup; class QHBoxLayout; class QVBoxLayout; class QToolButton; class QTimer; typedef enum { BioT_FingerPrint, /** 指纹 **/ BioT_FingerVein, /** 指é�™è„‰ **/ BioT_Iris, /** 虹膜 **/ BioT_Face, /** 人脸 **/ BioT_VoicePrint, /** 声纹 **/ UniT_KCM, /** 安全管控 **/ UniT_General_Ukey, /** 普通的Ukey **/ UniT_Advanced_Ukey, /** 高阶的Ukey **/ UniT_Remote, /** 远程账户 **/ }Bio_Type; class LoginOptionsWidget : public QWidget { Q_OBJECT public: explicit LoginOptionsWidget(QWidget *parent = nullptr); virtual ~LoginOptionsWidget(); bool getCurLoginOpt(int& nLoginOptType, int& nDrvId); unsigned getLoginOptCount(); DeviceInfoPtr getFirstDevInfo(); int convertDeviceType(int nDevType); void updateUIStatus(bool update, int nPreOptType = -1); void updateUkeyUIStatus(int type); void setUser(int uid); void setCurrentDevice(int drvid); void setCurrentDevice(const QString &deviceName); void setCurrentDevice(const DeviceInfoPtr &pDeviceInfo); DeviceInfoPtr findDeviceById(int drvid); DeviceInfoPtr findDeviceByName(const QString &name); void setDeviceDisable(int nDevId, bool bDisable = true); bool isDeviceDisable(int nDevId); void lockStatusChanged(bool locked); /** * @brief 获å�–默认设备 * @return */ QString GetDefaultDevice(uid_t uid); QString GetDefaultDevice(uid_t uid,int bioType); /** * @brief 进行生物识别认è¯� * @param deviceInfo 使用的设备 * @param uid 待认è¯�的用户id */ void startAuth(DeviceInfoPtr device, int uid); /** * @brief 终止生物识别认è¯� */ void stopAuth(); /** * @brief 是å�¦æ­£åœ¨è®¤è¯� * @return */ bool isAuthenticating() { return m_isInAuth; } QPixmap loadSvg(QString path, QString color, int size); void SetExtraInfo(QString extra_info,QString info_type); bool getHasUkeyOptions(); void setSelectedPassword(); // 设置所有生物识别的ç¦�用状æ€� void setAllDeviceDisable(bool bDisable = true); void startBioWaiting(unsigned uCurLoginOptType); void stopBioWaiting(bool isDisable = false); public slots: void readDevicesInfo(); void onIdentifyComplete(int uid, bool ret, int retErrNo); void onAuthFinished(); void onStatusChanged(int drvid, const QString &message); void onFrameWritten(int drvid); void onUSBDeviceCountChange(int newNum); void onOptionSelected(int nIndex); void setQRCodeMsg(QString strMsg); void setQRCode(QImage& imgQRCode); void setFaceImg(QImage& imgFace, int nStatus = 0); signals: void notifyOptionsChange(unsigned uOptionsCount); void optionSelected(unsigned uLoginOptType, const DeviceInfoPtr &deviceInfo); void updateImage(QImage img); // nStatus -1 dbus错误,0 无错误,1 超时,2 其他错误 void authComplete(uid_t uid, bool bResult, int nStatus); void updateAuthMsg(QString strMsg); void updateWndSize(unsigned uLoginOptType, unsigned uLoginOptSize); private: void initUI(); void initConnections(); void initStyleTheme(); void addOptionButton(unsigned uLoginOptType, int nDrvId, QString strDrvName); void clearOptionButtons(); void updateOptionButtons(); void startAuth_(); QPixmap PixmapToRound(const QPixmap &src, int radius); QPixmap scaledPixmap(int width, int height, QString url); QPixmap drawSymbolicColoredPixmap(QPixmap &source, QString cgColor); void updatePixmap(); QPixmap scaledSmoothPixmap(const QPixmap &src, int nWidth, int nHeight); private: BioAuth *m_biomericProxy = nullptr; BioDevices *m_bioDevices = nullptr; DeviceMap m_mapDevices; unsigned m_curLoginOptType = LOGINOPT_TYPE_PASSWORD; int m_uid = -1; QString m_strUserName; DeviceInfoPtr m_curDevInfo = nullptr; // 当å‰�选择的设备信æ�¯ int m_dupFD = -1; // é€�传的图åƒ�文件å�¥æŸ„ bool m_isInAuth; // 是å�¦æ­£åœ¨éªŒè¯� bool m_isStopped; // 是å�¦è¢«å¼ºåˆ¶ç»ˆæ­¢ QTimer *m_retrytimer = nullptr; // é‡�试定时器 // UI QVBoxLayout *m_layoutMain = nullptr; QHBoxLayout *m_layoutOptBtns = nullptr; QHBoxLayout *m_layoutImage = nullptr; QLabel *m_labelOptTitle = nullptr; QButtonGroup *m_btnGroup = nullptr; QList m_listDriveId; QMap m_mapOptBtns; QWidget *m_widgetImage = nullptr; QLabel *m_labelFace = nullptr; QLabel *m_labelFaceLoad = nullptr; QLabel *m_labelQRCode = nullptr; // 二维ç �图标 QLabel *m_labelQRCodeMsg = nullptr; // 二维ç �状æ€�消æ�¯æ��示 QLabel *m_labelQRCodeTip = nullptr; QMap> m_mapDisableDev; bool is_Lock = false; QPixmap m_waitingPixmap; QTimer *w_timer; bool isShowUkey = false; // 指纹ã€�指é�™è„‰ã€�虹膜ã€�声纹识别动图 QLabel *m_labelBioWaiting = nullptr; // 指纹ã€�指é�™è„‰ã€�虹膜ã€�声纹识别动图æ��示 QTimer *m_timerBioWaiting = nullptr; // 指纹ã€�指é�™è„‰ã€�虹膜ã€�声纹识别动图切æ�¢å®šæ—¶å™¨ int m_nBioWaitingFrame = 0; // 当å‰�显示的动图帧 int m_nCurBioWaitingType = -1; // 当å‰�显示的动图类型 QGSettings *m_styleSettings = nullptr; QString m_strThemeName = ""; }; #endif // LOGINOPTIONSWIDGET_H ukui-biometric-auth/bioauth/include/bioauth.h0000664000175000017500000000534515167732630020272 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIOAUTH_H #define BIOAUTH_H #include #include "biotypes.h" class QDBusInterface; /*! * \brief The BioAuth class * 负责真正的生物识别æ“�作,通过startAuth开始认è¯�, * 认è¯�完æˆ�å�Žä¼šå�‘出æ�ºå¸¦ç»“果的authCompleteä¿¡å�· */ class BioAuth : public QObject { Q_OBJECT public: explicit BioAuth(qint32 uid, const DeviceInfoPtr deviceInfo, QObject *parent = nullptr); explicit BioAuth(QObject *parent = nullptr); ~BioAuth(); void setDevice(const DeviceInfoPtr deviceInfo); void setUid(qint32 uid); DeviceInfoPtr getDevice(); void startAuth(); void startUkeyAuth(); void startAuth(qint32 uid, const DeviceInfoPtr deviceInfo); void stopAuth(); bool isAuthenticating(); void init(); /** * @brief 设置一些认è¯�时所需的é¢�外的信æ�¯ * @param info_type é¢�外的信æ�¯ç±»åž‹ï¼Œukey pincode认è¯�æ—¶ä¼  "pincode" * @param extra_info é¢�外的信æ�¯å†…容,ukey pincode认è¯�æ—¶ä¼ PINç �内容 * @return 结果: (设置é¢�外信æ�¯çš„结果) */ int SetExtraInfo(QString info_type, QString extra_info); /** * @brief 获å�–当å‰�用户已连接设备对应特å¾�æ•°ç›® * @param uid 用户id * @param indexStart 用于认è¯�的特å¾�索引范围 * @param indexEnd * @return 返回是å�¦å­˜åœ¨ukey特å¾� */ bool GetHasUkeyFeature(int uid, int indexStart = 0, int indexEnd = -1); signals: void authComplete(int uid, bool result, int retErrNo); void authFinished(); void notify(const QString &message); void notifyDetail(int deviceId, const QString &message); void frameWritten(int deviceId); private slots: void onIdentityComplete(QDBusPendingCallWatcher *watcher); void onStatusChanged(int deviceId, int statusType); void onFrameWritten(int drvid); private: QDBusInterface *serviceInterface; qint32 uid; DeviceInfoPtr deviceInfo = nullptr; bool isInAuthentication; }; #endif // BIOAUTH_H ukui-biometric-auth/bioauth/include/biometric.h0000664000175000017500000000152315167732630020606 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIOMETRIC_H #define BIOMETRIC_H #include "bioauth.h" #include "biodevices.h" #include "bioauthwidget.h" #include "biodeviceswidget.h" #endif // BIOMETRIC_H ukui-biometric-auth/bioauth/include/bioauthwidget.h0000664000175000017500000000344515167732630021475 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIOAUTHWIDGET_H #define BIOAUTHWIDGET_H #include #include "bioauth.h" namespace Ui { class BioAuthWidget; } class BioAuthWidget : public QWidget { Q_OBJECT public: explicit BioAuthWidget(QWidget *parent = 0); ~BioAuthWidget(); void hidePasswdButton(); bool isAuthenticating(); public slots: void startAuth(uid_t uid, const DeviceInfoPtr device); void setMoreDevices(bool hasMore); void stopAuth(); void emitSwithToPassword(); signals: void switchToPassword(); void selectDevice(); void authComplete(uid_t uid, bool ret); private slots: void on_btnPasswdAuth_clicked(); void on_btnMore_clicked(); void on_btnRetry_clicked(); void onBioAuthNotify(const QString ¬ifyMsg); void onBioAuthComplete(uid_t uid, bool ret, int retErrNo); void onFrameWritten(int deviceId); private: void setMovie(); void setImage(); private: Ui::BioAuthWidget *ui; BioAuth *bioAuth; uid_t uid; DeviceInfoPtr device; int fd = -1; int dup_fd = -1; int nMaxFailCnt = 5; public: static int failedCount; }; #endif // BIOAUTHWIDGET_H ukui-biometric-auth/bioauth/include/uniauthservice.h0000664000175000017500000000531015167732644021672 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef UNIAUTH_SERVICE_H #define UNIAUTH_SERVICE_H // QtDBus 包å�«è·¯å¾„兼容 #if QT_VERSION_MAJOR == 6 #include #else #include #endif #include enum authEnableType { ENABLETYPE_BIO, // 全局总使能 ENABLETYPE_SAVER, // é”�å±� ENABLETYPE_GREETER, // 登录 ENABLETYPE_POLKIT, // 授æ�ƒ ENABLETYPE_SU, // æš‚ä¿�ç•™ ENABLETYPE_SUDO, // æš‚ä¿�ç•™ ENABLETYPE_LOGIN, // æš‚ä¿�ç•™ }; class UniAuthService : public QDBusAbstractInterface { Q_OBJECT public: explicit UniAuthService(QObject *parent = nullptr); public Q_SLOTS: // 设置默认设备 void setDefaultDevice(int bioDevType, QString deviceName); // 获å�–默认设备 QString getDefaultDevice(QString userName, int bioDevType); // 获å�–所有默认设备 QStringList getAllDefaultDevice(QString userName); //生物特å¾�开关接å�£ bool getBioAuthStatus(QString userName, int bioAuthType); void setBioAuthStatus(int bioAuthType, bool status); // 获å�–最大失败次数 int getMaxFailedTimes(); // 获å�–是å�¦ä½¿èƒ½å¾®ä¿¡æ‰«ç �登录 bool getQRCodeEnable(); // 获å�–是å�¦å�Œè®¤è¯� bool getDoubleAuth(); // 获å�–用户绑定 bool getUserBind(); // 获å�–是å�¦åœ¨æŽ§åˆ¶é�¢æ�¿æ˜¾ç¤º bool getIsShownInControlCenter(); // 获å�–是å�¦ä½¿ç”¨ç¬¬ä¸€ä¸ªè®¾å¤‡ bool getUseFirstDevice(); // 获å�–是å�¦éš�è—�切æ�¢æŒ‰é’® bool getHiddenSwitchButton(); // 获å�–正在认è¯�的应用 QStringList getAuthingApp(); // 获å�–应用认è¯�的驱动 int getAuthingAppDrivd(QString appName); public: bool isActivatable(); void recordAuthDrive(QString appName,int drvid,bool insert); Q_SIGNALS: //默认设备改å�˜ void defaultDeviceChanged(QString userName, int bioDevType, QString deviceName); //开关状æ€�改å�˜ void bioAuthStatusChanged(QString userName, int type, bool status); private: bool m_isActivatable; }; #endif // UNIAUTH_SERVICE_H ukui-biometric-auth/bioauth/include/giodbus.h0000664000175000017500000000140515167732630020264 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef GIODBUS_H #define GIODBUS_H int get_server_gvariant_stdout(int drvid); #endif ukui-biometric-auth/bioauth/include/biodeviceswidget.h0000664000175000017500000000320515167732630022150 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIODEVICESWIDGET_H #define BIODEVICESWIDGET_H #include #include "biodevices.h" #define UKUI_BIOMETRIC_SYS_CONFIG_PATH "/etc/biometric-auth/ukui-biometric.conf" namespace Ui { class BioDevicesWidget; } class BioDevicesWidget : public QWidget { Q_OBJECT public: explicit BioDevicesWidget(QWidget *parent = 0); void setCurrentDevice(DeviceInfoPtr device); ~BioDevicesWidget(); void init(uid_t uid); enum FLAG{FIRST,AGAIN}; signals: void back(); void deviceChanged(const DeviceInfo &device); void deviceCountChanged(int count); private slots: // void on_btnBack_clicked(); // void on_btnOK_clicked(); void on_lwDevices_currentIndexChanged(); void on_cmbDeviceTypes_currentIndexChanged(int index); void onDeviceCountChanged(); private: Ui::BioDevicesWidget *ui; BioDevices bioDevices; QMap> devicesMap; uid_t uid; }; int GetFailedTimes(); #endif // BIODEVICESWIDGET_H ukui-biometric-auth/bioauth/include/biodevices.h0000664000175000017500000000651515167732644020760 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIODEVICES_H #define BIODEVICES_H #include #include #include #include "biotypes.h" #include "uniauthservice.h" class QDBusInterface; #define SHARE_BIOMETRIC_CONFIG_PATH \ "/var/lib/lightdm-data/%1/ukui-biometric.conf" // greeterã€�screensaverã€�polkit share conf /*! * \brief The BioDevices class * this class saves the list of all device information * and list of available devices' info list for each uid */ class BioDevices : public QObject { Q_OBJECT public: explicit BioDevices(bool isIgnoreQrCode = false, QObject *parent = nullptr); int count(); void setUId(int nUId); QMap> getAllDevices(); QMap> getUserDevices(int uid); QList getDevices(int type); DeviceInfoPtr getDefaultDevice(uid_t uid); DeviceInfoPtr getDefaultDevice(uid_t uid, int bioType); int GetLastDevice(const QString &userName); void SetLastDevice(const QString &userName, int drvid); DeviceInfoPtr findDevice(const QString &deviceName); DeviceInfoPtr findDevice(const int id); DeviceList findDeviceByType(int nBioType); DeviceInfoPtr getFirstDevice(int uid); DeviceList GetDevList(); int getFeatureCount(int uid, int indexStart = 0, int indexEnd = -1); static QString bioTypeToString_tr(int type); void setIsShowHotPlug(bool isShow); int GetUserDevFeatureCount(int uid, int drvid); int GetUserDevCount(int uid); FeatureMap GetUserFeatures(int uid); bool getUseFirstDevice(); int getFailedTimes(); bool GetHiddenSwitchButton(); bool GetQRCodeEnable(); bool GetBioAuthEnable(); QStringList getAllDefDevices(); /** * @brief UpdateStatus 获å�–更新的设备状æ€� * @param drvid 驱动id * @return 结果: */ StatusReslut UpdateStatus(int drvid); bool GetBioAuthEnable(uid_t uid); bool GetDirveIsIdle(int drvid); void recordAuthDrive(QString appName, int drvid, bool insert); private: void connectToService(); void getDevicesList(); signals: void deviceCountChanged(int newNum); private slots: void onUSBDeviceHotPlug(int deviceId, int action, int devNumNow); private: QDBusInterface *serviceInterface; DeviceList deviceInfos; // the list of al device info bool isShowHotPlug; bool useFirstDevice; bool m_isIgnoreQrCode = false; UniAuthService *m_uniAuthService = nullptr; int m_nUId = -1; QList m_listPriority; }; #endif // BIODEVICES_H ukui-biometric-auth/bioauth/include/biotypes.h0000664000175000017500000001754115167732644020503 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef BIOCUSTOMTYPE_H #define BIOCUSTOMTYPE_H #include // QtDBus 包å�«è·¯å¾„兼容 #if QT_VERSION_MAJOR == 6 #include #else #include #endif #define BIO_DBUS_SERVICE "org.ukui.Biometric" #define BIO_DBUS_PATH "/org/ukui/Biometric" #define BIO_DBUS_INTERFACE "org.ukui.Biometric" #define DEFAULT_DEVICE "DefaultDevice" #ifdef LOG #undef LOG #endif #define LOG() qDebug() << "[BIOMETRIC]" enum LOGINOPT_TYPE { LOGINOPT_TYPE_PASSWORD = 0, // 密ç � LOGINOPT_TYPE_FACE, // 人脸 LOGINOPT_TYPE_FINGERPRINT, // 指纹 LOGINOPT_TYPE_IRIS, // 虹膜 LOGINOPT_TYPE_VOICEPRINT, // 声纹 LOGINOPT_TYPE_FINGERVEIN, // 指é�™è„‰ LOGINOPT_TYPE_GENERAL_UKEY, // 普通的ukey LOGINOPT_TYPE_ADVANCED_UKEY, // 高阶的ukey LOGINOPT_TYPE_QRCODE, // 二维ç � LOGINOPT_TYPE_OTHERS, // å…¶ä»– LOGINOPT_TYPE_COUNT }; /* the type of device */ enum BioType { BIOTYPE_FINGERPRINT, BIOTYPE_FINGERVEIN, BIOTYPE_IRIS, BIOTYPE_FACE, BIOTYPE_VOICEPRINT, __MAX_NR_BIOTYPES }; #define REMOTE_QRCODE_TYPE (8) /* StatusChanged D-Bus ä¿¡å�·è§¦å�‘时的状æ€�å�˜åŒ–类型 */ enum StatusType { STATUS_DEVICE, STATUS_OPERATION, STATUS_NOTIFY }; /* 录入/删除/æ�œç´¢ç­‰ D-Bus 调用的最终结果,å�³è¿”回值里的 result */ enum DBusResult { DBUS_RESULT_SUCCESS = 0, DBUS_RESULT_ERROR, DBUS_RESULT_DEVICEBUSY, DBUS_RESULT_NOSUCHDEVICE, DBUS_RESULT_PERMISSIONDENIED }; /** * @brief 识别æ“�作(Identify)的ops状æ€� */ /* 定义æ“�作类型 */ typedef enum { OPS_TYPE_COMM = 0, OPS_TYPE_OPEN, OPS_TYPE_ENROLL, OPS_TYPE_VERIFY, OPS_TYPE_IDENTIFY, OPS_TYPE_CAPTURE, OPS_TYPE_SEARCH, OPS_TYPE_CLEAN, OPS_TYPE_GET_FLIST, OPS_TYPE_RENAME, OPS_TYPE_CLOSE, }BioOpsType; /* * 定义å�„ç§�æ“�作结果 */ typedef enum { OPS_COMM_SUCCESS = OPS_TYPE_COMM * 100, /** 空闲状æ€� **/ OPS_COMM_FAIL, /** æ“�作失败 **/ OPS_COMM_NO_MATCH = OPS_COMM_FAIL, /** ä¸�匹é…� **/ OPS_COMM_ERROR, /** 通用æ“�作错误 **/ OPS_COMM_STOP_BY_USER, /** 用户å�–消 **/ OPS_COMM_TIMEOUT, /** æ“�作超时 **/ OPS_COMM_OUT_OF_MEM, /** 无法分é…�内存 **/ OPS_COMM_MAX, OPS_OPEN_SUCCESS = OPS_TYPE_OPEN * 100, /** 打开设备完æˆ� **/ OPS_OPEN_FAIL, /** 打开设备失败 **/ OPS_OPEN_ERROR, /** 打开设备é�‡åˆ°é”™è¯¯ **/ OPS_OPEN_MAX, OPS_ENROLL_SUCCESS = OPS_TYPE_ENROLL * 100, /** 录入信æ�¯æˆ�功 **/ OPS_ENROLL_FAIL, /** 录入失败 **/ OPS_ENROLL_ERROR, /** 录入过程中é�‡åˆ°é”™è¯¯ **/ OPS_ENROLL_STOP_BY_USER, /** 录入被用户中断 **/ OPS_ENROLL_TIMEOUT, /** æ“�作超时 **/ OPS_ENROLL_MAX, OPS_VERIFY_MATCH = OPS_TYPE_VERIFY * 100, /** 认è¯�匹é…� **/ OPS_VERIFY_NO_MATCH, /** 认è¯�ä¸�匹é…� **/ OPS_VERIFY_ERROR, /** 认è¯�过程中é�‡åˆ°é”™è¯¯ **/ OPS_VERIFY_STOP_BY_USER, /** 认è¯�被用户中断 **/ OPS_VERIFY_TIMEOUT, /** æ“�作超时 **/ OPS_VERIFY_MAX, OPS_IDENTIFY_MATCH = OPS_TYPE_IDENTIFY * 100, /** 识别到指定特å¾� **/ OPS_IDENTIFY_NO_MATCH, /** 未识别出指定特å¾� **/ OPS_IDENTIFY_ERROR, /** 识别过程中é�‡åˆ°é”™è¯¯ **/ OPS_IDENTIFY_STOP_BY_USER, /** 识别被用户中断 **/ OPS_IDENTIFY_TIMEOUT, /** æ“�作超时 **/ OPS_IDENTIFY_MAX, OPS_CAPTURE_SUCCESS = OPS_TYPE_CAPTURE * 100, /** æ�•获æˆ�功 **/ OPS_CAPTURE_FAIL, /** æ�•获失败 **/ OPS_CAPTURE_ERROR, /** æ�•获过程中é�‡åˆ°é”™è¯¯ **/ OPS_CAPTURE_STOP_BY_USER, /** æ�•获被用户中断 **/ OPS_CAPTURE_TIMEOUT, /** æ“�作超时 **/ OPS_CAPTURE_MAX, OPS_SEARCH_MATCH = OPS_TYPE_SEARCH * 100, /** æ�œç´¢åˆ°æŒ‡å®šç‰¹å¾� **/ OPS_SEARCH_NO_MATCH, /** 未æ�œç´¢åˆ°æŒ‡å®šç‰¹å¾� **/ OPS_SEARCH_ERROR, /** æ�œç´¢è¿‡ç¨‹ä¸­é�‡åˆ°é”™è¯¯ **/ OPS_SEARCH_STOP_BY_USER, /** æ�œç´¢è¢«ç”¨æˆ·ä¸­æ–­ **/ OPS_SEARCH_TIMEOUT, /** æ“�作超时 **/ OPS_SEARCH_MAX, OPS_CLEAN_SUCCESS = OPS_TYPE_CLEAN * 100, /** 清ç�†ç‰¹å¾�æˆ�功 **/ OPS_CLEAN_FAIL, /** 清ç�†å¤±è´¥ **/ OPS_CLEAN_ERROR, /** 清ç�†è¿‡ç¨‹ä¸­é�‡åˆ°é”™è¯¯ **/ OPS_CLEAN_STOP_BY_USER, /** 清ç�†è¢«ç”¨æˆ·ä¸­æ–­ **/ OPS_CLEAN_TIMEOUT, /** æ“�作超时 **/ OPS_CLEAN_MAX, OPS_GET_FLIST_SUCCESS = OPS_TYPE_GET_FLIST * 100, /** 获å�–特å¾�列表完æˆ� **/ OPS_GET_FLIST_FAIL, /** 获å�–特å¾�列表失败 **/ OPS_GET_FLIST_ERROR, /** 获å�–特å¾�列表过程中é�‡åˆ°é”™è¯¯ **/ OPS_GET_FLIST_STOP_BY_USER, /** 获å�–特å¾�列表被用户中断 **/ OPS_GET_FLIST_TIMEOUT, /** 获å�–特å¾�列表超时 **/ OPS_GET_FLIST_MAX, OPS_RENAME_SUCCESS = OPS_TYPE_RENAME * 100, /** é‡�命å��特å¾�完æˆ� **/ OPS_RENAME_FAIL, /** é‡�命å��特å¾�失败 **/ OPS_RENAME_ERROR, /** é‡�命å��特å¾�过程中é�‡åˆ°é”™è¯¯ **/ OPS_RENAME_STOP_BY_USER, /** é‡�命å��特å¾�被用户中断 **/ OPS_RENAME_TIMEOUT, /** é‡�命å��特å¾�è¶…æ—¶ **/ OPS_RENAME_MAX, OPS_CLOSE_SUCCESS = OPS_TYPE_CLOSE * 100, /** 关闭设备完æˆ� **/ OPS_CLOSE_FAIL, /** 关闭设备失败 **/ OPS_CLOSE_ERROR, /** 关闭设备过程中é�‡åˆ°é”™è¯¯ **/ OPS_CLOSE_MAX, }OpsResult; /** * @brief UpdateStauts调用返回的结果 */ struct StatusReslut { int result; int enable; int devNum; int devStatus; int opsStatus; int notifyMessageId; }; struct FeatureInfo { int uid; int biotype; QString device_shortname; int index; QString index_name; }; /* the info of device */ struct DeviceInfo { int device_id; QString device_shortname; /* aka driverName */ QString device_fullname; int driver_enable; /* The corresponding driver is enabled/disabled */ int device_available; /* The driver is enabled and the device is connected */ int biotype; int stotype; int eigtype; int vertype; int idtype; int bustype; int dev_status; int ops_status; bool operator==(const DeviceInfo&) const; bool operator !=(const DeviceInfo &deviceInfo) const { return !(*this == deviceInfo); } friend QDebug& operator<<(QDebug &stream, const DeviceInfo &deviceInfo); }; Q_DECLARE_METATYPE(DeviceInfo) typedef std::shared_ptr DeviceInfoPtr; typedef QList DeviceList; typedef QMap DeviceMap; typedef std::shared_ptr FeatureInfoPtr; typedef QList FeatureList; typedef QMap FeatureMap; QDBusArgument &operator<<(QDBusArgument &argument, const DeviceInfo &deviceInfo); const QDBusArgument &operator>>(const QDBusArgument &argument, DeviceInfo &deviceInfo); QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo); QDBusArgument &operator<<(QDBusArgument &argument, const FeatureInfo &featureInfo); const QDBusArgument &operator>>(const QDBusArgument &argument, FeatureInfo &featureInfo); QString bioTypeToString(int type); #endif // BIOCUSTOMTYPE_H ukui-biometric-auth/common/0000775000175000017500000000000015167732644014676 5ustar fengfengukui-biometric-auth/common/qt_matrix_compat.h0000664000175000017500000000506415167732644020427 0ustar fengfeng/* * Copyright (C) 2025 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef QT_MATRIX_COMPAT_H #define QT_MATRIX_COMPAT_H #include #include #if QT_VERSION_MAJOR == 6 // Qt6中使用QTransform替代QMatrix typedef QTransform QMatrix; // 为了ä¿�æŒ�API兼容性,æ��供一些QMatrix特有的方法 namespace QtMatrixCompat { // QMatrixçš„rotate方法在QTransform中对应rotate inline void rotateMatrix(QTransform& matrix, qreal angle) { matrix.rotate(angle); } // QMatrixçš„scale方法在QTransform中对应scale inline void scaleMatrix(QTransform& matrix, qreal sx, qreal sy) { matrix.scale(sx, sy); } // QMatrixçš„translate方法在QTransform中对应translate inline void translateMatrix(QTransform& matrix, qreal dx, qreal dy) { matrix.translate(dx, dy); } } #else // Qt5中直接使用QMatrix #include // 为了ä¿�æŒ�一致性,æ��供相å�Œçš„命å��空间 namespace QtMatrixCompat { inline void rotateMatrix(QMatrix& matrix, qreal angle) { matrix.rotate(angle); } inline void scaleMatrix(QMatrix& matrix, qreal sx, qreal sy) { matrix.scale(sx, sy); } inline void translateMatrix(QMatrix& matrix, qreal dx, qreal dy) { matrix.translate(dx, dy); } } #endif // æ��ä¾›QPixmap::transformed的兼容性处ç�† namespace QtPixmapCompat { inline QPixmap transformedPixmap(const QPixmap& pixmap, const QMatrix& matrix, Qt::TransformationMode mode = Qt::FastTransformation) { #if QT_VERSION_MAJOR == 6 // 在Qt6中,QMatrix实际上是QTransform return pixmap.transformed(static_cast(matrix), mode); #else // 在Qt5中,直接使用QMatrix return pixmap.transformed(matrix, mode); #endif } } #endif // QT_MATRIX_COMPAT_H ukui-biometric-auth/common/qt_desktop_compat.h0000664000175000017500000000733415167732644020576 0ustar fengfeng/* * Copyright (C) 2025 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef QT_DESKTOP_COMPAT_H #define QT_DESKTOP_COMPAT_H #include #include // QDesktopWidget 兼容性处ç�† #if QT_VERSION_MAJOR == 6 #include // Qt6中QDesktopWidget已被移除,使用QScreen替代 inline QScreen* getDesktopWidget() { return QApplication::primaryScreen(); } inline QRect getDesktopGeometry() { QScreen* screen = QApplication::primaryScreen(); return screen ? screen->geometry() : QRect(); } inline int getScreenCount() { return QApplication::screens().count(); } // 连接å±�幕å�˜åŒ–ä¿¡å�·çš„兼容性函数 template void connectScreenSignals(Receiver* receiver, Slot slot) { QApplication* app = qApp; QObject::connect(app, &QApplication::primaryScreenChanged, receiver, slot); QObject::connect(app, &QApplication::screenAdded, receiver, slot); QObject::connect(app, &QApplication::screenRemoved, receiver, slot); } template void disconnectScreenSignals(Receiver* receiver, Slot slot) { QApplication* app = qApp; QObject::disconnect(app, &QApplication::primaryScreenChanged, receiver, slot); QObject::disconnect(app, &QApplication::screenAdded, receiver, slot); QObject::disconnect(app, &QApplication::screenRemoved, receiver, slot); } #else #include inline QDesktopWidget* getDesktopWidget() { return QApplication::desktop(); } inline QRect getDesktopGeometry() { QDesktopWidget* desktop = QApplication::desktop(); return desktop ? desktop->geometry() : QRect(); } inline int getScreenCount() { QDesktopWidget* desktop = QApplication::desktop(); return desktop ? desktop->screenCount() : 0; } // 连接å±�幕å�˜åŒ–ä¿¡å�·çš„兼容性函数 template void connectScreenSignals(Receiver* receiver, Slot slot) { QDesktopWidget* desktop = QApplication::desktop(); if (desktop) { QObject::connect(desktop, SIGNAL(resized(int)), receiver, slot); QObject::connect(desktop, SIGNAL(workAreaResized(int)), receiver, slot); QObject::connect(desktop, SIGNAL(primaryScreenChanged(QScreen*)), receiver, slot); QObject::connect(desktop, SIGNAL(screenCountChanged(int)), receiver, slot); } } template void disconnectScreenSignals(Receiver* receiver, Slot slot) { QDesktopWidget* desktop = QApplication::desktop(); if (desktop) { QObject::disconnect(desktop, SIGNAL(resized(int)), receiver, slot); QObject::disconnect(desktop, SIGNAL(workAreaResized(int)), receiver, slot); QObject::disconnect(desktop, SIGNAL(primaryScreenChanged(QScreen*)), receiver, slot); QObject::disconnect(desktop, SIGNAL(screenCountChanged(int)), receiver, slot); } } #endif #endif // QT_DESKTOP_COMPAT_H ukui-biometric-auth/common/generic.h0000664000175000017500000000301115167732630016451 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef GENERIC_H #define GENERIC_H #define BIO_ERROR -1 #define BIO_FAILED 0 #define BIO_SUCCESS 1 #define BIO_IGNORE 2 #define BIOMETRIC_PAM_DOUBLE "BIOMETRIC_PAM_DOUBLE" #define BIOMETRIC_PAM "BIOMETRIC_PAM" #define BIOMETRIC_PAM_QRCODE "BIOMETRIC_PAM_QRCODE" #define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" #define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS" #define BIOMETRIC_FAILED "BIOMETRIC_FAILED" #define BIO_COM_FILE "/tmp/bio_com" #define STR(s) #s #define GET_STR(s) STR(s) #define _MULTI_THREADED #define AGENT_NAME "polkit-ukui-authentication-agent" #define POLKIT_LISTENER_ID "/org/ukui/PolicyKit1/AuthenticationAgent" #ifdef __cplusplus #include "qlogging.h" extern bool enableDebug; extern QString logPrefix; void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg); #endif #endif ukui-biometric-auth/common/generic.cpp0000664000175000017500000000377115167732630017021 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "generic.h" #include #include void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) { Q_UNUSED(context) if(!enableDebug) return; QDateTime dateTime = QDateTime::currentDateTime(); QByteArray time = QString("[%1] ").arg(dateTime.toString("MM-dd hh:mm:ss.zzz")).toLocal8Bit(); QByteArray localMsg = msg.toLocal8Bit(); QByteArray prefix = logPrefix.toLocal8Bit(); switch(type) { case QtDebugMsg: fprintf(stderr, "%s %s [Debug]: %s\n", prefix.constData(), time.constData(), localMsg.constData()); break; #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) case QtInfoMsg: fprintf(stderr, "%s %s [Info]: %s\n", prefix.constData(), time.constData(), localMsg.constData()); break; #endif case QtWarningMsg: fprintf(stderr, "%s %s [Warnning]: %s\n", prefix.constData(), time.constData(), localMsg.constData()); break; case QtCriticalMsg: fprintf(stderr, "%s %s [Critical]: %s\n", prefix.constData(), time.constData(), localMsg.constData()); break; case QtFatalMsg: fprintf(stderr, "%s %s [Fatal]: %s\n", prefix.constData(), time.constData(), localMsg.constData()); abort(); } } ukui-biometric-auth/pam-biometric/0000775000175000017500000000000015167732644016136 5ustar fengfengukui-biometric-auth/pam-biometric/biotest.c0000664000175000017500000001001115167732644017744 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #define BUF_SIZE 128 #define DISABLE_ECHO 0 #define ENABLE_ECHO 1 char * getpasswd(int enable_echo); int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); struct pam_conv conv = { pam_conversation, NULL }; int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int count = num_msg; char *password = 0; *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response)); /*指针备份,下é�¢çš„循环需è¦�指针å�Žç§»*/ struct pam_response *tmp_save = (struct pam_response *)(*resp); memset(*resp, 0, num_msg * sizeof(struct pam_response)); while(count-- >= 1){ switch((*msg)->msg_style){ case PAM_PROMPT_ECHO_OFF: printf("%s",(*msg)->msg); password = getpasswd(DISABLE_ECHO); (*resp)->resp = password; (*resp)->resp_retcode = 0; break; case PAM_PROMPT_ECHO_ON: printf("%s",(*msg)->msg); password = getpasswd(ENABLE_ECHO); (*resp)->resp = password; (*resp)->resp_retcode = 0; break; case PAM_ERROR_MSG: printf("%s",(*msg)->msg); break; case PAM_TEXT_INFO: printf("%s",(*msg)->msg); break; default: printf("Should not reach here!\n"); } if(count != 0){ msg++; (*resp)++; } } /*指针归ä½� 方法1*/ /* unsigned long address_value = (unsigned long)(*resp) - (num_msg -1) * sizeof(struct pam_response); (*resp) = (struct pam_response *)address_value; */ /*指针归ä½� 方法2*/ (*resp) = tmp_save; return PAM_SUCCESS; } int main(int argc, char *argv[]) { pam_handle_t *pamh = NULL; int retval; char *user = NULL; if(argc == 2){ user = argv[1]; } else { printf("Usage: You must specify a username.\n"); exit(1); } retval = pam_start("biotest", user, &conv, &pamh); if(retval == PAM_SUCCESS){ printf("PAM started Success.\n"); } else { printf("PAM started Failed.\n"); } int auth_status = pam_authenticate(pamh,0); if(auth_status != PAM_SUCCESS){ const char * error_msg = pam_strerror(pamh, auth_status); printf("Auth Status : %s\n",error_msg); } else { printf("Authenticate Success!\n"); auth_status = pam_acct_mgmt(pamh, 0); } if(pam_end(pamh, retval) != PAM_SUCCESS){ pamh = NULL; printf("Failed to terminate PAM."); exit(1); } return (retval == PAM_SUCCESS ? 0:1); } char * getpasswd(int enable_echo) { struct termios tp, save; char *password = (char *)malloc(BUF_SIZE * sizeof(char)); /* printf("Input Password:"); fflush(stdout); */ if (tcgetattr(STDIN_FILENO, &tp) == -1){ printf("tcgetattr error\n"); exit(1); } save = tp;/* So we can restore settings later */ if(enable_echo) ;/*Default is echo. Do nothing*/ else tp.c_lflag &= ~ECHO;/* ECHO off, other bits unchanged */ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tp) == -1){ printf("tcgetattr error\n"); exit(1); } /* Read some input */ if (fgets(password, BUF_SIZE, stdin) == NULL) printf("Got end-of-file/error on fgets()\n"); else ; /* Restore original terminal settings */ if (tcsetattr(STDIN_FILENO, TCSANOW, &save) == -1){ printf("tcgetattr error\n"); exit(1); } /*fgets读入的字符串末尾有回车符,在此替æ�¢ä¸º\0*/ password[strnlen(password,128)-1] = '\0'; return password; } ukui-biometric-auth/pam-biometric/pam_biometric.c0000664000175000017500000005370115167732644021122 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #define PAM_SM_AUTH #include "generic.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define USER_CONFIG_FILE "/home/%s/.biometric_auth/ukui_biometric.conf" /* Declare log function */ extern int pam_enable_debug; extern char *pam_log_prefix; extern int pam_logger(char *format, ...); static int ukui_biometric_lock = 0; int enable_biometric_authentication(pam_handle_t *pamh); int enable_qrcode_authentication(pam_handle_t *pamh); int enable_biometric_auth_double(); /* GUI child process alive status */ static int child_alive = 1; /* Signal handler */ static void signal_handler(int signo) { if (signo == SIGUSR1) child_alive = 0; /* GUI child process has terminated */ pam_logger("signal_handler is triggered\n"); } int enable_biometric_authentication_app() { char conf_file[] = GET_STR(CONFIG_FILE); FILE *file; char line[1024]; int i; int is_enable = 0; if((file = fopen(conf_file, "r")) == NULL){ pam_logger("open configure file failed: %s\n", strerror(errno)); return 1; } while(fgets(line, sizeof(line), file)) { i = sscanf(line, "EnableAuthApp=%d\n", &is_enable); if(i > 0) { pam_logger("EnableAuthApp=%d\n", is_enable); break; } } fclose(file); return is_enable; } /* * Check if the service should use biometric authentication */ int service_filter(char *service) { //int is_enable = enable_biometric_authentication_app(); //syslog(LOG_INFO,"is_enable = %d service = %s\n",is_enable,service); if (strcmp(service, "lightdm") == 0) { //if(is_enable & 1 == 0) // return 0; return 1; } if (strcmp(service, "ukui-screensaver-qt") == 0){ //if((is_enable & (1<<1)) == 0) // return 0; return 1; } if (strcmp(service, "polkit-1") == 0){ //if((is_enable & (1<<2)) == 0) // return 0; return 1; } if (strcmp(service, "sudo") == 0){ //if((is_enable & (1<<3)) == 0) // return 0; return 1; } if (strcmp(service, "su") == 0){ //if((is_enable & (1<<4)) == 0) // return 0; return 1; } if (strcmp(service, "login") == 0){ //if((is_enable & (1<<5)) == 0) // return 0; return 1; } #ifdef ENABLE_BIOTEST if (strcmp(service, "biotest") == 0) return 1; #endif return 0; } /* * Invoke the PAM conversation function */ int call_conversation(pam_handle_t *pamh, int msg_style, char *msg, char *resp, int resp_length) { /* PAM data structures used by conversation */ const struct pam_message *message[1] = {0}; struct pam_message *message_tmp = 0; struct pam_response *response = 0; const struct pam_conv *conv_struct = 0; int status = -1; status = pam_get_item(pamh, PAM_CONV, (const void **)&conv_struct); if (status != PAM_SUCCESS) return PAM_SYSTEM_ERR; message_tmp = (struct pam_message *)malloc(sizeof(struct pam_message)); message_tmp->msg_style = msg_style; message_tmp->msg = msg; message[0] = message_tmp; pam_logger("Call conv callback function\n"); status = conv_struct->conv(1, message, &response, conv_struct->appdata_ptr); pam_logger("Finish conv callback function\n"); if (resp && response->resp && resp_length > 1) snprintf(resp, resp_length - 1, "%s", response->resp); /* Use typecast to suppress gcc warnings */ free((void *)message[0]); if (response->resp) free(response->resp); free(response); return status; } /* GUI child process */ void child(char *service, char *username, char *xdisp) { pam_logger("Child process will be replaced.\n"); int fd = open("/dev/null", O_WRONLY); dup2(fd, 2); execl("/usr/bin/bioauth", "bioauth", "--service", service, "--user", username, // "--display", xdisp, pam_enable_debug ? "--debug" : "", (char *)0); /* * execl almost always succeed as long as the GUI executable file exists. * Though invoking GUI under console will exit with error, the GUI child * process won't reach here. Therefore, the following code won't be * executed in general. */ pam_logger("Fatal error: execl(gui) failed in child process. " "This is an extremely rare condition. Please ensure that the " "biometric-authentication executable file exists.\n"); pam_logger("Use password as a fallback\n"); pam_logger("Child _exit with BIO_IGNORE\n"); /* Child process exits */ _exit(BIO_IGNORE); } void handler(int signo) { (void)signo; // é�¿å…�未使用å�‚数警告 return; } /* PAM parent process */ int parent(int pid, pam_handle_t *pamh, int need_call_conv) { pam_logger("Parent process continue running.\n"); int child_status = -1; /* * 1. If calling conversation function is not needed, wait the child * until it exits. * 2. Otherwise, send a text info to application at first and then * call the conversation function to request the password. The returned * password is unused. * Note: During requesting the password, screensaver won't display the * prompting message, while greeter will display it into the password * entry. If there is a "\n" at the end of the message, it will be * displayed on the Label above the password entry. */ if (need_call_conv) { char *lang = getenv("LANG"); char *msg1, *msg2; if (lang && !strncmp(lang, "zh_CN", 5)) msg1 = "请进行生物识别或点击“切æ�¢åˆ°å¯†ç �登录â€�\n"; else msg1 = "Use biometric authentication or click " "\"Switch to password\"\n"; #ifdef EMPTY_PAM_PWD_PROMPT msg2 = ""; #else msg2 = "pam_biometric.so needs a fake ENTER:"; #endif if (signal(SIGUSR1, signal_handler) == SIG_ERR) pam_logger("Fatal Error. Can't catch SIGUSR1\n"); reinvoke: call_conversation(pamh, PAM_TEXT_INFO, msg1, NULL, 0); call_conversation(pamh, PAM_PROMPT_ECHO_OFF, msg2, NULL, 0); /* GUI child process is still alive. This enter is typed by user. */ if (child_alive == 1) goto reinvoke; signal(SIGUSR1, SIG_DFL); waitpid(pid, &child_status, 0); } else { pam_logger("Waiting for the GUI child process to exit...\n"); //由于sudo命令在进入pam认è¯�时,会阻塞æ�¥è‡ªç»ˆç«¯çš„SIGINT以å�ŠSIGQUITä¿¡å�·ï¼Œå¯¼è‡´ä½¿ç”¨ //pam认è¯�时,按下Ctrl+Cæ— å��应,认è¯�完æˆ�å�Žï¼Œsudo会退出,这里为了简å�•,å�–消了阻塞 //ä¿¡å�·ï¼Œæ�•获信å�·ä½†ä¸�å�šå¤„ç�†ï¼Œåœ¨è®¤è¯�完æˆ�å�Žï¼Œæ�¢å¤�原本阻塞状æ€� sigset_t mask; sigprocmask(SIG_BLOCK,NULL,&mask); sigprocmask(SIG_UNBLOCK,&mask,NULL); signal(SIGINT,handler); waitpid(pid, &child_status, 0); pam_logger("GUI child process has exited.\n"); sigprocmask(SIG_SETMASK,&mask,NULL); } /* * Determine the return value of PAM according to the return value of * child process. */ int bio_result = BIO_ERROR; /* biometric result code */ if (WIFEXITED(child_status)) bio_result = WEXITSTATUS(child_status); else /* This may be because the GUI child process is invoked under console. */ pam_logger("The GUI-Child process terminate abnormally.\n"); if (bio_result == BIO_SUCCESS) { if(!enable_biometric_authentication(pamh) && !enable_qrcode_authentication(pamh)) { pam_logger("disable biometric authentication.\n"); return PAM_SYSTEM_ERR; } pam_logger("pam_biometric.so return PAM_SUCCESS\n"); return PAM_SUCCESS; } else if (bio_result == BIO_IGNORE) { /* Override msg1 to empty the label. We are ready to enter the password module. */ call_conversation(pamh, PAM_TEXT_INFO, "", NULL, 0); ukui_biometric_lock = 1; pam_logger("pam_biometric.so return PAM_IGNORE\n"); return PAM_IGNORE; } else { pam_logger("pam_biometric.so return PAM_SYSTEM_ERR\n"); ukui_biometric_lock = 1; return PAM_SYSTEM_ERR; } } /* Set environment variables related to displaying */ void check_and_set_env(pam_handle_t *pamh, char **xdisp, char **xauth) { *xdisp=getenv("DISPLAY"); *xauth=getenv("XAUTHORITY"); if (*xdisp == 0){ pam_get_item(pamh, PAM_XDISPLAY, (const void **)xdisp); if (*xdisp) setenv("DISPLAY",*xdisp,-1); } if (*xauth == 0) setenv("XAUTHORITY", "/var/run/lightdm/root/:0", -1); *xdisp=getenv("DISPLAY"); *xauth=getenv("XAUTHORITY"); if (*xdisp == 0) pam_logger("Warning: DISPLAY env is still empty, " "this is not an error if you are using terminal\n"); if (*xauth == 0) pam_logger("Warning: XAUTHORITY env is still empty, " "this is not an error if you are using terminal\n"); } /* Biometric processing function for generic purpose */ int biometric_auth_independent(pam_handle_t *pamh , char *service, int need_call_conv) { /* Get the username */ char *username = 0; pam_get_item(pamh, PAM_USER, (const void **)&username); /* Check and set environment variables */ char *xdisp, *xauth; check_and_set_env(pamh, &xdisp, &xauth); /* Detach child process */ unsigned int pid; pid = fork(); if (pid < 0) { pam_logger("Fork Error!\n"); return PAM_SYSTEM_ERR; } else if (pid != 0) { return parent(pid, pamh, need_call_conv); } else { child(service, username, xdisp); pam_logger("Should never reach here.\n"); return PAM_SYSTEM_ERR; } } int biometric_auth_embeded(pam_handle_t *pamh) { /* * By convention, PAM module sends a string "BIOMETRIC_PAM" to * lightdm and this message will be forwarded to greeter. After * the authentication is completed, greeter will send a string * "BIOMETRIC_IGNORE"/"BIOMETRIC_SUCCESS" to lightdm and then it * will be forwarded to PAM module. We can get the authentication * status by comparing strings. */ char resp[96] = {0}; if(enable_biometric_auth_double()) call_conversation(pamh, PAM_PROMPT_ECHO_OFF, BIOMETRIC_PAM_DOUBLE, resp, sizeof(resp)); else call_conversation(pamh, PAM_PROMPT_ECHO_OFF, BIOMETRIC_PAM, resp, sizeof(resp)); if (strcmp(resp, BIOMETRIC_IGNORE) == 0) return PAM_IGNORE; else if (strcmp(resp, BIOMETRIC_SUCCESS) == 0){ if(!enable_biometric_authentication(pamh) && !enable_qrcode_authentication(pamh)) { pam_logger("disable biometric authentication.\n"); return PAM_SYSTEM_ERR; } return PAM_SUCCESS; } else if (strcmp(resp, BIOMETRIC_FAILED) == 0) return PAM_AUTH_ERR; else return PAM_SYSTEM_ERR; } void get_greeter_session(char buf[], int len) { GPtrArray *args_ps = NULL; gchar *stdout_ps = NULL; gchar *greeter_name = NULL; args_ps = g_ptr_array_new (); g_ptr_array_add(args_ps, (gpointer)"/usr/bin/ps"); g_ptr_array_add(args_ps, (gpointer)"-aux"); g_ptr_array_add(args_ps, (gpointer)"--columns"); g_ptr_array_add(args_ps, (gpointer)"256"); g_ptr_array_add(args_ps, NULL); if (!g_spawn_sync(NULL, (char**)args_ps->pdata, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &stdout_ps, NULL, NULL, NULL)) { if (stdout_ps) g_free(stdout_ps); g_ptr_array_free (args_ps, TRUE); return ; } if (stdout_ps) { gchar **lines = NULL; lines = g_strsplit(stdout_ps, "\n", 0); for (int n = 0; lines[n] != NULL; n++) { if (lines[n][0] == '\0') continue; gchar *res = g_strstr_len(lines[n], 1024, "greeter-session"); if (res) { gchar **greeter_args = g_strsplit(res, " ", 0); int arg_index = 0; for (int m = 0; greeter_args[m] != NULL; m++) { if (greeter_args[m][0] == '\0') continue; // greeter-session arg1 if (arg_index == 1) { gchar *greeter = g_strrstr_len(greeter_args[m], 256, "/"); if (greeter && strnlen(greeter,1024) > 1) { greeter_name = g_strdup(greeter + 1); break; } } arg_index ++; } g_strfreev(greeter_args); if (greeter_name) { break; } } } g_strfreev(lines); g_free(stdout_ps); } g_ptr_array_free (args_ps, TRUE); if (greeter_name) { g_strlcpy(buf, greeter_name, len); g_free(greeter_name); } else { GPtrArray *args_pidof = NULL; gchar *stdout_pidof = NULL; args_pidof = g_ptr_array_new (); g_ptr_array_add(args_pidof, (gpointer)"/usr/bin/pidof"); g_ptr_array_add(args_pidof, (gpointer)"ukui-greeter"); g_ptr_array_add(args_pidof, NULL); if (!g_spawn_sync(NULL, (char**)args_pidof->pdata, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &stdout_pidof, NULL, NULL, NULL)) { if (stdout_pidof) g_free(stdout_pidof); g_ptr_array_free (args_pidof, TRUE); //如果ukui-greeter进程ä¸�存在,进而判断ukui-screensaver-backend进程 args_pidof = g_ptr_array_new (); g_ptr_array_add(args_pidof, (gpointer)"/usr/bin/pidof"); g_ptr_array_add(args_pidof, (gpointer)"ukui-screensaver-backend"); g_ptr_array_add(args_pidof, NULL); if (!g_spawn_sync(NULL, (char**)args_pidof->pdata, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &stdout_pidof, NULL, NULL, NULL)) { if (stdout_pidof) { g_free(stdout_pidof); stdout_pidof = NULL; } g_ptr_array_free (args_pidof, TRUE); } if (stdout_pidof) { if (strnlen(stdout_pidof,1024) > 0 && atoi(stdout_pidof) > 0) { g_strlcpy(buf, "ukui-screensaver-backend", len); } g_free(stdout_pidof); } g_ptr_array_free (args_pidof, TRUE); return ; } if (stdout_pidof) { if (strnlen(stdout_pidof,1024) > 0 && atoi(stdout_pidof) > 0) { g_strlcpy(buf, "ukui-greeter", len); } g_free(stdout_pidof); } g_ptr_array_free (args_pidof, TRUE); } } int enable_by_polkit() { FILE *file; char buf[1024]; if( (file = fopen(BIO_COM_FILE, "r")) == NULL) { pam_logger("open communication file failed: %s\n", strerror(errno)); return 0; } memset(buf, 0, sizeof(buf)); fgets(buf, sizeof(buf), file); fclose(file); if(remove(BIO_COM_FILE) < 0) pam_logger("remove communication file failed: %s\n", strerror(errno)); pam_logger("%s\n", buf); if(strcmp(buf, "polkit-ukui-authentication-agent-1") == 0) return 1; return 0; } int enable_biometric_authentication(pam_handle_t *pamh) { char *username = NULL; int is_found = 0; int is_auth_enable = 0; pam_get_item(pamh, PAM_USER, (const void **)&username); if (username) { char conf_file_user[256]; snprintf(conf_file_user, 255, USER_CONFIG_FILE, username); FILE *file = NULL; char line[1024], is_enable[16]; int i; if((file = fopen(conf_file_user, "r")) == NULL){ pam_logger("open configure file failed: %s\n", strerror(errno)); } else { while(fgets(line, sizeof(line), file)) { i = sscanf(line, "EnableAuth=%15s\n", is_enable); if(i > 0) { pam_logger("EnableAuth=%s\n", is_enable); is_found = 1; break; } } fclose(file); if(!strcmp(is_enable, "true")) is_auth_enable = 1; } } if (is_found != 0) { return is_auth_enable; } char conf_file[] = GET_STR(CONFIG_FILE); FILE *file; char line[1024], is_enable[16]; int i; if((file = fopen(conf_file, "r")) == NULL){ pam_logger("open configure file failed: %s\n", strerror(errno)); return 0; } while(fgets(line, sizeof(line), file)) { i = sscanf(line, "EnableAuth=%15s\n", is_enable); if(i > 0) { pam_logger("EnableAuth=%s\n", is_enable); break; } } fclose(file); if(!strcmp(is_enable, "true")) return 1; return 0; } int enable_qrcode_authentication(pam_handle_t *pamh) { char *username = NULL; int is_found = 0; int is_auth_enable = 0; pam_get_item(pamh, PAM_USER, (const void **)&username); if (username) { char conf_file_user[256]; snprintf(conf_file_user, 255, USER_CONFIG_FILE, username); FILE *file = NULL; char line[1024], is_enable[16]; int i; if((file = fopen(conf_file_user, "r")) == NULL){ pam_logger("open configure file failed: %s\n", strerror(errno)); } else { while(fgets(line, sizeof(line), file)) { i = sscanf(line, "EnableQRCode=%15s\n", is_enable); if(i > 0) { pam_logger("EnableQRCode=%s\n", is_enable); is_found = 1; break; } } fclose(file); if(!strcmp(is_enable, "true")) is_auth_enable = 1; } } if (is_found != 0) { return is_auth_enable; } char conf_file[] = GET_STR(CONFIG_FILE); FILE *file; char line[1024], is_enable[16]; int i; if((file = fopen(conf_file, "r")) == NULL){ pam_logger("open configure file failed: %s\n", strerror(errno)); return 0; } while(fgets(line, sizeof(line), file)) { i = sscanf(line, "EnableQRCode=%15s\n", is_enable); if(i > 0) { pam_logger("EnableQRCode=%s\n", is_enable); break; } } fclose(file); if(!strcmp(is_enable, "true")) return 1; return 0; } int enable_biometric_auth_double() { char conf_file[] = GET_STR(CONFIG_FILE); FILE *file; char line[1024], is_enable[16]; int i; if((file = fopen(conf_file, "r")) == NULL){ pam_logger("open configure file failed: %s\n", strerror(errno)); return 0; } while(fgets(line, sizeof(line), file)) { i = sscanf(line, "DoubleAuth=%s\n", is_enable); if(i > 0) { pam_logger("DoubleAuth=%s\n", is_enable); break; } } fclose(file); if(!strcmp(is_enable, "true")) return 1; return 0; } /* * SPI interface */ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { for(int i = 0; i < argc; i++) { if(strcmp(argv[i], "debug") == 0) { pam_enable_debug = 1; pam_log_prefix = "PAM_BIO"; } } pam_logger("Invoke libpam_biometric.so module\n"); char *service = 0; if((!enable_biometric_authentication(pamh) && !enable_qrcode_authentication(pamh)) || ukui_biometric_lock) { pam_logger("disable biometric authentication.\n"); return PAM_IGNORE; } pam_logger("enable biometric authentication.\n"); pam_get_item(pamh, PAM_SERVICE, (const void **)&service); /* Service filter */ if (!service_filter(service)){ pam_logger("Service <%s> should not use biometric-authentication\n", service); return PAM_IGNORE; } /* Different services use different processing function */ if (strcmp(service, "lightdm") == 0) { char buf[128]; get_greeter_session(buf, sizeof(buf)); pam_logger("current greeter: %s\n", buf); if(strcmp(buf, "ukui-greeter") == 0 || strcmp(buf, "ukui-greeter-wayland") == 0 || strcmp(buf, "ukui-session") == 0 || strcmp(buf,"ukui-screensaver-backend")) return biometric_auth_embeded(pamh); // else // return biometric_auth_independent(pamh, "lightdm", 1); } else if (strcmp(service, "ukui-screensaver-qt")==0) return biometric_auth_embeded(pamh); else if (strcmp(service, "polkit-1") == 0){ if(enable_by_polkit()) return biometric_auth_embeded(pamh); else pam_logger("[PAM_BIOMETRIC]: It's not polkit-ukui-authentication-agent-1.\n"); } else if (strcmp(service, "sudo") == 0) return biometric_auth_independent(pamh, "sudo", 0); else if (strcmp(service, "login") == 0) return biometric_auth_independent(pamh, "login", 0); else if (strcmp(service, "su") == 0) return biometric_auth_independent(pamh, "su", 0); // else if (strcmp(service, "mate-screensaver") == 0) // return biometric_auth_independent(pamh, "mate-screensaver", 1); #ifdef ENABLE_BIOTEST else if (strcmp(service, "biotest") == 0) return biometric_auth_independent(pamh, "biotest", 1); #endif else pam_logger("Service <%s> slip through the service filter\n", service); return PAM_IGNORE; } int pam_sm_setcred (pam_handle_t *pamh, int flags , int argc , const char **argv ) { return PAM_SUCCESS; } ukui-biometric-auth/pam-biometric/logger.c0000664000175000017500000000243115167732630017554 0ustar fengfeng/* * Copyright (C) 2023 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include int pam_enable_debug; char *pam_log_prefix; void pam_logger(char *format, ...) { if(!pam_enable_debug){ return; } va_list args; time_t t = time(NULL); char timestr[32] = {0}; strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&t)); //产生"YYYYMMDD hh:mm:ss"æ ¼å¼�的字符串。 fprintf(stderr, "[%s] %s - ", pam_log_prefix, timestr); va_start(args, format); /* åˆ�始化 args */ vfprintf(stderr, format, args); } ukui-biometric-auth/pam-biometric/CMakeLists.txt0000664000175000017500000000342215167732644020677 0ustar fengfengproject(pam_biometric) find_path(PAM_INCLUDE_DIR security/pam_modules.h) find_library(PAM_LIB NAMES pam) if(NOT PAM_INCLUDE_DIR OR NOT PAM_LIB) message(FATAL_ERROR "pam_modules.h not found") endif() set(SCRIPTS_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/bin) configure_file( ${PROJECT_SOURCE_DIR}/data/org.freedesktop.plicykit.pkexec.bioctl-helper.policy.in ${PROJECT_BINARY_DIR}/data/org.freedesktop.plicykit.pkexec.bioctl-helper.policy ) configure_file( ${PROJECT_SOURCE_DIR}/data/org.freedesktop.plicykit.pkexec.biodrvctl.policy.in ${PROJECT_BINARY_DIR}/data/org.freedesktop.plicykit.pkexec.biodrvctl.policy ) configure_file( ${PROJECT_SOURCE_DIR}/data/org.freedesktop.plicykit.pkexec.biorestart.policy.in ${PROJECT_BINARY_DIR}/data/org.freedesktop.plicykit.pkexec.biorestart.policy ) set(pam_SRCS pam_biometric.c logger.c ) include_directories( ../common ${PAM_INCLUDE_DIR} ${GLIB2_INCLUDE_DIRS} ) add_library(pam_biometric SHARED ${pam_SRCS}) target_link_libraries(pam_biometric ${PAM_LIB} ${GLIB2_LIBRARIES}) #去除libå‰�ç¼€ set_target_properties(pam_biometric PROPERTIES PREFIX "") install(TARGETS pam_biometric DESTINATION /usr/lib/security) install(FILES pam-configs/pam-biometric DESTINATION /etc/pam-configs) install(FILES data/ukui-biometric.conf DESTINATION /usr/share/ukui-biometric) install(FILES ${PROJECT_BINARY_DIR}/data/org.freedesktop.plicykit.pkexec.bioctl-helper.policy ${PROJECT_BINARY_DIR}/data/org.freedesktop.plicykit.pkexec.biodrvctl.policy ${PROJECT_BINARY_DIR}/data/org.freedesktop.plicykit.pkexec.biorestart.policy DESTINATION /usr/share/polkit-1/actions ) install(FILES utils/bioctl utils/bioctl-helper utils/biodrvctl utils/biorestart DESTINATION bin PERMISSIONS ${CONDOR_SCRIPT_PERMS}) ukui-biometric-auth/pam-biometric/utils/0000775000175000017500000000000015167732630017271 5ustar fengfengukui-biometric-auth/pam-biometric/utils/bioctl0000775000175000017500000000050215167732630020470 0ustar fengfeng#!/bin/bash # Usage: bioctl status|enable|disable if [ "$1" = "enable" ]; then pkexec /usr/bin/bioctl-helper enable $2 elif [ "$1" = "disable" ]; then pkexec /usr/bin/bioctl-helper disable $2 elif [ "$1" = "status" ]; then /usr/bin/bioctl-helper status $2 else echo "Usage: bioctl status|enable|disable" fi exit 0 ukui-biometric-auth/pam-biometric/utils/bioctl-helper0000775000175000017500000002050015167732630021745 0ustar fengfeng#!/bin/bash # Usage: bioctl status|enable|disable CONFIG_DIR=/etc/biometric-auth CONFIG_FILE=$CONFIG_DIR/ukui-biometric.conf function test_privilege() { if [ `whoami` != 'root' ]; then echo $(gettext "Permission denied, please run by root") exit 1; fi } if [ ! -d $CONFIG_DIR ]; then mkdir -p $CONFIG_DIR fi if [ ! -f $CONFIG_FILE ]; then touch $CONFIG_FILE fi contain_key=`grep -c "^EnableAuth=" $CONFIG_FILE` contain_key_app=`grep -c "^EnableAuthApp=" $CONFIG_FILE` greeter=1 screensaver=$[1<<1] polkit=$[1<<2] sudo=$[1<<3] su=$[1<<4] login=$[1<<5] if [ "$1" = "enable" ]; then test_privilege # 生物识别管ç�†å·¥å…·åœ¨æ‰“开生物识别开关的时候会调用这个脚本, # 如果之å‰�手动改过pamçš„é…�置文件,在执行这个脚本的时候会有交互 # 性æ��示,但å‰�端程åº�上看ä¸�到,导致生物识别管ç�†å·¥å…·é˜»å¡žï¼Œä¸�过 # 由于在安装pam_biomtric这个包时已ç»�执行了这个命令,且会通过 # /etc/biometric-auth é…�置文件æ�¥åˆ¤æ–­ç”Ÿç‰©è¯†åˆ«çжæ€�,所以也ä¸�需è¦� #执行 pam-auth-update 了。 #pam-auth-update --package pam-biometric if [[ $# > 1 ]] && [[ $2 = "greeter" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app | $greeter ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=63" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "screensaver" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app | $screensaver ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=63" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "sudo" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app | $sudo ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=63" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "polkit" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app | $polkit ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=63" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "su" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app | $su ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=63" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "login" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app | $login ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=63" >> $CONFIG_FILE fi elif [ "$contain_key" = "1" ]; then sed -i 's/^EnableAuth=[a-zA-Z0-9]*/EnableAuth=true/g' $CONFIG_FILE else echo "EnableAuth=true" >> $CONFIG_FILE fi elif [ "$1" = "disable" ]; then test_privilege if [[ $# > 1 ]] && [[ $2 = "greeter" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app & $[~$greeter] ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=0" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "screensaver" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app & $[ ~$screensaver ]] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=0" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "sudo" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app & $[ ~$sudo ] ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=0" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "polkit" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app & $[~$polkit] ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=0" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "su" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app & $[~$su] ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=0" >> $CONFIG_FILE fi elif [[ $# > 1 ]] && [[ $2 = "login" ]]; then if [ "$contain_key_app" = "1" ]; then cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=$[ $cur_status_app & $[~$login] ] sed -i "s/^EnableAuthApp=[a-zA-Z0-9]*/EnableAuthApp=$cur_status_app/g" $CONFIG_FILE else echo "EnableAuthApp=0" >> $CONFIG_FILE fi elif [ "$contain_key" = "1" ]; then sed -i 's/^EnableAuth=[a-zA-Z0-9]*/EnableAuth=false/g' $CONFIG_FILE else echo "EnableAuth=false" >> $CONFIG_FILE fi elif [ "$1" = "status" ]; then cur_status=`sed '/^EnableAuth=/!d;s/.*=//' $CONFIG_FILE` cur_status_app=`sed '/^EnableAuthApp=/!d;s/.*=//' $CONFIG_FILE` if [[ $# > 1 ]] && [[ $2 = "greeter" ]];then if [ $[ $[cur_status_app] & $[greeter] ] = $greeter ]; then echo "enable" else echo "disable" fi elif [[ $# > 1 ]] && [[ $2 = "screensaver" ]];then if [ $[$cur_status_app & $screensaver] = $screensaver ]; then echo "enable" else echo "disable" fi elif [[ $# > 1 ]] && [[ $2 = "sudo" ]];then if [ $[$cur_status_app & $sudo] = $sudo ]; then echo "enable" else echo "disable" fi elif [[ $# > 1 ]] && [[ $2 = "polkit" ]];then if [ $[$cur_status_app & $polkit] = $polkit ]; then echo "enable" else echo "disable" fi elif [[ $# > 1 ]] && [[ $2 = "su" ]];then if [ $[$cur_status_app & $su] = $su ]; then echo "enable" else echo "disable" fi elif [[ $# > 1 ]] && [[ $2 = "login" ]];then if [ $[$cur_status_app & $login] = $login ]; then echo "enable" else echo "disable" fi elif [ "$cur_status" = "true" ]; then echo "enable" else echo "disable" fi else echo "Usage: bioctl status|enable|disable" fi exit 0 ukui-biometric-auth/pam-biometric/utils/biorestart0000775000175000017500000000024515167732630021376 0ustar fengfeng#!/bin/bash if [ `whoami` != 'root' ]; then echo $(gettext "Permission denied, please run by root") exit 1 fi systemctl restart biometric-authentication.service ukui-biometric-auth/pam-biometric/utils/biodrvctl0000775000175000017500000000143615167732630021213 0ustar fengfeng#!/bin/bash export TEXTDOMAINDIR=/usr/share/locale export TEXTDOMAIN=biodrvctl . gettext.sh function usage() { echo -e "Usage:" echo -e " biodrvctl "$(gettext "COMMAND DRIVER-NAME") echo echo -e "Build-in command:" echo -e " enable\t"$(gettext "Enable device's driver") echo -e " disable\t"$(gettext "Disable device's driver") } if [ $# -ne 2 ]; then usage exit 1 fi if [ `whoami` != 'root' ]; then echo $(gettext "Permission denied, please run by root") exit 1 fi if [ "$1" == "enable" ]; then biometric-config-tool enable-driver $2 elif [ "$1" == "disable" ]; then biometric-config-tool disable-driver $2 else usage exit 1 fi if [ $? -eq 0 ]; then systemctl reset-failed biometric-authentication.service systemctl restart biometric-authentication.service fi exit $? ukui-biometric-auth/pam-biometric/pam-configs/0000775000175000017500000000000015167732630020334 5ustar fengfengukui-biometric-auth/pam-biometric/pam-configs/pam-biometric0000664000175000017500000000026515167732630023012 0ustar fengfengName: Biometric Verification Default: yes Priority: 260 Conflicts: fprint fprintd fprintd.i386 fprintd.amd64 Auth-Type: Primary Auth: [success=end default=ignore] pam_biometric.so ukui-biometric-auth/pam-biometric/data/0000775000175000017500000000000015167732644017047 5ustar fengfengukui-biometric-auth/pam-biometric/data/org.freedesktop.plicykit.pkexec.biorestart.policy.in0000664000175000017500000000634015167732630031256 0ustar fengfeng Restart Service é‡�å�¯ç”Ÿç‰©ç‰¹å¾�æœ�务 བསà¾�ྱར་དུ་ཞབས་འདེགས་ཞུ་བ ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ ᠤᠨ ᠣᠨᠴᠠᠯᠢᠭ ᠤᠨ ᠦᠢᠯᠡᠴᠢᠯᠡᠭᠡ á ¶á ¢ ᠳᠠᠬᠢᠨ ᠡᠭᠢᠯᠡᠭᠦᠯᠪᠡ᠃ Authentication is required to restart biometric service é‡�啟生物特徵æœ�å‹™ بىئولوگىيەلىك ئالاھىدىلىك مۇلازىمىتىنى قايتىدىن قوزغىتىش بىئولوگىيەلىك ەرەكشەلىك قىزىمەتتى قايتادان قوزعالتۋ بىئولوگىيەلىك ۅزگۅچۅلۉك مۇلازىمەتىردى قايتادان قوزعوتۇۇ é‡�å�¯ç”Ÿç‰©ç‰¹å¾�æœ�务需è¦�身份验è¯� སà¾�ྱ་དངོས་དབྱེ་འབྱེད་ཞབས་ཞུ་སླར་གསོ་བྱེད་པར་བདེན་དཔང་ར་སྤྲད་བྱ་དགོསà¼� ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ ᠤᠨ ᠣᠨᠴᠠᠯᠢᠭ ᠰᠢᠨᠵᠢ ᠲᠡᠮᠳᠡᠭ ᠦᠨ ᠦᠢᠯᠡᠴᠢᠯᠡᠭᠡ á ¶á ¢ ᠳᠠᠬᠢᠨ ᠰᠡᠩᠬᠡᠷᠡᠭᠦᠯᠬᠦ ᠳᠦ ᠪᠡᠶ᠎ᠡ ᠶᠢᠨ ᠭᠠᠷᠤᠯ á ¢ ᠰᠢᠯᠭᠠᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠬᠦ ᠴᠢᠬᠤᠯᠠ ᠲᠠᠶ ᠪᠠᠶᠢᠨ᠎ᠠ á ƒ بىئولوگىيەلىك ئالاھىدىلىك مۇلازىمىتىنى قايتىدىن قوزغىتىش ئۈچۈن دەلىللەش ÙƒÛ�رەك é‡�啟生物特徵æœ�務需è¦�身份驗證 بىئولوگىيەلىك ەرەكشەلىك قىزىمەتتى قايتادان قوزعالتۋ ٷشٸن دالەلدەۋ كەرەك بىئولوگىيەلىك پارىقتاندىرۋ اسبابٸن قوزعالتۋ مەڭگەرۋ ەتۋ اسپاپتى جۇرگىزۋ بىئولوگىيەلىك ۅزگۅچۅلۉك مۇلازىمەتىردى قايتادان قوزعوتۇۇ Û‰Ú†Û‰Ù† دالىلدۅ كەرەك بىئولوگىيەلىك ايىرمالاندىرىش جابدۇۇسۇن قوزعوتۇۇ تىزگىندۅۅ جاسوو ،اتقارۇۇ stock_person auth_admin auth_admin auth_admin_keep ${SCRIPTS_INSTALL_PATH}/biorestart ukui-biometric-auth/pam-biometric/data/org.freedesktop.plicykit.pkexec.bioctl-helper.policy.in0000664000175000017500000000641415167732630031633 0ustar fengfeng Run the biometric authentication control tool è¿�行生物识别认è¯�控制工具 འà½�ོར་སà¾�ྱོད་སà¾�ྱེ་དངོས་ཀྱི་ངོས་འཛིན་à½�ས་ལེན་ཚོད་འཛིན་ཡོ་བྱདà¼�à¼� ᠠᠵᠢᠯᠯᠠᠭᠠᠨ á ¤ ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ á ¢ ᠢᠯᠭᠠᠨ ᠲᠠᠨᠢᠵᠤ ᠭᠡᠷᠡᠴᠢᠯᠡᠬᠦ ᠡᠵᠡᠮᠳᠡᠯ ᠦᠨ ᠪᠠᠭᠠᠵᠢ á ¶á ¢ ᠢᠯᠭᠠᠨ ᠲᠠᠨᠢᠬᠤ ᠬᠡᠷᠡᠭᠲᠡᠶ á ƒ é�‹è¡Œç”Ÿç‰©è­˜åˆ¥èª�證控制工具 بىئولوگىيەلىك پەرقلەندۈرۈش ئىسپاتلاش كونترول قىلىش قورالى بىئولوگىيەلىك پارىقتاندىرۋ سپاتتاۋ مەڭگەرۋ ەتۋ قۇرالى بىئولوگىيەلىك ايىرمالاندىرىش ىسپاتتوو تىزگىندۅۅ جاسوو ،اتقارۇۇ قۇرالى Authentication is required to enable or disable biometric authentication å¼€å�¯æˆ–关闭生物识别认è¯�需è¦�进行身份验è¯� སྒོ་རྒྱག་པའམ་ཡང་ན་སྒོ་རྒྱག་པའི་སà¾�ྱེ་དངོས་ངོས་འཛིན་བདེན་དཔངར་སྤྲོད་བྱེད་པར་à½�ོབ་à½�ང་གི་ཚོད་ལྟསར་སྤྲོད་བྱ་དགོསà¼� ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ á ¢ ᠢᠯᠭᠠᠨ ᠲᠠᠨᠢᠬᠤ ᠭᠡᠷᠡᠴᠢᠯᠡᠭᠡ á ¶á ¢ ᠨᠡᠭᠡᠭᠡᠬᠦ ᠪᠤᠶᠤ ᠬᠠᠭᠠᠬᠤ ᠳᠤ ᠪᠡᠶ᠎ᠡ ᠶᠢᠨ ᠭᠠᠷᠤᠯ ᠤᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠯ ᠬᠢᠬᠦ ᠴᠢᠬᠤᠯᠠ ᠲᠠᠶ ᠪᠠᠶᠢᠨ᠎ᠠ᠃ 開啟或關閉生物識別èª�證需è¦�進行身份驗證 بىئولوگىيەلىك پەرقلەندۈرۈش ئىسپاتىنى ئÛ�چىش ياكى تاقاش ئۈچۈن دەلىللەش ÙƒÛ�رەك بىئولوگىيەلىك پارىقتاندىرۋ سىپاتىن ٸشٸۋ ياكي تاقاۋ ٷشٸن دالەلدەۋ كەرەك بىئولوگىيەلىك ايىرمالاندىرىش دالىلىن اچۇۇ كۅرۉنۉشتۅرۉ بەكىتىش Û‰Ú†Û‰Ù† دالىلدۅ كەرەك stock_person no no yes ${SCRIPTS_INSTALL_PATH}/bioctl-helper ukui-biometric-auth/pam-biometric/data/ukui-biometric.conf0000664000175000017500000000034715167732644022652 0ustar fengfeng[General] EnableAuth=true EnableAuthApp=63 DefaultDevice= DoubleAuth=false UserBind=false isShownInControlCenter=false UseFirstDevice=true MaxFailedTimes=5 HiddenSwitchButton=false FaceTimeoutTimes=1 [Functions] EnableQRCode=true ukui-biometric-auth/pam-biometric/data/org.freedesktop.plicykit.pkexec.biodrvctl.policy.in0000664000175000017500000000647515167732630031101 0ustar fengfeng Run the biometric device driver control tool è¿�行生物识别设备驱动控制工具 སà¾�ྱ་དངོས་དབྱེ་འབྱེད་སྒྲག་ཆས་ཀྱི་à½�་ལོ་བའི་ཚོད་འཛིན་ཡོ་བྱད་ ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ á ¢ ᠢᠯᠭᠠᠨ ᠲᠠᠨᠢᠬᠤ ᠲᠥᠬᠥᠭᠡᠷᠦᠮᠵᠢ ᠪᠡᠷ ᠬᠥᠳᠡᠯᠭᠡᠭᠦᠷ ᠪᠣᠯᠭᠠᠬᠤ ᠡᠵᠡᠮᠳᠡᠯ ᠦᠨ ᠪᠠᠭᠠᠵᠢ á ¶á ¢ ᠠᠵᠢᠯᠯᠠᠭᠤᠯᠤᠨ᠎ᠠ á ƒ é�‹è¡Œç”Ÿç‰©è­˜åˆ¥è¨­å‚™é©…動控制工具 بىئولوگىيەلىك پەرقلەندۈرۈش ئۈسكۈنىسىنى قوزغىتىش كونترول قىلىش ئەسۋابىنى يۈرگۈزۈش شايمانىن جۉرگۅزۉ شايمانىن جۉرگۅزۉ Authentication is required to change the status of biometric device's driver 改å�˜ç”Ÿç‰©è¯†åˆ«è®¾å¤‡é©±åŠ¨çŠ¶æ€�需è¦�进行身份验è¯� སà¾�ྱ་དངོས་དབྱེ་འབྱེད་སྒྲག་ཆས་ཀྱི་à½�་ལོ་བའི་གནས་ཚུལ་ལ་འགྱུར་ལྡོག་གà½�ོང་བར་བདེན་དཔང་ར་སྤྲད་བྱ་དགོསà¼� ᠠᠮᠢᠳᠤ ᠪᠣᠳᠠᠰ á ¢ ᠢᠯᠭᠠᠨ ᠲᠠᠨᠢᠬᠤ ᠲᠥᠬᠥᠭᠡᠷᠦᠮᠵᠢ ᠶᠢᠨ ᠬᠥᠳᠡᠯᠭᠡᠭᠦᠷ ᠪᠣᠯᠭᠠᠬᠤ ᠪᠠᠶᠢᠳᠠᠯ á ¢ ᠬᠤᠪᠢᠷᠠᠭᠤᠯᠬᠤ ᠳᠤ ᠪᠡᠶ᠎ᠡ ᠶᠢᠨ ᠭᠠᠷᠤᠯ ᠤᠨ ᠭᠡᠷᠡᠴᠢᠯᠡᠯ ᠬᠢᠬᠦ ᠴᠢᠬᠤᠯᠠ ᠲᠠᠶ ᠪᠠᠶᠢᠬᠤ ᠬᠡᠷᠡᠭᠲᠡᠶ᠃ 改變生物識別設備驅動狀態需è¦�進行身份驗證 بىئولوگىيەلىك پەرقلەندۈرۈش ئۈسكۈنىسىنىڭ قوزغىتىش ھالىتىنى ئۆزگەرتىشتە دەلىللەش ÙƒÛ�رەك بىئولوگىيەلىك پارىقتاندىرۋ اسپابىنىڭ قوزعالتۋ كۇيىن وزگەتۋگە دالەلدەۋ كەرەك بىئولوگىيەلىك ايىرمالاندىرىش شايمانىنىن قوزعوتۇۇ ابالىن ۅزگۅرتۉۉدۅ دالىلدۅ كەرەك stock_person auth_admin auth_admin auth_admin_keep ${SCRIPTS_INSTALL_PATH}/biodrvctl ukui-biometric-auth/tests/0000775000175000017500000000000015167732644014550 5ustar fengfengukui-biometric-auth/tests/unit_test_keywatcher/0000775000175000017500000000000015167732644021014 5ustar fengfengukui-biometric-auth/tests/unit_test_keywatcher/CMakeLists.txt0000664000175000017500000000315515167732630023553 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets Test REQUIRED) find_package(PkgConfig REQUIRED) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../bioauth-bin/src/keywatcher.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../bioauth-bin/src/keywatcher.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_keywatcher ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_keywatcher Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets Qt5::Test ) # 链接 GTest 库 target_link_libraries(unit_test_keywatcher GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_keywatcher/main.cpp0000664000175000017500000000435715167732644022455 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include "../../bioauth-bin/src/keywatcher.h" class KeyWatcherTest : public ::testing::Test { protected: void SetUp() override { watcher = new KeyWatcher(nullptr); } void TearDown() override { delete watcher; } KeyWatcher* watcher; int argc = 0; char** argv = nullptr; }; TEST_F(KeyWatcherTest, ConstructionAndDestruction) { // Verify that the KeyWatcher object can be constructed and destroyed without crashing. EXPECT_TRUE(watcher != nullptr); } TEST_F(KeyWatcherTest, EmitExitSignal) { // This test is tricky because it depends on terminal I/O. // We can use a signal spy to detect the exit signal. //QSignalSpy spy(watcher, &KeyWatcher::exit); // Normally, we would need to run the KeyWatcher thread and simulate input. // However, for simplicity, we will just call stop() which should trigger the cleanup code. //watcher->stop(); // Note: This is not a complete test of the run() method, just a check for signal emission. // A proper test would require simulating terminal input and output. //EXPECT_EQ(spy.count(), 1); } // Additional tests could be added here to test other parts of the KeyWatcher class. // For example, testing the behavior of the run() method with different inputs would require // setting up a mock terminal or using some form of input redirection. int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); QCoreApplication app(argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_biodeviceinfo/0000775000175000017500000000000015167732644021453 5ustar fengfengukui-biometric-auth/tests/unit_test_biodeviceinfo/CMakeLists.txt0000664000175000017500000000313015167732630024203 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus REQUIRED) find_package(PkgConfig REQUIRED) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../uniauth-backend/src/biodeviceinfo.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../uniauth-backend/src/biodeviceinfo.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_biodeviceinfo ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_biodeviceinfo Qt5::Core Qt5::Gui Qt5::DBus ) # 链接 GTest 库 target_link_libraries(unit_test_biodeviceinfo GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_biodeviceinfo/main.cpp0000664000175000017500000000453015167732644023105 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "../../uniauth-backend/src/biodeviceinfo.h" #include #include // gtest 测试用例 TEST(BioDeviceInfoTest, SerializationAndDeserialization) { registerCustomTypes(); DeviceInfo original; original.device_id = 1; original.device_shortname = "TestDevice"; original.device_fullname = "Test Device Full Name"; original.driver_enable = 1; original.device_available = 1; original.biotype = BIOTYPE_FINGERPRINT; original.stotype = 0; original.eigtype = 0; original.vertype = 0; original.idtype = 0; original.bustype = 0; original.dev_status = 0; original.ops_status = 0; QDBusArgument argument; argument<> deserialized; EXPECT_EQ(original.device_id, deserialized.device_id); EXPECT_EQ(original.device_shortname, deserialized.device_shortname); EXPECT_EQ(original.device_fullname, deserialized.device_fullname); EXPECT_EQ(original.driver_enable, deserialized.driver_enable); EXPECT_EQ(original.device_available, deserialized.device_available); EXPECT_EQ(original.biotype, deserialized.biotype); EXPECT_EQ(original.stotype, deserialized.stotype); EXPECT_EQ(original.eigtype, deserialized.eigtype); EXPECT_EQ(original.vertype, deserialized.vertype); EXPECT_EQ(original.idtype, deserialized.idtype); EXPECT_EQ(original.bustype, deserialized.bustype); EXPECT_EQ(original.dev_status, deserialized.dev_status); EXPECT_EQ(original.ops_status, deserialized.ops_status); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_kalabel/0000775000175000017500000000000015167732644020241 5ustar fengfengukui-biometric-auth/tests/unit_test_kalabel/CMakeLists.txt0000664000175000017500000000311515167732630022774 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../polkit-agent/src/kalabel.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../polkit-agent/src/kalabel.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_kalabel ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_kalabel Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ) # 链接 GTest 库 target_link_libraries(unit_test_kalabel GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_kalabel/main.cpp0000664000175000017500000000663215167732644021700 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "../../polkit-agent/src/kalabel.h" #include #include #include // 辅助函数,用于创建QFontMetrics对象,é�¿å…�在测试中é‡�å¤�代ç � QFontMetrics createFontMetrics(const QFont& font) { return QFontMetrics(font); } // 测试getElidedText方法是å�¦æ­£ç¡®åœ°çœ�略了文本 TEST(KALabelTest, GetElidedText_ShouldElideTextIfWidthIsExceeded) { // 创建一个QFont对象,并设置其属性(这里使用默认属性) QFont font; QFontMetrics fontMetrics = createFontMetrics(font); // 设置测试字符串和宽度 QString testString = "This is a very long text that needs to be elided."; #if QT_VERSION_MAJOR == 6 int width = fontMetrics.horizontalAdvance("This is a short text."); // å�‡è®¾è¿™ä¸ªå®½åº¦æ˜¯å�ˆé€‚的测试宽度 #else int width = fontMetrics.width("This is a short text."); // å�‡è®¾è¿™ä¸ªå®½åº¦æ˜¯å�ˆé€‚的测试宽度 #endif // 创建KALabel对象(仅为了访问其getElidedText方法) KALabel kalabel; // 调用getElidedText方法 QString elidedText = kalabel.getElidedText(font, width, testString); // 检查文本是å�¦è¢«çœ�ç•¥ EXPECT_TRUE(elidedText.endsWith("...")); #if QT_VERSION_MAJOR == 6 EXPECT_LT(fontMetrics.horizontalAdvance(elidedText), width); #else EXPECT_LT(fontMetrics.width(elidedText), width); #endif } // 测试getElidedText方法在没有超过宽度时是å�¦è¿”回原始文本 TEST(KALabelTest, GetElidedText_ShouldNotElideTextIfWidthIsNotExceeded) { // 创建一个QFont对象,并设置其属性(这里使用默认属性) QFont font; QFontMetrics fontMetrics = createFontMetrics(font); // 设置测试字符串和宽度(确ä¿�宽度足够大以容纳整个字符串) QString testString = "Short text"; #if QT_VERSION_MAJOR == 6 int width = fontMetrics.horizontalAdvance(testString) + 10; // 加一些é¢�外的宽度以确ä¿�ä¸�会çœ�ç•¥ #else int width = fontMetrics.width(testString) + 10; // 加一些é¢�外的宽度以确ä¿�ä¸�会çœ�ç•¥ #endif // 创建KALabel对象(仅为了访问其getElidedText方法) KALabel kalabel; // 调用getElidedText方法 QString elidedText = kalabel.getElidedText(font, width, testString); // 检查文本是å�¦æœªè¢«çœ�ç•¥ EXPECT_EQ(elidedText, testString); } TEST(KALabelTest, ShowTest) { KALabel kalabel; KALabel kalabel1("test"); kalabel1.setText("test1"); kalabel1.setFixedWidth(80); kalabel1.paintEvent(nullptr); kalabel1.setText("long long long long long test text"); kalabel1.paintEvent(nullptr); } int main(int argc, char **argv) { QApplication a(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_rsac/0000775000175000017500000000000015167732644017576 5ustar fengfengukui-biometric-auth/tests/unit_test_rsac/CMakeLists.txt0000664000175000017500000000321515167732630022332 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus REQUIRED) find_package(PkgConfig REQUIRED) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../uniauth-backend/src/rsac.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../uniauth-backend/src/rsac.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ${CMAKE_CURRENT_SOURCE_DIR}/../../uniauth-backend/src/ ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_rsac ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_rsac Qt5::Core Qt5::Gui Qt5::DBus ) # 链接 GTest 库 target_link_libraries(unit_test_rsac GTest::GTest GTest::Main Threads::Threads ${GIOUNIX2_LIBRARIES} -lcrypto ) ukui-biometric-auth/tests/unit_test_rsac/main.cpp0000664000175000017500000000715515167732644021236 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "../../uniauth-backend/src/rsac.h" #include #include #include #include #include #include #include // 辅助函数,用于åˆ�始化OpenSSL库 void InitOpenSSL() { OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); } // 辅助函数,用于清ç�†OpenSSL库 void CleanupOpenSSL() { EVP_cleanup(); ERR_free_strings(); } // 测试类 class RSACTest : public ::testing::Test { protected: void SetUp() override { InitOpenSSL(); } void TearDown() override { CleanupOpenSSL(); } RSAC rsac; }; // 测试密钥生æˆ�å¹¶ä¿�存到文件 TEST_F(RSACTest, GenerateKeyPairToFile) { QString priKeyFile = "test_private.pem"; QString pubKeyFile = "test_public.pem"; rsac.generateKeyPair(priKeyFile, pubKeyFile, 1024); // 这里å�¯ä»¥æ·»åŠ é¢�外的检查æ�¥éªŒè¯�文件是å�¦æˆ�功生æˆ�且内容有效 // 例如,打开文件并读å�–内容,检查是å�¦ä¸ºæœ‰æ•ˆçš„PEMæ ¼å¼�密钥 // 但由于这是一个简å�•的测试示例,我们çœ�略了这些步骤 } // 测试密钥生æˆ�å¹¶ä¿�存到QByteArray TEST_F(RSACTest, GenerateKeyPairToByteArray) { QByteArray privateKey; QByteArray publicKey; rsac.generateKeyPair(privateKey, publicKey, 1024); // 检查生æˆ�的密钥是å�¦é�žç©º EXPECT_FALSE(privateKey.isEmpty()); EXPECT_FALSE(publicKey.isEmpty()); // 这里å�¯ä»¥æ·»åŠ é¢�外的检查æ�¥éªŒè¯�密钥的有效性 // 例如,使用OpenSSL函数解æž�生æˆ�的密钥并检查其属性 // 但由于这是一个简å�•的测试示例,我们çœ�略了这些步骤 } // 测试加密和解密 TEST_F(RSACTest, EncryptDecrypt) { QByteArray privateKey; QByteArray publicKey; rsac.generateKeyPair(privateKey, publicKey, 1024); QByteArray plaintext = "Hello, RSA!"; QByteArray ciphertext; QByteArray decryptedtext; bool encryptResult = rsac.encrypt(plaintext, ciphertext, publicKey); EXPECT_TRUE(encryptResult); bool decryptResult = rsac.decrypt(ciphertext, decryptedtext, privateKey); EXPECT_TRUE(decryptResult); EXPECT_EQ(plaintext, decryptedtext); } // 测试签å��和验签 TEST_F(RSACTest, SignVerify) { QByteArray privateKey; QByteArray publicKey; rsac.generateKeyPair(privateKey, publicKey, 1024); QByteArray message = "This is a test message."; QByteArray signature; bool signResult = rsac.sign(message, signature, privateKey); EXPECT_TRUE(signResult); bool verifyResult = rsac.verify(message, signature, publicKey); EXPECT_TRUE(verifyResult); // å°�试使用错误的消æ�¯è¿›è¡ŒéªŒç­¾ï¼Œåº”该失败 bool verifyWithWrongMessageResult = rsac.verify("Wrong message.", signature, publicKey); EXPECT_FALSE(verifyWithWrongMessageResult); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_giodbus/0000775000175000017500000000000015167732644020302 5ustar fengfengukui-biometric-auth/tests/unit_test_giodbus/CMakeLists.txt0000664000175000017500000000343515167732630023042 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../bioauth/src/giodbus.cpp unit_test_giodbus.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../bioauth/include/giodbus.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ${CMAKE_CURRENT_SOURCE_DIR}/../../bioauth/include/ ${GIOUNIX2_INCLUDE_DIRS} ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_giodbus ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_giodbus Qt5::Core Qt5::Gui Qt5::DBus ) # 链接 GTest 库 target_link_libraries(unit_test_giodbus GTest::GTest GTest::Main Threads::Threads ${GIOUNIX2_LIBRARIES} ) ukui-biometric-auth/tests/unit_test_giodbus/main.cpp0000664000175000017500000000156115167732644021735 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include int main(int argc, char **argv) { QGuiApplication a(argc, argv); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_giodbus/unit_test_giodbus.cpp0000664000175000017500000000202415167732644024536 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include "../../bioauth/include/giodbus.h" #include "stubext.h" using namespace stub_ext; class FreedesktopHelperTest : public testing::Test { protected: }; TEST_F(FreedesktopHelperTest, get_server_gvariant_stdout) { int value = get_server_gvariant_stdout(-1); ASSERT_EQ(value, -1); } ukui-biometric-auth/tests/CMakeLists.txt0000664000175000017500000000275315167732630017312 0ustar fengfengadd_subdirectory(unit_test_giodbus) add_subdirectory(unit_test_biodeviceinfo) add_subdirectory(unit_test_kalabel) add_subdirectory(unit_test_rsac) add_subdirectory(unit_test_pam_tally) add_subdirectory(unit_test_common) add_subdirectory(unit_test_loginoptionswidget) add_subdirectory(unit_test_keywatcher) add_subdirectory(unit_test_personalizeddata) add_subdirectory(unit_test_modebutton) add_subdirectory(unit_test_users) add_subdirectory(unit_test_biodevices) add_subdirectory(unit_test_usdblockshortcut) add_subdirectory(unit_test_sessionmanager) add_subdirectory(unit_test_servicemanager) # 处ç�†æ‰“桩工具相关é…�ç½® set(TEST_UTILS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/kt-test-utils") # 收集打桩工具的头文件,递归查找符å�ˆæ�¡ä»¶çš„头文件 file(GLOB_RECURSE UTILS_HEADERS "${TEST_UTILS_PATH}/cpp-stub/*.h" "${TEST_UTILS_PATH}/cpp-stub/*.hpp" "${TEST_UTILS_PATH}/cpp-stub-ext/*.h" ) # 收集打桩工具的æº�文件,递归查找符å�ˆæ�¡ä»¶çš„æº�文件 file(GLOB_RECURSE UTILS_SOURCES "${TEST_UTILS_PATH}/cpp-stub/*.cpp" "${TEST_UTILS_PATH}/cpp-stub-ext/*.cpp" ) # 创建一个库(这里以é�™æ€�库为例,å�¯ä»¥æ ¹æ�®éœ€æ±‚改为共享库等)æ�¥å­˜æ”¾æ‰“桩工具相关代ç � add_library(utils_lib STATIC ${UTILS_SOURCES} ${UTILS_HEADERS}) # 将打桩工具库的头文件目录添加到包å�«è·¯å¾„,方便其他目标使用 target_include_directories(utils_lib PUBLIC "${TEST_UTILS_PATH}/cpp-stub" "${TEST_UTILS_PATH}/cpp-stub-ext" ) ukui-biometric-auth/tests/unit_test_personalizeddata/0000775000175000017500000000000015167732644022177 5ustar fengfengukui-biometric-auth/tests/unit_test_personalizeddata/CMakeLists.txt0000664000175000017500000000350515167732630024735 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus REQUIRED) find_package(PkgConfig REQUIRED) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) pkg_check_modules(LIGHTDM-QT5-3 REQUIRED liblightdm-qt5-3) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../uniauth-backend/src/personalizeddata.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../uniauth-backend/src/personalizeddata.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ${CMAKE_CURRENT_SOURCE_DIR}/../../uniauth-backend/src/ ${LIGHTDM-QT5-3_INCLUDE_DIRS} ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_personalizeddata ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_personalizeddata Qt5::Core Qt5::Gui Qt5::DBus ) # 链接 GTest 库 target_link_libraries(unit_test_personalizeddata GTest::GTest GTest::Main Threads::Threads ${GIOUNIX2_LIBRARIES} -lcrypto ${LIGHTDM-QT5-3_LIBRARIES} ) ukui-biometric-auth/tests/unit_test_personalizeddata/main.cpp0000664000175000017500000000772715167732644023644 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include "../../uniauth-backend/src/personalizeddata.h" // Global instance for testing PersonalizedDataMng* g_personalizedDataMng = nullptr; // Test case for PersonalizedData TEST(PersonalizedDataTest, GetJsonData) { // Create a PersonalizedData instance PersonalizedData pd("testuser"); // Set some values (using direct access for simplicity in this test) pd.dateType("yyyy-MM-dd"); pd.fontSize(12); pd.timeType(24); pd.backgroundPath("/path/to/background"); pd.color("#FFFFFF"); pd.cursor_size(10); pd.cursor_theme(""); pd.scaling_factor(1); // Get JSON data QJsonObject json; pd.getJsonData(json); // Verify JSON data EXPECT_EQ(json["user"].toString(), "testuser"); EXPECT_EQ(json["dateType"].toString(), "yyyy-MM-dd"); EXPECT_EQ(json["fontSize"].toInt(), 12); EXPECT_EQ(json["timeType"].toInt(), 24); EXPECT_EQ(json["backgroundPath"].toString(), "/path/to/background"); EXPECT_EQ(json["color"].toString(), "#FFFFFF"); pd.dateType(); pd.fontSize(); pd.timeType(); pd.backgroundPath(); pd.color(); pd.cursor_size(); pd.cursor_theme(); pd.scaling_factor(); pd.getJsonData(); pd.fileChanged(""); pd.__load_conf_usd_conf(); pd.__copy_file("/usr/share/backgrounds/1-openkylin.jpg"); pd.__copy_file(""); } // Test case for PersonalizedDataMng TEST(PersonalizedDataMngTest, GetConfInformation) { // Initialize PersonalizedDataMng with mock dependencies if needed if (!g_personalizedDataMng) { g_personalizedDataMng = new PersonalizedDataMng(); // Mock QLightDM::UsersModel and other dependencies if necessary } // Add a user to the model (simulating onUserAdded) QString userName = "testuser"; PersonalizedData* pd = new PersonalizedData(userName); QJsonObject json; pd->getJsonData(json); json["operation"] = "testoperation"; QJsonDocument document; document.setObject(json); QString jsonStr = document.toJson(QJsonDocument::Compact); // Emit the conf_changed signal (simulating onUserAdded) emit g_personalizedDataMng->conf_changed(jsonStr); // Retrieve configuration information QString confInfo = g_personalizedDataMng->GetConfInformation(userName); // Verify configuration information (parse JSON and check values) QJsonDocument confDoc = QJsonDocument::fromJson(confInfo.toUtf8()); QJsonObject confJson = confDoc.object(); EXPECT_EQ(confJson["user"].toString(), userName); // EXPECT_EQ(confJson["operation"].toInt(), "testoperation"); EXPECT_EQ(confJson["dateType"].toString(), "cn"); // Default value from PersonalizedData // Add more verifications as needed g_personalizedDataMng->SetLoginSynInformation(""); g_personalizedDataMng->GetConfInformation("kylin"); g_personalizedDataMng->GetConfInformation("lightdm"); g_personalizedDataMng->GetConfInformation(""); QModelIndex index; g_personalizedDataMng->onUserAdded(index,0,0); g_personalizedDataMng->onUserRemoved(index,0,0); delete g_personalizedDataMng; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_usdblockshortcut/0000775000175000017500000000000015167732644022250 5ustar fengfengukui-biometric-auth/tests/unit_test_usdblockshortcut/CMakeLists.txt0000664000175000017500000000317215167732631025007 0ustar fengfeng# CMake 最低版本è¦�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) # 包å�« GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # å¼€å�¯ä»£ç �覆盖率相关编译选项(对应QMAKE_LFLAGSå’ŒQMAKE_CXXFLAGS中代ç �覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义æº�文件列表,对应原æ�¥çš„SOURCESå�˜é‡� set(SOURCES ../../polkit-agent/src/usdblockshortcut.cpp main.cpp ) # 定义头文件列表,对应原æ�¥çš„HEADERSå�˜é‡� set(HEADERS ../../polkit-agent/src/usdblockshortcut.h ) # 包å�«å¤´æ–‡ä»¶çš„路径设置,对应原æ�¥çš„INCLUDEPATHå�˜é‡� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生æˆ�元对象代ç �相关的æº�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加å�¯æ‰§è¡Œæ–‡ä»¶æˆ–库目标,将元对象代ç �æº�文件一起添加进去 add_executable(unit_test_usdblockshortcut ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_usdblockshortcut Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ) # 链接 GTest 库 target_link_libraries(unit_test_usdblockshortcut GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_usdblockshortcut/main.cpp0000664000175000017500000000300515167732644023676 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ // usdblockshortcut_test.cpp #include #include #include #include #include #include #include #include "../../polkit-agent/src/usdblockshortcut.h" // Test fixture for SessionManager class USDBlockShortCutTest : public ::testing::Test { protected: void SetUp() override { usdblockShortCut = new USDBlockShortCut(); } void TearDown() override { delete usdblockShortCut; } USDBlockShortCut *usdblockShortCut; }; TEST_F(USDBlockShortCutTest, testUSDBlockShortCutTest) { EXPECT_TRUE(usdblockShortCut != nullptr); usdblockShortCut->blockShortcuts(); } int main(int argc, char **argv) { QCoreApplication app(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/kt-test-utils/0000775000175000017500000000000015167732630017274 5ustar fengfengukui-biometric-auth/tests/kt-test-utils/cpp-stub/0000775000175000017500000000000015167732644021036 5ustar fengfengukui-biometric-auth/tests/kt-test-utils/cpp-stub/addr_pri.h0000664000175000017500000002436415167732630022777 0ustar fengfeng#ifndef __ADDR_PRI_H__ #define __ADDR_PRI_H__ #include #include //base on C++11 /********************************************************** access private function **********************************************************/ namespace std { template using enable_if_t = typename enable_if::type; template using remove_reference_t = typename remove_reference::type; } // std // Unnamed namespace is used to avoid duplicate symbols if the macros are used namespace { namespace private_access_detail { // @tparam TagType, used to declare different "get" funciton overloads for // different members/statics template struct private_access { // Normal lookup cannot find in-class defined (inline) friend functions. friend PtrType get(TagType) { return PtrValue; } }; } // namespace private_access_detail } // namespace // Used macro naming conventions: // The "namespace" of this macro library is PRIVATE_ACCESS, i.e. all // macro here has this prefix. // All implementation macro, which are not meant to be used directly have the // PRIVATE_ACCESS_DETAIL prefix. // Some macros have the ABCD_IMPL form, which means they contain the // implementation details for the specific ABCD macro. #define PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y) x##y #define PRIVATE_ACCESS_DETAIL_CONCATENATE(x, y) \ PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y) // @param PtrTypeKind E.g if we have "class A", then it can be "A::*" in case of // members, or it can be "*" in case of statics. #define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, \ PtrTypeKind) \ namespace { \ namespace private_access_detail { \ /* Tag type, used to declare different get funcitons for different \ * members \ */ \ struct Tag {}; \ /* Explicit instantiation */ \ template struct private_access; \ /* We can build the PtrType only with two aliases */ \ /* E.g. using PtrType = int(int) *; would be illformed */ \ using PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) = Type; \ using PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) = \ PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) PtrTypeKind; \ /* Declare the friend function, now it is visible in namespace scope. \ * Note, \ * we could declare it inside the Tag type too, in that case ADL would \ * find \ * the declaration. By choosing to declare it here, the Tag type remains \ * a \ * simple tag type, it has no other responsibilities. */ \ PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) get(Tag); \ } \ } #define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(Tag, Class, Type, Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \ namespace { \ namespace access_private_field { \ Type &Class##Name(Class &&t) { return t.*get(private_access_detail::Tag{}); } \ Type &Class##Name(Class &t) { return t.*get(private_access_detail::Tag{}); } \ /* The following usings are here to avoid duplicate const qualifier \ * warnings \ */ \ using PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag) = Type; \ using PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) = \ const PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag); \ PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) & Class##Name(const Class &t) {\ return t.*get(private_access_detail::Tag{}); \ } \ } \ } #define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(Tag, Class, Type, Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \ namespace { \ namespace call_private_fun { \ /* We do perfect forwarding, but we want to restrict the overload set \ * only for objects which have the type Class. */ \ template , \ Class>::value> * = nullptr, \ typename... Args> \ auto Class##Name(Obj &&o, Args &&... args) -> decltype( \ (std::forward(o).* \ get(private_access_detail::Tag{}))(std::forward(args)...)) { \ return (std::forward(o).*get(private_access_detail::Tag{}))( \ std::forward(args)...); \ } \ } \ namespace get_private_fun { \ auto Class##Name() -> decltype( \ get(private_access_detail::Tag{})) { \ return (get(private_access_detail::Tag{})); \ } \ } \ } #define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD(Tag, Class, Type, \ Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \ namespace { \ namespace access_private_static_field { \ namespace Class { \ Type &Class##Name() { return *get(private_access_detail::Tag{}); } \ } \ } \ } #define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN(Tag, Class, Type, \ Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \ namespace { \ namespace call_private_static_fun { \ namespace Class { \ template \ auto Class##Name(Args &&... args) -> decltype( \ get(private_access_detail::Tag{})(std::forward(args)...)) { \ return get(private_access_detail::Tag{})( \ std::forward(args)...); \ } \ } \ } \ namespace get_private_static_fun { \ namespace Class { \ auto Class##Name() -> decltype(get(private_access_detail::Tag{})) { \ return get(private_access_detail::Tag{}); \ } \ } \ } \ } #define PRIVATE_ACCESS_DETAIL_UNIQUE_TAG \ PRIVATE_ACCESS_DETAIL_CONCATENATE(PrivateAccessTag, __COUNTER__) #define ACCESS_PRIVATE_FIELD(Class, Type, Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \ Class, Type, Name) #define ACCESS_PRIVATE_FUN(Class, Type, Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \ Class, Type, Name) #define ACCESS_PRIVATE_STATIC_FIELD(Class, Type, Name) \ Type Class::Name; \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD( \ PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name) #define ACCESS_PRIVATE_STATIC_FUN(Class, Type, Name) \ PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN( \ PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name) #endif ukui-biometric-auth/tests/kt-test-utils/cpp-stub/addr_any.h0000664000175000017500000002113415167732630022764 0ustar fengfeng#ifndef __ADDR_ANY_H__ #define __ADDR_ANY_H__ //linux #include #include //c #include #include #include //c++ #include #include //project #include "elfio.hpp" class AddrAny { public: AddrAny() { m_init = get_exe_pathname(m_fullname); m_baseaddr = 0; } AddrAny(std::string libname) { m_init = get_lib_pathname_and_baseaddr(libname, m_fullname, m_baseaddr); } int get_local_func_addr_symtab(std::string func_name_regex_str, std::map& result) { return get_func_addr(SHT_SYMTAB, STB_LOCAL, func_name_regex_str, result); } int get_global_func_addr_symtab(std::string func_name_regex_str, std::map& result) { return get_func_addr(SHT_SYMTAB, STB_GLOBAL, func_name_regex_str, result); } int get_weak_func_addr_symtab(std::string func_name_regex_str, std::map& result) { return get_func_addr(SHT_SYMTAB, STB_WEAK, func_name_regex_str, result); } int get_global_func_addr_dynsym( std::string func_name_regex_str, std::map& result) { return get_func_addr(SHT_DYNSYM, STB_GLOBAL, func_name_regex_str, result); } int get_weak_func_addr_dynsym(std::string func_name_regex_str, std::map& result) { return get_func_addr(SHT_DYNSYM, STB_WEAK, func_name_regex_str, result); } private: bool demangle(std::string& s, std::string& name) { int status; char* pname = abi::__cxa_demangle(s.c_str(), 0, 0, &status); if (status != 0) { switch(status) { case -1: name = "memory allocation error"; break; case -2: name = "invalid name given"; break; case -3: name = "internal error: __cxa_demangle: invalid argument"; break; default: name = "unknown error occured"; break; } return false; } name = pname; free(pname); return true; } bool get_exe_pathname( std::string& name) { char line[512]; FILE *fp; uintptr_t base_addr; char perm[5]; unsigned long offset; int pathname_pos; char *pathname; size_t pathname_len; int match = 0; if(NULL == (fp = fopen("/proc/self/maps", "r"))) { return false; } while(fgets(line, sizeof(line), fp)) { if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue; if(0 != offset) continue; //get pathname while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1)) pathname_pos += 1; if(pathname_pos >= (int)(sizeof(line) - 1)) continue; pathname = line + pathname_pos; pathname_len = strlen(pathname); if(0 == pathname_len) continue; if(pathname[pathname_len - 1] == '\n') { pathname[pathname_len - 1] = '\0'; pathname_len -= 1; } if(0 == pathname_len) continue; if('[' == pathname[0]) continue; name = pathname; match = 1; break; } fclose(fp); if(0 == match) { return false; } else { return true; } } bool get_lib_pathname_and_baseaddr(std::string pathname_regex_str, std::string& name, unsigned long& addr) { char line[512]; FILE *fp; uintptr_t base_addr; char perm[5]; unsigned long offset; int pathname_pos; char *pathname; size_t pathname_len; int match; regex_t pathname_regex; regcomp(&pathname_regex, pathname_regex_str.c_str(), 0); if(NULL == (fp = fopen("/proc/self/maps", "r"))) { return false; } while(fgets(line, sizeof(line), fp)) { if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue; //check permission if(perm[0] != 'r') continue; if(perm[3] != 'p') continue; //do not touch the shared memory //check offset // //We are trying to find ELF header in memory. //It can only be found at the beginning of a mapped memory regions //whose offset is 0. if(0 != offset) continue; //get pathname while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1)) pathname_pos += 1; if(pathname_pos >= (int)(sizeof(line) - 1)) continue; pathname = line + pathname_pos; pathname_len = strlen(pathname); if(0 == pathname_len) continue; if(pathname[pathname_len - 1] == '\n') { pathname[pathname_len - 1] = '\0'; pathname_len -= 1; } if(0 == pathname_len) continue; if('[' == pathname[0]) continue; //check pathname //if we need to hook this elf? match = 0; if(0 == regexec(&pathname_regex, pathname, 0, NULL, 0)) { match = 1; name = pathname; addr = (unsigned long)base_addr; break; } if(0 == match) continue; } fclose(fp); if(0 == match) { return false; } else { return true; } } int get_func_addr(unsigned int ttype, unsigned int stype, std::string& func_name_regex_str, std::map& result) { // Create an elfio reader ELFIO::elfio reader; int count = 0; regex_t pathname_regex; if(!m_init) { return -1; } regcomp(&pathname_regex, func_name_regex_str.c_str(), 0); // Load ELF data if(!reader.load(m_fullname.c_str())) { return -1; } ELFIO::Elf_Half sec_num = reader.sections.size(); for(int i = 0; i < sec_num; ++i) { ELFIO::section* psec = reader.sections[i]; // Check section type if(psec->get_type() == ttype) { const ELFIO::symbol_section_accessor symbols( reader, psec ); for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j ) { std::string name; std::string name_mangle; ELFIO::Elf64_Addr value; ELFIO::Elf_Xword size; unsigned char bind; unsigned char type; ELFIO::Elf_Half section_index; unsigned char other; // Read symbol properties symbols.get_symbol( j, name, value, size, bind, type, section_index, other ); if(type == STT_FUNC && bind == stype) { bool ret = demangle(name,name_mangle); if(ret == true) { if (0 == regexec(&pathname_regex, name_mangle.c_str(), 0, NULL, 0)) { result.insert ( std::pair(name_mangle,(void*)(value + m_baseaddr))); count++; } } else { if (0 == regexec(&pathname_regex, name.c_str(), 0, NULL, 0)) { result.insert ( std::pair(name,(void*)(value + m_baseaddr))); count++; } } } } break; } } return count; } private: bool m_init; std::string m_name; std::string m_fullname; unsigned long m_baseaddr; }; #endif ukui-biometric-auth/tests/kt-test-utils/cpp-stub/elfio.hpp0000664000175000017500000045310415167732630022647 0ustar fengfeng /*** Start of inlined file: elfio_dump.hpp ***/ #ifndef ELFIO_DUMP_HPP #define ELFIO_DUMP_HPP #include #include #include #include #include /*** Start of inlined file: elfio.hpp ***/ #ifndef ELFIO_HPP #define ELFIO_HPP #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4996 ) #pragma warning( disable : 4355 ) #pragma warning( disable : 4244 ) #endif #include #include #include #include #include #include #include #include /*** Start of inlined file: elf_types.hpp ***/ #ifndef ELFTYPES_H #define ELFTYPES_H #ifndef ELFIO_NO_OWN_TYPES #if !defined( ELFIO_NO_CSTDINT ) && !defined( ELFIO_NO_INTTYPES ) #include #else typedef unsigned char uint8_t; typedef signed char int8_t; typedef unsigned short uint16_t; typedef signed short int16_t; #ifdef _MSC_VER typedef unsigned __int32 uint32_t; typedef signed __int32 int32_t; typedef unsigned __int64 uint64_t; typedef signed __int64 int64_t; #else typedef unsigned int uint32_t; typedef signed int int32_t; typedef unsigned long long uint64_t; typedef signed long long int64_t; #endif // _MSC_VER #endif // ELFIO_NO_CSTDINT #endif // ELFIO_NO_OWN_TYPES namespace ELFIO { // Attention! Platform depended definitions. typedef uint16_t Elf_Half; typedef uint32_t Elf_Word; typedef int32_t Elf_Sword; typedef uint64_t Elf_Xword; typedef int64_t Elf_Sxword; typedef uint32_t Elf32_Addr; typedef uint32_t Elf32_Off; typedef uint64_t Elf64_Addr; typedef uint64_t Elf64_Off; #define Elf32_Half Elf_Half #define Elf64_Half Elf_Half #define Elf32_Word Elf_Word #define Elf64_Word Elf_Word #define Elf32_Sword Elf_Sword #define Elf64_Sword Elf_Sword /////////////////////// // ELF Header Constants // File type #define ET_NONE 0 #define ET_REL 1 #define ET_EXEC 2 #define ET_DYN 3 #define ET_CORE 4 #define ET_LOOS 0xFE00 #define ET_HIOS 0xFEFF #define ET_LOPROC 0xFF00 #define ET_HIPROC 0xFFFF #define EM_NONE 0 // No machine #define EM_M32 1 // AT&T WE 32100 #define EM_SPARC 2 // SUN SPARC #define EM_386 3 // Intel 80386 #define EM_68K 4 // Motorola m68k family #define EM_88K 5 // Motorola m88k family #define EM_486 6 // Intel 80486// Reserved for future use #define EM_860 7 // Intel 80860 #define EM_MIPS 8 // MIPS R3000 (officially, big-endian only) #define EM_S370 9 // IBM System/370 #define EM_MIPS_RS3_LE \ 10 // MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated #define EM_res011 11 // Reserved #define EM_res012 12 // Reserved #define EM_res013 13 // Reserved #define EM_res014 14 // Reserved #define EM_PARISC 15 // HPPA #define EM_res016 16 // Reserved #define EM_VPP550 17 // Fujitsu VPP500 #define EM_SPARC32PLUS 18 // Sun's "v8plus" #define EM_960 19 // Intel 80960 #define EM_PPC 20 // PowerPC #define EM_PPC64 21 // 64-bit PowerPC #define EM_S390 22 // IBM S/390 #define EM_SPU 23 // Sony/Toshiba/IBM SPU #define EM_res024 24 // Reserved #define EM_res025 25 // Reserved #define EM_res026 26 // Reserved #define EM_res027 27 // Reserved #define EM_res028 28 // Reserved #define EM_res029 29 // Reserved #define EM_res030 30 // Reserved #define EM_res031 31 // Reserved #define EM_res032 32 // Reserved #define EM_res033 33 // Reserved #define EM_res034 34 // Reserved #define EM_res035 35 // Reserved #define EM_V800 36 // NEC V800 series #define EM_FR20 37 // Fujitsu FR20 #define EM_RH32 38 // TRW RH32 #define EM_MCORE 39 // Motorola M*Core // May also be taken by Fujitsu MMA #define EM_RCE 39 // Old name for MCore #define EM_ARM 40 // ARM #define EM_OLD_ALPHA 41 // Digital Alpha #define EM_SH 42 // Renesas (formerly Hitachi) / SuperH SH #define EM_SPARCV9 43 // SPARC v9 64-bit #define EM_TRICORE 44 // Siemens Tricore embedded processor #define EM_ARC 45 // ARC Cores #define EM_H8_300 46 // Renesas (formerly Hitachi) H8/300 #define EM_H8_300H 47 // Renesas (formerly Hitachi) H8/300H #define EM_H8S 48 // Renesas (formerly Hitachi) H8S #define EM_H8_500 49 // Renesas (formerly Hitachi) H8/500 #define EM_IA_64 50 // Intel IA-64 Processor #define EM_MIPS_X 51 // Stanford MIPS-X #define EM_COLDFIRE 52 // Motorola Coldfire #define EM_68HC12 53 // Motorola M68HC12 #define EM_MMA 54 // Fujitsu Multimedia Accelerator #define EM_PCP 55 // Siemens PCP #define EM_NCPU 56 // Sony nCPU embedded RISC processor #define EM_NDR1 57 // Denso NDR1 microprocesspr #define EM_STARCORE 58 // Motorola Star*Core processor #define EM_ME16 59 // Toyota ME16 processor #define EM_ST100 60 // STMicroelectronics ST100 processor #define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor #define EM_X86_64 62 // Advanced Micro Devices X86-64 processor #define EM_PDSP 63 // Sony DSP Processor #define EM_PDP10 64 // Digital Equipment Corp. PDP-10 #define EM_PDP11 65 // Digital Equipment Corp. PDP-11 #define EM_FX66 66 // Siemens FX66 microcontroller #define EM_ST9PLUS 67 // STMicroelectronics ST9+ 8/16 bit microcontroller #define EM_ST7 68 // STMicroelectronics ST7 8-bit microcontroller #define EM_68HC16 69 // Motorola MC68HC16 Microcontroller #define EM_68HC11 70 // Motorola MC68HC11 Microcontroller #define EM_68HC08 71 // Motorola MC68HC08 Microcontroller #define EM_68HC05 72 // Motorola MC68HC05 Microcontroller #define EM_SVX 73 // Silicon Graphics SVx #define EM_ST19 74 // STMicroelectronics ST19 8-bit cpu #define EM_VAX 75 // Digital VAX #define EM_CRIS 76 // Axis Communications 32-bit embedded processor #define EM_JAVELIN 77 // Infineon Technologies 32-bit embedded cpu #define EM_FIREPATH 78 // Element 14 64-bit DSP processor #define EM_ZSP 79 // LSI Logic's 16-bit DSP processor #define EM_MMIX 80 // Donald Knuth's educational 64-bit processor #define EM_HUANY 81 // Harvard's machine-independent format #define EM_PRISM 82 // SiTera Prism #define EM_AVR 83 // Atmel AVR 8-bit microcontroller #define EM_FR30 84 // Fujitsu FR30 #define EM_D10V 85 // Mitsubishi D10V #define EM_D30V 86 // Mitsubishi D30V #define EM_V850 87 // NEC v850 #define EM_M32R 88 // Renesas M32R (formerly Mitsubishi M32R) #define EM_MN10300 89 // Matsushita MN10300 #define EM_MN10200 90 // Matsushita MN10200 #define EM_PJ 91 // picoJava #define EM_OPENRISC 92 // OpenRISC 32-bit embedded processor #define EM_ARC_A5 93 // ARC Cores Tangent-A5 #define EM_XTENSA 94 // Tensilica Xtensa Architecture #define EM_VIDEOCORE 95 // Alphamosaic VideoCore processor #define EM_TMM_GPP 96 // Thompson Multimedia General Purpose Processor #define EM_NS32K 97 // National Semiconductor 32000 series #define EM_TPC 98 // Tenor Network TPC processor #define EM_SNP1K 99 // Trebia SNP 1000 processor #define EM_ST200 100 // STMicroelectronics ST200 microcontroller #define EM_IP2K 101 // Ubicom IP2022 micro controller #define EM_MAX 102 // MAX Processor #define EM_CR 103 // National Semiconductor CompactRISC #define EM_F2MC16 104 // Fujitsu F2MC16 #define EM_MSP430 105 // TI msp430 micro controller #define EM_BLACKFIN 106 // ADI Blackfin #define EM_SE_C33 107 // S1C33 Family of Seiko Epson processors #define EM_SEP 108 // Sharp embedded microprocessor #define EM_ARCA 109 // Arca RISC Microprocessor #define EM_UNICORE \ 110 // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University #define EM_EXCESS 111 // eXcess: 16/32/64-bit configurable embedded CPU #define EM_DXP 112 // Icera Semiconductor Inc. Deep Execution Processor #define EM_ALTERA_NIOS2 113 // Altera Nios II soft-core processor #define EM_CRX 114 // National Semiconductor CRX #define EM_XGATE 115 // Motorola XGATE embedded processor #define EM_C166 116 // Infineon C16x/XC16x processor #define EM_M16C 117 // Renesas M16C series microprocessors #define EM_DSPIC30F \ 118 // Microchip Technology dsPIC30F Digital Signal Controller #define EM_CE 119 // Freescale Communication Engine RISC core #define EM_M32C 120 // Renesas M32C series microprocessors #define EM_res121 121 // Reserved #define EM_res122 122 // Reserved #define EM_res123 123 // Reserved #define EM_res124 124 // Reserved #define EM_res125 125 // Reserved #define EM_res126 126 // Reserved #define EM_res127 127 // Reserved #define EM_res128 128 // Reserved #define EM_res129 129 // Reserved #define EM_res130 130 // Reserved #define EM_TSK3000 131 // Altium TSK3000 core #define EM_RS08 132 // Freescale RS08 embedded processor #define EM_res133 133 // Reserved #define EM_ECOG2 134 // Cyan Technology eCOG2 microprocessor #define EM_SCORE 135 // Sunplus Score #define EM_SCORE7 135 // Sunplus S+core7 RISC processor #define EM_DSP24 136 // New Japan Radio (NJR) 24-bit DSP Processor #define EM_VIDEOCORE3 137 // Broadcom VideoCore III processor #define EM_LATTICEMICO32 138 // RISC processor for Lattice FPGA architecture #define EM_SE_C17 139 // Seiko Epson C17 family #define EM_TI_C6000 140 // Texas Instruments TMS320C6000 DSP family #define EM_TI_C2000 141 // Texas Instruments TMS320C2000 DSP family #define EM_TI_C5500 142 // Texas Instruments TMS320C55x DSP family #define EM_res143 143 // Reserved #define EM_res144 144 // Reserved #define EM_res145 145 // Reserved #define EM_res146 146 // Reserved #define EM_res147 147 // Reserved #define EM_res148 148 // Reserved #define EM_res149 149 // Reserved #define EM_res150 150 // Reserved #define EM_res151 151 // Reserved #define EM_res152 152 // Reserved #define EM_res153 153 // Reserved #define EM_res154 154 // Reserved #define EM_res155 155 // Reserved #define EM_res156 156 // Reserved #define EM_res157 157 // Reserved #define EM_res158 158 // Reserved #define EM_res159 159 // Reserved #define EM_MMDSP_PLUS 160 // STMicroelectronics 64bit VLIW Data Signal Processor #define EM_CYPRESS_M8C 161 // Cypress M8C microprocessor #define EM_R32C 162 // Renesas R32C series microprocessors #define EM_TRIMEDIA 163 // NXP Semiconductors TriMedia architecture family #define EM_QDSP6 164 // QUALCOMM DSP6 Processor #define EM_8051 165 // Intel 8051 and variants #define EM_STXP7X 166 // STMicroelectronics STxP7x family #define EM_NDS32 \ 167 // Andes Technology compact code size embedded RISC processor family #define EM_ECOG1 168 // Cyan Technology eCOG1X family #define EM_ECOG1X 168 // Cyan Technology eCOG1X family #define EM_MAXQ30 169 // Dallas Semiconductor MAXQ30 Core Micro-controllers #define EM_XIMO16 170 // New Japan Radio (NJR) 16-bit DSP Processor #define EM_MANIK 171 // M2000 Reconfigurable RISC Microprocessor #define EM_CRAYNV2 172 // Cray Inc. NV2 vector architecture #define EM_RX 173 // Renesas RX family #define EM_METAG 174 // Imagination Technologies META processor architecture #define EM_MCST_ELBRUS 175 // MCST Elbrus general purpose hardware architecture #define EM_ECOG16 176 // Cyan Technology eCOG16 family #define EM_CR16 177 // National Semiconductor CompactRISC 16-bit processor #define EM_ETPU 178 // Freescale Extended Time Processing Unit #define EM_SLE9X 179 // Infineon Technologies SLE9X core #define EM_L1OM 180 // Intel L1OM #define EM_INTEL181 181 // Reserved by Intel #define EM_INTEL182 182 // Reserved by Intel #define EM_res183 183 // Reserved by ARM #define EM_res184 184 // Reserved by ARM #define EM_AVR32 185 // Atmel Corporation 32-bit microprocessor family #define EM_STM8 186 // STMicroeletronics STM8 8-bit microcontroller #define EM_TILE64 187 // Tilera TILE64 multicore architecture family #define EM_TILEPRO 188 // Tilera TILEPro multicore architecture family #define EM_MICROBLAZE 189 // Xilinx MicroBlaze 32-bit RISC soft processor core #define EM_CUDA 190 // NVIDIA CUDA architecture #define EM_TILEGX 191 // Tilera TILE-Gx multicore architecture family #define EM_CLOUDSHIELD 192 // CloudShield architecture family #define EM_COREA_1ST 193 // KIPO-KAIST Core-A 1st generation processor family #define EM_COREA_2ND 194 // KIPO-KAIST Core-A 2nd generation processor family #define EM_ARC_COMPACT2 195 // Synopsys ARCompact V2 #define EM_OPEN8 196 // Open8 8-bit RISC soft processor core #define EM_RL78 197 // Renesas RL78 family #define EM_VIDEOCORE5 198 // Broadcom VideoCore V processor #define EM_78KOR 199 // Renesas 78KOR family #define EM_56800EX 200 // Freescale 56800EX Digital Signal Controller (DSC) #define EM_BA1 201 // Beyond BA1 CPU architecture #define EM_BA2 202 // Beyond BA2 CPU architecture #define EM_XCORE 203 // XMOS xCORE processor family #define EM_MCHP_PIC 204 // Microchip 8-bit PIC(r) family #define EM_INTEL205 205 // Reserved by Intel #define EM_INTEL206 206 // Reserved by Intel #define EM_INTEL207 207 // Reserved by Intel #define EM_INTEL208 208 // Reserved by Intel #define EM_INTEL209 209 // Reserved by Intel #define EM_KM32 210 // KM211 KM32 32-bit processor #define EM_KMX32 211 // KM211 KMX32 32-bit processor #define EM_KMX16 212 // KM211 KMX16 16-bit processor #define EM_KMX8 213 // KM211 KMX8 8-bit processor #define EM_KVARC 214 // KM211 KVARC processor #define EM_CDP 215 // Paneve CDP architecture family #define EM_COGE 216 // Cognitive Smart Memory Processor #define EM_COOL 217 // iCelero CoolEngine #define EM_NORC 218 // Nanoradio Optimized RISC #define EM_CSR_KALIMBA 219 // CSR Kalimba architecture family #define EM_Z80 220 // Zilog Z80 #define EM_VISIUM 221 // Controls and Data Services VISIUMcore processor #define EM_FT32 222 // FTDI Chip FT32 high performance 32-bit RISC architecture #define EM_MOXIE 223 // Moxie processor family #define EM_AMDGPU 224 // AMD GPU architecture #define EM_RISCV 243 // RISC-V #define EM_LANAI 244 // Lanai processor #define EM_CEVA 245 // CEVA Processor Architecture Family #define EM_CEVA_X2 246 // CEVA X2 Processor Family #define EM_BPF 247 // Linux BPF – in-kernel virtual machine #define EM_GRAPHCORE_IPU 248 // Graphcore Intelligent Processing Unit #define EM_IMG1 249 // Imagination Technologies #define EM_NFP 250 // Netronome Flow Processor (P) #define EM_CSKY 252 // C-SKY processor family // File version #define EV_NONE 0 #define EV_CURRENT 1 // Identification index #define EI_MAG0 0 #define EI_MAG1 1 #define EI_MAG2 2 #define EI_MAG3 3 #define EI_CLASS 4 #define EI_DATA 5 #define EI_VERSION 6 #define EI_OSABI 7 #define EI_ABIVERSION 8 #define EI_PAD 9 #define EI_NIDENT 16 // Magic number #define ELFMAG0 0x7F #define ELFMAG1 'E' #define ELFMAG2 'L' #define ELFMAG3 'F' // File class #define ELFCLASSNONE 0 #define ELFCLASS32 1 #define ELFCLASS64 2 // Encoding #define ELFDATANONE 0 #define ELFDATA2LSB 1 #define ELFDATA2MSB 2 // OS extensions #define ELFOSABI_NONE 0 // No extensions or unspecified #define ELFOSABI_HPUX 1 // Hewlett-Packard HP-UX #define ELFOSABI_NETBSD 2 // NetBSD #define ELFOSABI_LINUX 3 // Linux #define ELFOSABI_SOLARIS 6 // Sun Solaris #define ELFOSABI_AIX 7 // AIX #define ELFOSABI_IRIX 8 // IRIX #define ELFOSABI_FREEBSD 9 // FreeBSD #define ELFOSABI_TRU64 10 // Compaq TRU64 UNIX #define ELFOSABI_MODESTO 11 // Novell Modesto #define ELFOSABI_OPENBSD 12 // Open BSD #define ELFOSABI_OPENVMS 13 // Open VMS #define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel #define ELFOSABI_AROS 15 // Amiga Research OS #define ELFOSABI_FENIXOS 16 // The FenixOS highly scalable multi-core OS // 64-255 Architecture-specific value range #define ELFOSABI_AMDGPU_HSA \ 64 // AMDGPU OS for HSA compatible compute // kernels. #define ELFOSABI_AMDGPU_PAL \ 65 // AMDGPU OS for AMD PAL compatible graphics // shaders and compute kernels. #define ELFOSABI_AMDGPU_MESA3D \ 66 // AMDGPU OS for Mesa3D compatible graphics // shaders and compute kernels. // AMDGPU specific e_flags #define EF_AMDGPU_MACH 0x0ff // AMDGPU processor selection mask. #define EF_AMDGPU_XNACK \ 0x100 // Indicates if the XNACK target feature is // enabled for all code contained in the ELF. // AMDGPU processors #define EF_AMDGPU_MACH_NONE 0x000 // Unspecified processor. #define EF_AMDGPU_MACH_R600_R600 0x001 #define EF_AMDGPU_MACH_R600_R630 0x002 #define EF_AMDGPU_MACH_R600_RS880 0x003 #define EF_AMDGPU_MACH_R600_RV670 0x004 #define EF_AMDGPU_MACH_R600_RV710 0x005 #define EF_AMDGPU_MACH_R600_RV730 0x006 #define EF_AMDGPU_MACH_R600_RV770 0x007 #define EF_AMDGPU_MACH_R600_CEDAR 0x008 #define EF_AMDGPU_MACH_R600_CYPRESS 0x009 #define EF_AMDGPU_MACH_R600_JUNIPER 0x00a #define EF_AMDGPU_MACH_R600_REDWOOD 0x00b #define EF_AMDGPU_MACH_R600_SUMO 0x00c #define EF_AMDGPU_MACH_R600_BARTS 0x00d #define EF_AMDGPU_MACH_R600_CAICOS 0x00e #define EF_AMDGPU_MACH_R600_CAYMAN 0x00f #define EF_AMDGPU_MACH_R600_TURKS 0x010 #define EF_AMDGPU_MACH_R600_RESERVED_FIRST 0x011 #define EF_AMDGPU_MACH_R600_RESERVED_LAST 0x01f #define EF_AMDGPU_MACH_R600_FIRST EF_AMDGPU_MACH_R600_R600 #define EF_AMDGPU_MACH_R600_LAST EF_AMDGPU_MACH_R600_TURKS #define EF_AMDGPU_MACH_AMDGCN_GFX600 0x020 #define EF_AMDGPU_MACH_AMDGCN_GFX601 0x021 #define EF_AMDGPU_MACH_AMDGCN_GFX700 0x022 #define EF_AMDGPU_MACH_AMDGCN_GFX701 0x023 #define EF_AMDGPU_MACH_AMDGCN_GFX702 0x024 #define EF_AMDGPU_MACH_AMDGCN_GFX703 0x025 #define EF_AMDGPU_MACH_AMDGCN_GFX704 0x026 #define EF_AMDGPU_MACH_AMDGCN_GFX801 0x028 #define EF_AMDGPU_MACH_AMDGCN_GFX802 0x029 #define EF_AMDGPU_MACH_AMDGCN_GFX803 0x02a #define EF_AMDGPU_MACH_AMDGCN_GFX810 0x02b #define EF_AMDGPU_MACH_AMDGCN_GFX900 0x02c #define EF_AMDGPU_MACH_AMDGCN_GFX902 0x02d #define EF_AMDGPU_MACH_AMDGCN_GFX904 0x02e #define EF_AMDGPU_MACH_AMDGCN_GFX906 0x02f #define EF_AMDGPU_MACH_AMDGCN_RESERVED0 0x027 #define EF_AMDGPU_MACH_AMDGCN_RESERVED1 0x030 #define EF_AMDGPU_MACH_AMDGCN_FIRST EF_AMDGPU_MACH_AMDGCN_GFX600 #define EF_AMDGPU_MACH_AMDGCN_LAST EF_AMDGPU_MACH_AMDGCN_GFX906 ///////////////////// // Sections constants // Section indexes #define SHN_UNDEF 0 #define SHN_LORESERVE 0xFF00 #define SHN_LOPROC 0xFF00 #define SHN_HIPROC 0xFF1F #define SHN_LOOS 0xFF20 #define SHN_HIOS 0xFF3F #define SHN_ABS 0xFFF1 #define SHN_COMMON 0xFFF2 #define SHN_XINDEX 0xFFFF #define SHN_HIRESERVE 0xFFFF // Section types #define SHT_NULL 0 #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_RELA 4 #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 #define SHT_NOBITS 8 #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 #define SHT_INIT_ARRAY 14 #define SHT_FINI_ARRAY 15 #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 #define SHT_LOOS 0x60000000 #define SHT_HIOS 0x6fffffff #define SHT_LOPROC 0x70000000 #define SHT_HIPROC 0x7FFFFFFF #define SHT_LOUSER 0x80000000 #define SHT_HIUSER 0xFFFFFFFF // Section attribute flags #define SHF_WRITE 0x1 #define SHF_ALLOC 0x2 #define SHF_EXECINSTR 0x4 #define SHF_MERGE 0x10 #define SHF_STRINGS 0x20 #define SHF_INFO_LINK 0x40 #define SHF_LINK_ORDER 0x80 #define SHF_OS_NONCONFORMING 0x100 #define SHF_GROUP 0x200 #define SHF_TLS 0x400 #define SHF_MASKOS 0x0ff00000 #define SHF_MASKPROC 0xF0000000 // Section group flags #define GRP_COMDAT 0x1 #define GRP_MASKOS 0x0ff00000 #define GRP_MASKPROC 0xf0000000 // Symbol binding #define STB_LOCAL 0 #define STB_GLOBAL 1 #define STB_WEAK 2 #define STB_LOOS 10 #define STB_HIOS 12 #define STB_MULTIDEF 13 #define STB_LOPROC 13 #define STB_HIPROC 15 // Note types #define NT_AMDGPU_METADATA 1 #define NT_AMD_AMDGPU_HSA_METADATA 10 #define NT_AMD_AMDGPU_ISA 11 #define NT_AMD_AMDGPU_PAL_METADATA 12 // Symbol types #define STT_NOTYPE 0 #define STT_OBJECT 1 #define STT_FUNC 2 #define STT_SECTION 3 #define STT_FILE 4 #define STT_COMMON 5 #define STT_TLS 6 #define STT_LOOS 10 #define STT_AMDGPU_HSA_KERNEL 10 #define STT_HIOS 12 #define STT_LOPROC 13 #define STT_HIPROC 15 // Symbol visibility #define STV_DEFAULT 0 #define STV_INTERNAL 1 #define STV_HIDDEN 2 #define STV_PROTECTED 3 // Undefined name #define STN_UNDEF 0 // Relocation types #define R_386_NONE 0 #define R_X86_64_NONE 0 #define R_AMDGPU_NONE 0 #define R_386_32 1 #define R_X86_64_64 1 #define R_AMDGPU_ABS32_LO 1 #define R_386_PC32 2 #define R_X86_64_PC32 2 #define R_AMDGPU_ABS32_HI 2 #define R_386_GOT32 3 #define R_X86_64_GOT32 3 #define R_AMDGPU_ABS64 3 #define R_386_PLT32 4 #define R_X86_64_PLT32 4 #define R_AMDGPU_REL32 4 #define R_386_COPY 5 #define R_X86_64_COPY 5 #define R_AMDGPU_REL64 5 #define R_386_GLOB_DAT 6 #define R_X86_64_GLOB_DAT 6 #define R_AMDGPU_ABS32 6 #define R_386_JMP_SLOT 7 #define R_X86_64_JUMP_SLOT 7 #define R_AMDGPU_GOTPCREL 7 #define R_386_RELATIVE 8 #define R_X86_64_RELATIVE 8 #define R_AMDGPU_GOTPCREL32_LO 8 #define R_386_GOTOFF 9 #define R_X86_64_GOTPCREL 9 #define R_AMDGPU_GOTPCREL32_HI 9 #define R_386_GOTPC 10 #define R_X86_64_32 10 #define R_AMDGPU_REL32_LO 10 #define R_386_32PLT 11 #define R_X86_64_32S 11 #define R_AMDGPU_REL32_HI 11 #define R_X86_64_16 12 #define R_X86_64_PC16 13 #define R_AMDGPU_RELATIVE64 13 #define R_386_TLS_TPOFF 14 #define R_X86_64_8 14 #define R_386_TLS_IE 15 #define R_X86_64_PC8 15 #define R_386_TLS_GOTIE 16 #define R_X86_64_DTPMOD64 16 #define R_386_TLS_LE 17 #define R_X86_64_DTPOFF64 17 #define R_386_TLS_GD 18 #define R_X86_64_TPOFF64 18 #define R_386_TLS_LDM 19 #define R_X86_64_TLSGD 19 #define R_386_16 20 #define R_X86_64_TLSLD 20 #define R_386_PC16 21 #define R_X86_64_DTPOFF32 21 #define R_386_8 22 #define R_X86_64_GOTTPOFF 22 #define R_386_PC8 23 #define R_X86_64_TPOFF32 23 #define R_386_TLS_GD_32 24 #define R_X86_64_PC64 24 #define R_386_TLS_GD_PUSH 25 #define R_X86_64_GOTOFF64 25 #define R_386_TLS_GD_CALL 26 #define R_X86_64_GOTPC32 26 #define R_386_TLS_GD_POP 27 #define R_X86_64_GOT64 27 #define R_386_TLS_LDM_32 28 #define R_X86_64_GOTPCREL64 28 #define R_386_TLS_LDM_PUSH 29 #define R_X86_64_GOTPC64 29 #define R_386_TLS_LDM_CALL 30 #define R_X86_64_GOTPLT64 30 #define R_386_TLS_LDM_POP 31 #define R_X86_64_PLTOFF64 31 #define R_386_TLS_LDO_32 32 #define R_386_TLS_IE_32 33 #define R_386_TLS_LE_32 34 #define R_X86_64_GOTPC32_TLSDESC 34 #define R_386_TLS_DTPMOD32 35 #define R_X86_64_TLSDESC_CALL 35 #define R_386_TLS_DTPOFF32 36 #define R_X86_64_TLSDESC 36 #define R_386_TLS_TPOFF32 37 #define R_X86_64_IRELATIVE 37 #define R_386_SIZE32 38 #define R_386_TLS_GOTDESC 39 #define R_386_TLS_DESC_CALL 40 #define R_386_TLS_DESC 41 #define R_386_IRELATIVE 42 #define R_386_GOT32X 43 #define R_X86_64_GNU_VTINHERIT 250 #define R_X86_64_GNU_VTENTRY 251 // Segment types #define PT_NULL 0 #define PT_LOAD 1 #define PT_DYNAMIC 2 #define PT_INTERP 3 #define PT_NOTE 4 #define PT_SHLIB 5 #define PT_PHDR 6 #define PT_TLS 7 #define PT_LOOS 0x60000000 #define PT_HIOS 0x6fffffff #define PT_LOPROC 0x70000000 #define PT_HIPROC 0x7FFFFFFF // Segment flags #define PF_X 1 // Execute #define PF_W 2 // Write #define PF_R 4 // Read #define PF_MASKOS 0x0ff00000 // Unspecified #define PF_MASKPROC 0xf0000000 // Unspecified // Dynamic Array Tags #define DT_NULL 0 #define DT_NEEDED 1 #define DT_PLTRELSZ 2 #define DT_PLTGOT 3 #define DT_HASH 4 #define DT_STRTAB 5 #define DT_SYMTAB 6 #define DT_RELA 7 #define DT_RELASZ 8 #define DT_RELAENT 9 #define DT_STRSZ 10 #define DT_SYMENT 11 #define DT_INIT 12 #define DT_FINI 13 #define DT_SONAME 14 #define DT_RPATH 15 #define DT_SYMBOLIC 16 #define DT_REL 17 #define DT_RELSZ 18 #define DT_RELENT 19 #define DT_PLTREL 20 #define DT_DEBUG 21 #define DT_TEXTREL 22 #define DT_JMPREL 23 #define DT_BIND_NOW 24 #define DT_INIT_ARRAY 25 #define DT_FINI_ARRAY 26 #define DT_INIT_ARRAYSZ 27 #define DT_FINI_ARRAYSZ 28 #define DT_RUNPATH 29 #define DT_FLAGS 30 #define DT_ENCODING 32 #define DT_PREINIT_ARRAY 32 #define DT_PREINIT_ARRAYSZ 33 #define DT_MAXPOSTAGS 34 #define DT_LOOS 0x6000000D #define DT_HIOS 0x6ffff000 #define DT_LOPROC 0x70000000 #define DT_HIPROC 0x7FFFFFFF // DT_FLAGS values #define DF_ORIGIN 0x1 #define DF_SYMBOLIC 0x2 #define DF_TEXTREL 0x4 #define DF_BIND_NOW 0x8 #define DF_STATIC_TLS 0x10 // ELF file header struct Elf32_Ehdr { unsigned char e_ident[EI_NIDENT]; Elf_Half e_type; Elf_Half e_machine; Elf_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf_Word e_flags; Elf_Half e_ehsize; Elf_Half e_phentsize; Elf_Half e_phnum; Elf_Half e_shentsize; Elf_Half e_shnum; Elf_Half e_shstrndx; }; struct Elf64_Ehdr { unsigned char e_ident[EI_NIDENT]; Elf_Half e_type; Elf_Half e_machine; Elf_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf_Word e_flags; Elf_Half e_ehsize; Elf_Half e_phentsize; Elf_Half e_phnum; Elf_Half e_shentsize; Elf_Half e_shnum; Elf_Half e_shstrndx; }; // Section header struct Elf32_Shdr { Elf_Word sh_name; Elf_Word sh_type; Elf_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf_Word sh_size; Elf_Word sh_link; Elf_Word sh_info; Elf_Word sh_addralign; Elf_Word sh_entsize; }; struct Elf64_Shdr { Elf_Word sh_name; Elf_Word sh_type; Elf_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf_Xword sh_size; Elf_Word sh_link; Elf_Word sh_info; Elf_Xword sh_addralign; Elf_Xword sh_entsize; }; // Segment header struct Elf32_Phdr { Elf_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf_Word p_filesz; Elf_Word p_memsz; Elf_Word p_flags; Elf_Word p_align; }; struct Elf64_Phdr { Elf_Word p_type; Elf_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf_Xword p_filesz; Elf_Xword p_memsz; Elf_Xword p_align; }; // Symbol table entry struct Elf32_Sym { Elf_Word st_name; Elf32_Addr st_value; Elf_Word st_size; unsigned char st_info; unsigned char st_other; Elf_Half st_shndx; }; struct Elf64_Sym { Elf_Word st_name; unsigned char st_info; unsigned char st_other; Elf_Half st_shndx; Elf64_Addr st_value; Elf_Xword st_size; }; #define ELF_ST_BIND( i ) ( ( i ) >> 4 ) #define ELF_ST_TYPE( i ) ( (i)&0xf ) #define ELF_ST_INFO( b, t ) ( ( ( b ) << 4 ) + ( (t)&0xf ) ) #define ELF_ST_VISIBILITY( o ) ( (o)&0x3 ) // Relocation entries struct Elf32_Rel { Elf32_Addr r_offset; Elf_Word r_info; }; struct Elf32_Rela { Elf32_Addr r_offset; Elf_Word r_info; Elf_Sword r_addend; }; struct Elf64_Rel { Elf64_Addr r_offset; Elf_Xword r_info; }; struct Elf64_Rela { Elf64_Addr r_offset; Elf_Xword r_info; Elf_Sxword r_addend; }; #define ELF32_R_SYM( i ) ( ( i ) >> 8 ) #define ELF32_R_TYPE( i ) ( (unsigned char)( i ) ) #define ELF32_R_INFO( s, t ) ( ( ( s ) << 8 ) + (unsigned char)( t ) ) #define ELF64_R_SYM( i ) ( ( i ) >> 32 ) #define ELF64_R_TYPE( i ) ( (i)&0xffffffffL ) #define ELF64_R_INFO( s, t ) \ ( ( ( ( int64_t )( s ) ) << 32 ) + ( (t)&0xffffffffL ) ) // Dynamic structure struct Elf32_Dyn { Elf_Sword d_tag; union { Elf_Word d_val; Elf32_Addr d_ptr; } d_un; }; struct Elf64_Dyn { Elf_Sxword d_tag; union { Elf_Xword d_val; Elf64_Addr d_ptr; } d_un; }; } // namespace ELFIO #endif // ELFTYPES_H /*** End of inlined file: elf_types.hpp ***/ /*** Start of inlined file: elfio_version.hpp ***/ #define ELFIO_VERSION "3.8" /*** End of inlined file: elfio_version.hpp ***/ /*** Start of inlined file: elfio_utils.hpp ***/ #ifndef ELFIO_UTILS_HPP #define ELFIO_UTILS_HPP #define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ TYPE get_##NAME() const { return ( *convertor )( FIELD ); } #define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \ void set_##NAME( TYPE value ) \ { \ FIELD = value; \ FIELD = ( *convertor )( FIELD ); \ } #define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \ TYPE get_##NAME() const { return ( *convertor )( FIELD ); } \ void set_##NAME( TYPE value ) \ { \ FIELD = value; \ FIELD = ( *convertor )( FIELD ); \ } #define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0 #define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \ virtual void set_##NAME( TYPE value ) = 0 #define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \ virtual TYPE get_##NAME() const = 0; \ virtual void set_##NAME( TYPE value ) = 0 namespace ELFIO { //------------------------------------------------------------------------------ class endianess_convertor { public: //------------------------------------------------------------------------------ endianess_convertor() { need_conversion = false; } //------------------------------------------------------------------------------ void setup( unsigned char elf_file_encoding ) { need_conversion = ( elf_file_encoding != get_host_encoding() ); } //------------------------------------------------------------------------------ uint64_t operator()( uint64_t value ) const { if ( !need_conversion ) { return value; } value = ( ( value & 0x00000000000000FFull ) << 56 ) | ( ( value & 0x000000000000FF00ull ) << 40 ) | ( ( value & 0x0000000000FF0000ull ) << 24 ) | ( ( value & 0x00000000FF000000ull ) << 8 ) | ( ( value & 0x000000FF00000000ull ) >> 8 ) | ( ( value & 0x0000FF0000000000ull ) >> 24 ) | ( ( value & 0x00FF000000000000ull ) >> 40 ) | ( ( value & 0xFF00000000000000ull ) >> 56 ); return value; } //------------------------------------------------------------------------------ int64_t operator()( int64_t value ) const { if ( !need_conversion ) { return value; } return ( int64_t )( *this )( (uint64_t)value ); } //------------------------------------------------------------------------------ uint32_t operator()( uint32_t value ) const { if ( !need_conversion ) { return value; } value = ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) | ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 ); return value; } //------------------------------------------------------------------------------ int32_t operator()( int32_t value ) const { if ( !need_conversion ) { return value; } return ( int32_t )( *this )( (uint32_t)value ); } //------------------------------------------------------------------------------ uint16_t operator()( uint16_t value ) const { if ( !need_conversion ) { return value; } value = ( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 ); return value; } //------------------------------------------------------------------------------ int16_t operator()( int16_t value ) const { if ( !need_conversion ) { return value; } return ( int16_t )( *this )( (uint16_t)value ); } //------------------------------------------------------------------------------ int8_t operator()( int8_t value ) const { return value; } //------------------------------------------------------------------------------ uint8_t operator()( uint8_t value ) const { return value; } //------------------------------------------------------------------------------ private: //------------------------------------------------------------------------------ unsigned char get_host_encoding() const { static const int tmp = 1; if ( 1 == *(const char*)&tmp ) { return ELFDATA2LSB; } else { return ELFDATA2MSB; } } //------------------------------------------------------------------------------ private: bool need_conversion; }; //------------------------------------------------------------------------------ inline uint32_t elf_hash( const unsigned char* name ) { uint32_t h = 0, g; while ( *name ) { h = ( h << 4 ) + *name++; g = h & 0xf0000000; if ( g != 0 ) h ^= g >> 24; h &= ~g; } return h; } } // namespace ELFIO #endif // ELFIO_UTILS_HPP /*** End of inlined file: elfio_utils.hpp ***/ /*** Start of inlined file: elfio_header.hpp ***/ #ifndef ELF_HEADER_HPP #define ELF_HEADER_HPP #include namespace ELFIO { class elf_header { public: virtual ~elf_header(){}; virtual bool load( std::istream& stream ) = 0; virtual bool save( std::ostream& stream ) const = 0; // ELF header functions ELFIO_GET_ACCESS_DECL( unsigned char, class ); ELFIO_GET_ACCESS_DECL( unsigned char, elf_version ); ELFIO_GET_ACCESS_DECL( unsigned char, encoding ); ELFIO_GET_ACCESS_DECL( Elf_Half, header_size ); ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size ); ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version ); ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi ); ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); }; template struct elf_header_impl_types; template <> struct elf_header_impl_types { typedef Elf32_Phdr Phdr_type; typedef Elf32_Shdr Shdr_type; static const unsigned char file_class = ELFCLASS32; }; template <> struct elf_header_impl_types { typedef Elf64_Phdr Phdr_type; typedef Elf64_Shdr Shdr_type; static const unsigned char file_class = ELFCLASS64; }; template class elf_header_impl : public elf_header { public: //------------------------------------------------------------------------------ elf_header_impl( endianess_convertor* convertor_, unsigned char encoding ) { convertor = convertor_; std::fill_n( reinterpret_cast( &header ), sizeof( header ), '\0' ); header.e_ident[EI_MAG0] = ELFMAG0; header.e_ident[EI_MAG1] = ELFMAG1; header.e_ident[EI_MAG2] = ELFMAG2; header.e_ident[EI_MAG3] = ELFMAG3; header.e_ident[EI_CLASS] = elf_header_impl_types::file_class; header.e_ident[EI_DATA] = encoding; header.e_ident[EI_VERSION] = EV_CURRENT; header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT ); header.e_ehsize = ( sizeof( header ) ); header.e_ehsize = ( *convertor )( header.e_ehsize ); header.e_shstrndx = ( *convertor )( (Elf_Half)1 ); header.e_phentsize = sizeof( typename elf_header_impl_types::Phdr_type ); header.e_shentsize = sizeof( typename elf_header_impl_types::Shdr_type ); header.e_phentsize = ( *convertor )( header.e_phentsize ); header.e_shentsize = ( *convertor )( header.e_shentsize ); } //------------------------------------------------------------------------------ bool load( std::istream& stream ) { stream.seekg( 0 ); stream.read( reinterpret_cast( &header ), sizeof( header ) ); return ( stream.gcount() == sizeof( header ) ); } //------------------------------------------------------------------------------ bool save( std::ostream& stream ) const { stream.seekp( 0 ); stream.write( reinterpret_cast( &header ), sizeof( header ) ); return stream.good(); } //------------------------------------------------------------------------------ // ELF header functions ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] ); ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] ); ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] ); ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize ); ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize ); ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize ); ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version ); ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] ); ELFIO_GET_SET_ACCESS( unsigned char, abi_version, header.e_ident[EI_ABIVERSION] ); ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx ); ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry ); ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum ); ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff ); ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum ); ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); private: T header; endianess_convertor* convertor; }; } // namespace ELFIO #endif // ELF_HEADER_HPP /*** End of inlined file: elfio_header.hpp ***/ /*** Start of inlined file: elfio_section.hpp ***/ #ifndef ELFIO_SECTION_HPP #define ELFIO_SECTION_HPP #include #include #include namespace ELFIO { class section { friend class elfio; public: virtual ~section(){}; ELFIO_GET_ACCESS_DECL( Elf_Half, index ); ELFIO_GET_SET_ACCESS_DECL( std::string, name ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); virtual const char* get_data() const = 0; virtual void set_data( const char* pData, Elf_Word size ) = 0; virtual void set_data( const std::string& data ) = 0; virtual void append_data( const char* pData, Elf_Word size ) = 0; virtual void append_data( const std::string& data ) = 0; virtual size_t get_stream_size() const = 0; virtual void set_stream_size( size_t value ) = 0; protected: ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_SET_ACCESS_DECL( Elf_Half, index ); virtual void load( std::istream& stream, std::streampos header_offset ) = 0; virtual void save( std::ostream& stream, std::streampos header_offset, std::streampos data_offset ) = 0; virtual bool is_address_initialized() const = 0; }; template class section_impl : public section { public: //------------------------------------------------------------------------------ section_impl( const endianess_convertor* convertor_ ) : convertor( convertor_ ) { std::fill_n( reinterpret_cast( &header ), sizeof( header ), '\0' ); is_address_set = false; data = 0; data_size = 0; index = 0; stream_size = 0; } //------------------------------------------------------------------------------ ~section_impl() { delete[] data; } //------------------------------------------------------------------------------ // Section info functions ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr ); //------------------------------------------------------------------------------ Elf_Half get_index() const { return index; } //------------------------------------------------------------------------------ std::string get_name() const { return name; } //------------------------------------------------------------------------------ void set_name( std::string name_ ) { name = name_; } //------------------------------------------------------------------------------ void set_address( Elf64_Addr value ) { header.sh_addr = value; header.sh_addr = ( *convertor )( header.sh_addr ); is_address_set = true; } //------------------------------------------------------------------------------ bool is_address_initialized() const { return is_address_set; } //------------------------------------------------------------------------------ const char* get_data() const { return data; } //------------------------------------------------------------------------------ void set_data( const char* raw_data, Elf_Word size ) { if ( get_type() != SHT_NOBITS ) { delete[] data; data = new ( std::nothrow ) char[size]; if ( 0 != data && 0 != raw_data ) { data_size = size; std::copy( raw_data, raw_data + size, data ); } else { data_size = 0; } } set_size( data_size ); } //------------------------------------------------------------------------------ void set_data( const std::string& str_data ) { return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); } //------------------------------------------------------------------------------ void append_data( const char* raw_data, Elf_Word size ) { if ( get_type() != SHT_NOBITS ) { if ( get_size() + size < data_size ) { std::copy( raw_data, raw_data + size, data + get_size() ); } else { data_size = 2 * ( data_size + size ); char* new_data = new ( std::nothrow ) char[data_size]; if ( 0 != new_data ) { std::copy( data, data + get_size(), new_data ); std::copy( raw_data, raw_data + size, new_data + get_size() ); delete[] data; data = new_data; } else { size = 0; } } set_size( get_size() + size ); } } //------------------------------------------------------------------------------ void append_data( const std::string& str_data ) { return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); } //------------------------------------------------------------------------------ protected: //------------------------------------------------------------------------------ ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); //------------------------------------------------------------------------------ void set_index( Elf_Half value ) { index = value; } //------------------------------------------------------------------------------ void load( std::istream& stream, std::streampos header_offset ) { std::fill_n( reinterpret_cast( &header ), sizeof( header ), '\0' ); stream.seekg( 0, stream.end ); set_stream_size( stream.tellg() ); stream.seekg( header_offset ); stream.read( reinterpret_cast( &header ), sizeof( header ) ); Elf_Xword size = get_size(); if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size() ) { data = new ( std::nothrow ) char[size + 1]; if ( ( 0 != size ) && ( 0 != data ) ) { stream.seekg( ( *convertor )( header.sh_offset ) ); stream.read( data, size ); data[size] = 0; // Ensure data is ended with 0 to avoid oob read data_size = size; } else { data_size = 0; } } } //------------------------------------------------------------------------------ void save( std::ostream& stream, std::streampos header_offset, std::streampos data_offset ) { if ( 0 != get_index() ) { header.sh_offset = data_offset; header.sh_offset = ( *convertor )( header.sh_offset ); } save_header( stream, header_offset ); if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL && get_size() != 0 && data != 0 ) { save_data( stream, data_offset ); } } //------------------------------------------------------------------------------ private: //------------------------------------------------------------------------------ void save_header( std::ostream& stream, std::streampos header_offset ) const { stream.seekp( header_offset ); stream.write( reinterpret_cast( &header ), sizeof( header ) ); } //------------------------------------------------------------------------------ void save_data( std::ostream& stream, std::streampos data_offset ) const { stream.seekp( data_offset ); stream.write( get_data(), get_size() ); } //------------------------------------------------------------------------------ size_t get_stream_size() const { return stream_size; } //------------------------------------------------------------------------------ void set_stream_size( size_t value ) { stream_size = value; } //------------------------------------------------------------------------------ private: T header; Elf_Half index; std::string name; char* data; Elf_Word data_size; const endianess_convertor* convertor; bool is_address_set; size_t stream_size; }; } // namespace ELFIO #endif // ELFIO_SECTION_HPP /*** End of inlined file: elfio_section.hpp ***/ /*** Start of inlined file: elfio_segment.hpp ***/ #ifndef ELFIO_SEGMENT_HPP #define ELFIO_SEGMENT_HPP #include #include #include namespace ELFIO { class segment { friend class elfio; public: virtual ~segment(){}; ELFIO_GET_ACCESS_DECL( Elf_Half, index ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); virtual const char* get_data() const = 0; virtual Elf_Half add_section_index( Elf_Half index, Elf_Xword addr_align ) = 0; virtual Elf_Half get_sections_num() const = 0; virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; virtual bool is_offset_initialized() const = 0; protected: ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_SET_ACCESS_DECL( Elf_Half, index ); virtual const std::vector& get_sections() const = 0; virtual void load( std::istream& stream, std::streampos header_offset ) = 0; virtual void save( std::ostream& stream, std::streampos header_offset, std::streampos data_offset ) = 0; }; //------------------------------------------------------------------------------ template class segment_impl : public segment { public: //------------------------------------------------------------------------------ segment_impl( endianess_convertor* convertor_ ) : stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ ) { is_offset_set = false; std::fill_n( reinterpret_cast( &ph ), sizeof( ph ), '\0' ); } //------------------------------------------------------------------------------ virtual ~segment_impl() { delete[] data; } //------------------------------------------------------------------------------ // Section info functions ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); size_t stream_size; //------------------------------------------------------------------------------ size_t get_stream_size() const { return stream_size; } //------------------------------------------------------------------------------ void set_stream_size( size_t value ) { stream_size = value; } //------------------------------------------------------------------------------ Elf_Half get_index() const { return index; } //------------------------------------------------------------------------------ const char* get_data() const { return data; } //------------------------------------------------------------------------------ Elf_Half add_section_index( Elf_Half sec_index, Elf_Xword addr_align ) { sections.push_back( sec_index ); if ( addr_align > get_align() ) { set_align( addr_align ); } return (Elf_Half)sections.size(); } //------------------------------------------------------------------------------ Elf_Half get_sections_num() const { return (Elf_Half)sections.size(); } //------------------------------------------------------------------------------ Elf_Half get_section_index_at( Elf_Half num ) const { if ( num < sections.size() ) { return sections[num]; } return Elf_Half( -1 ); } //------------------------------------------------------------------------------ protected: //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void set_offset( Elf64_Off value ) { ph.p_offset = value; ph.p_offset = ( *convertor )( ph.p_offset ); is_offset_set = true; } //------------------------------------------------------------------------------ bool is_offset_initialized() const { return is_offset_set; } //------------------------------------------------------------------------------ const std::vector& get_sections() const { return sections; } //------------------------------------------------------------------------------ void set_index( Elf_Half value ) { index = value; } //------------------------------------------------------------------------------ void load( std::istream& stream, std::streampos header_offset ) { stream.seekg( 0, stream.end ); set_stream_size( stream.tellg() ); stream.seekg( header_offset ); stream.read( reinterpret_cast( &ph ), sizeof( ph ) ); is_offset_set = true; if ( PT_NULL != get_type() && 0 != get_file_size() ) { stream.seekg( ( *convertor )( ph.p_offset ) ); Elf_Xword size = get_file_size(); if ( size > get_stream_size() ) { data = 0; } else { data = new (std::nothrow) char[size + 1]; if ( 0 != data ) { stream.read( data, size ); data[size] = 0; } } } } //------------------------------------------------------------------------------ void save( std::ostream& stream, std::streampos header_offset, std::streampos data_offset ) { ph.p_offset = data_offset; ph.p_offset = ( *convertor )( ph.p_offset ); stream.seekp( header_offset ); stream.write( reinterpret_cast( &ph ), sizeof( ph ) ); } //------------------------------------------------------------------------------ private: T ph; Elf_Half index; char* data; std::vector sections; endianess_convertor* convertor; bool is_offset_set; }; } // namespace ELFIO #endif // ELFIO_SEGMENT_HPP /*** End of inlined file: elfio_segment.hpp ***/ /*** Start of inlined file: elfio_strings.hpp ***/ #ifndef ELFIO_STRINGS_HPP #define ELFIO_STRINGS_HPP #include #include #include namespace ELFIO { //------------------------------------------------------------------------------ template class string_section_accessor_template { public: //------------------------------------------------------------------------------ string_section_accessor_template( S* section_ ) : string_section( section_ ) { } //------------------------------------------------------------------------------ const char* get_string( Elf_Word index ) const { if ( string_section ) { if ( index < string_section->get_size() ) { const char* data = string_section->get_data(); if ( 0 != data ) { return data + index; } } } return 0; } //------------------------------------------------------------------------------ Elf_Word add_string( const char* str ) { Elf_Word current_position = 0; if ( string_section ) { // Strings are addeded to the end of the current section data current_position = (Elf_Word)string_section->get_size(); if ( current_position == 0 ) { char empty_string = '\0'; string_section->append_data( &empty_string, 1 ); current_position++; } string_section->append_data( str, (Elf_Word)std::strlen( str ) + 1 ); } return current_position; } //------------------------------------------------------------------------------ Elf_Word add_string( const std::string& str ) { return add_string( str.c_str() ); } //------------------------------------------------------------------------------ private: S* string_section; }; using string_section_accessor = string_section_accessor_template

; using const_string_section_accessor = string_section_accessor_template; } // namespace ELFIO #endif // ELFIO_STRINGS_HPP /*** End of inlined file: elfio_strings.hpp ***/ #define ELFIO_HEADER_ACCESS_GET( TYPE, FNAME ) \ TYPE get_##FNAME() const { return header ? ( header->get_##FNAME() ) : 0; } #define ELFIO_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \ TYPE get_##FNAME() const \ { \ return header ? ( header->get_##FNAME() ) : 0; \ } \ void set_##FNAME( TYPE val ) \ { \ if ( header ) { \ header->set_##FNAME( val ); \ } \ } namespace ELFIO { //------------------------------------------------------------------------------ class elfio { public: //------------------------------------------------------------------------------ elfio() : sections( this ), segments( this ) { header = 0; current_file_pos = 0; create( ELFCLASS32, ELFDATA2LSB ); } //------------------------------------------------------------------------------ ~elfio() { clean(); } //------------------------------------------------------------------------------ void create( unsigned char file_class, unsigned char encoding ) { clean(); convertor.setup( encoding ); header = create_header( file_class, encoding ); create_mandatory_sections(); } //------------------------------------------------------------------------------ bool load( const std::string& file_name ) { std::ifstream stream; stream.open( file_name.c_str(), std::ios::in | std::ios::binary ); if ( !stream ) { return false; } return load( stream ); } //------------------------------------------------------------------------------ bool load( std::istream& stream ) { clean(); unsigned char e_ident[EI_NIDENT]; // Read ELF file signature stream.read( reinterpret_cast( &e_ident ), sizeof( e_ident ) ); // Is it ELF file? if ( stream.gcount() != sizeof( e_ident ) || e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 || e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3 ) { return false; } if ( ( e_ident[EI_CLASS] != ELFCLASS64 ) && ( e_ident[EI_CLASS] != ELFCLASS32 ) ) { return false; } convertor.setup( e_ident[EI_DATA] ); header = create_header( e_ident[EI_CLASS], e_ident[EI_DATA] ); if ( 0 == header ) { return false; } if ( !header->load( stream ) ) { return false; } load_sections( stream ); bool is_still_good = load_segments( stream ); return is_still_good; } //------------------------------------------------------------------------------ bool save( const std::string& file_name ) { std::ofstream stream; stream.open( file_name.c_str(), std::ios::out | std::ios::binary ); if ( !stream ) { return false; } return save( stream ); } //------------------------------------------------------------------------------ bool save( std::ostream& stream ) { if ( !stream || !header ) { return false; } bool is_still_good = true; // Define layout specific header fields // The position of the segment table is fixed after the header. // The position of the section table is variable and needs to be fixed // before saving. header->set_segments_num( segments.size() ); header->set_segments_offset( segments.size() ? header->get_header_size() : 0 ); header->set_sections_num( sections.size() ); header->set_sections_offset( 0 ); // Layout the first section right after the segment table current_file_pos = header->get_header_size() + header->get_segment_entry_size() * (Elf_Xword)header->get_segments_num(); calc_segment_alignment(); is_still_good = layout_segments_and_their_sections(); is_still_good = is_still_good && layout_sections_without_segments(); is_still_good = is_still_good && layout_section_table(); is_still_good = is_still_good && save_header( stream ); is_still_good = is_still_good && save_sections( stream ); is_still_good = is_still_good && save_segments( stream ); return is_still_good; } //------------------------------------------------------------------------------ // ELF header access functions ELFIO_HEADER_ACCESS_GET( unsigned char, class ); ELFIO_HEADER_ACCESS_GET( unsigned char, elf_version ); ELFIO_HEADER_ACCESS_GET( unsigned char, encoding ); ELFIO_HEADER_ACCESS_GET( Elf_Word, version ); ELFIO_HEADER_ACCESS_GET( Elf_Half, header_size ); ELFIO_HEADER_ACCESS_GET( Elf_Half, section_entry_size ); ELFIO_HEADER_ACCESS_GET( Elf_Half, segment_entry_size ); ELFIO_HEADER_ACCESS_GET_SET( unsigned char, os_abi ); ELFIO_HEADER_ACCESS_GET_SET( unsigned char, abi_version ); ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, type ); ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, machine ); ELFIO_HEADER_ACCESS_GET_SET( Elf_Word, flags ); ELFIO_HEADER_ACCESS_GET_SET( Elf64_Addr, entry ); ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset ); ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset ); ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index ); //------------------------------------------------------------------------------ const endianess_convertor& get_convertor() const { return convertor; } //------------------------------------------------------------------------------ Elf_Xword get_default_entry_size( Elf_Word section_type ) const { switch ( section_type ) { case SHT_RELA: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Rela ); } else { return sizeof( Elf32_Rela ); } case SHT_REL: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Rel ); } else { return sizeof( Elf32_Rel ); } case SHT_SYMTAB: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Sym ); } else { return sizeof( Elf32_Sym ); } case SHT_DYNAMIC: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Dyn ); } else { return sizeof( Elf32_Dyn ); } default: return 0; } } //------------------------------------------------------------------------------ private: bool is_offset_in_section( Elf64_Off offset, const section* sec ) const { return ( offset >= sec->get_offset() ) && ( offset < ( sec->get_offset() + sec->get_size() ) ); } //------------------------------------------------------------------------------ public: //! returns an empty string if no problems are detected, //! or a string containing an error message if problems are found std::string validate() const { // check for overlapping sections in the file for ( int i = 0; i < sections.size(); ++i ) { for ( int j = i + 1; j < sections.size(); ++j ) { const section* a = sections[i]; const section* b = sections[j]; if ( !( a->get_type() & SHT_NOBITS ) && !( b->get_type() & SHT_NOBITS ) && ( a->get_size() > 0 ) && ( b->get_size() > 0 ) && ( a->get_offset() > 0 ) && ( b->get_offset() > 0 ) ) { if ( is_offset_in_section( a->get_offset(), b ) || is_offset_in_section( a->get_offset() + a->get_size() - 1, b ) || is_offset_in_section( b->get_offset(), a ) || is_offset_in_section( b->get_offset() + b->get_size() - 1, a ) ) { return "Sections " + a->get_name() + " and " + b->get_name() + " overlap in file"; } } } } // more checks to be added here... return ""; } //------------------------------------------------------------------------------ private: //------------------------------------------------------------------------------ void clean() { delete header; header = 0; std::vector::const_iterator it; for ( it = sections_.begin(); it != sections_.end(); ++it ) { delete *it; } sections_.clear(); std::vector::const_iterator it1; for ( it1 = segments_.begin(); it1 != segments_.end(); ++it1 ) { delete *it1; } segments_.clear(); } //------------------------------------------------------------------------------ elf_header* create_header( unsigned char file_class, unsigned char encoding ) { elf_header* new_header = 0; if ( file_class == ELFCLASS64 ) { new_header = new elf_header_impl( &convertor, encoding ); } else if ( file_class == ELFCLASS32 ) { new_header = new elf_header_impl( &convertor, encoding ); } else { return 0; } return new_header; } //------------------------------------------------------------------------------ section* create_section() { section* new_section; unsigned char file_class = get_class(); if ( file_class == ELFCLASS64 ) { new_section = new section_impl( &convertor ); } else if ( file_class == ELFCLASS32 ) { new_section = new section_impl( &convertor ); } else { return 0; } new_section->set_index( (Elf_Half)sections_.size() ); sections_.push_back( new_section ); return new_section; } //------------------------------------------------------------------------------ segment* create_segment() { segment* new_segment; unsigned char file_class = header->get_class(); if ( file_class == ELFCLASS64 ) { new_segment = new segment_impl( &convertor ); } else if ( file_class == ELFCLASS32 ) { new_segment = new segment_impl( &convertor ); } else { return 0; } new_segment->set_index( (Elf_Half)segments_.size() ); segments_.push_back( new_segment ); return new_segment; } //------------------------------------------------------------------------------ void create_mandatory_sections() { // Create null section without calling to 'add_section' as no string // section containing section names exists yet section* sec0 = create_section(); sec0->set_index( 0 ); sec0->set_name( "" ); sec0->set_name_string_offset( 0 ); set_section_name_str_index( 1 ); section* shstrtab = sections.add( ".shstrtab" ); shstrtab->set_type( SHT_STRTAB ); shstrtab->set_addr_align( 1 ); } //------------------------------------------------------------------------------ Elf_Half load_sections( std::istream& stream ) { Elf_Half entry_size = header->get_section_entry_size(); Elf_Half num = header->get_sections_num(); Elf64_Off offset = header->get_sections_offset(); for ( Elf_Half i = 0; i < num; ++i ) { section* sec = create_section(); sec->load( stream, (std::streamoff)offset + (std::streampos)i * entry_size ); sec->set_index( i ); // To mark that the section is not permitted to reassign address // during layout calculation sec->set_address( sec->get_address() ); } Elf_Half shstrndx = get_section_name_str_index(); if ( SHN_UNDEF != shstrndx ) { string_section_accessor str_reader( sections[shstrndx] ); for ( Elf_Half i = 0; i < num; ++i ) { Elf_Word section_offset = sections[i]->get_name_string_offset(); const char* p = str_reader.get_string( section_offset ); if ( p != 0 ) { sections[i]->set_name( p ); } } } return num; } //------------------------------------------------------------------------------ //! Checks whether the addresses of the section entirely fall within the given segment. //! It doesn't matter if the addresses are memory addresses, or file offsets, //! they just need to be in the same address space bool is_sect_in_seg( Elf64_Off sect_begin, Elf_Xword sect_size, Elf64_Off seg_begin, Elf64_Off seg_end ) { return ( seg_begin <= sect_begin ) && ( sect_begin + sect_size <= seg_end ) && ( sect_begin < seg_end ); // this is important criteria when sect_size == 0 // Example: seg_begin=10, seg_end=12 (-> covering the bytes 10 and 11) // sect_begin=12, sect_size=0 -> shall return false! } //------------------------------------------------------------------------------ bool load_segments( std::istream& stream ) { Elf_Half entry_size = header->get_segment_entry_size(); Elf_Half num = header->get_segments_num(); Elf64_Off offset = header->get_segments_offset(); for ( Elf_Half i = 0; i < num; ++i ) { segment* seg; unsigned char file_class = header->get_class(); if ( file_class == ELFCLASS64 ) { seg = new segment_impl( &convertor ); } else if ( file_class == ELFCLASS32 ) { seg = new segment_impl( &convertor ); } else { return false; } seg->load( stream, (std::streamoff)offset + (std::streampos)i * entry_size ); seg->set_index( i ); // Add sections to the segments (similar to readelfs algorithm) Elf64_Off segBaseOffset = seg->get_offset(); Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size(); Elf64_Off segVBaseAddr = seg->get_virtual_address(); Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size(); for ( Elf_Half j = 0; j < sections.size(); ++j ) { const section* psec = sections[j]; // SHF_ALLOC sections are matched based on the virtual address // otherwise the file offset is matched if ( ( psec->get_flags() & SHF_ALLOC ) ? is_sect_in_seg( psec->get_address(), psec->get_size(), segVBaseAddr, segVEndAddr ) : is_sect_in_seg( psec->get_offset(), psec->get_size(), segBaseOffset, segEndOffset ) ) { // Alignment of segment shall not be updated, to preserve original value // It will be re-calculated on saving. seg->add_section_index( psec->get_index(), 0 ); } } // Add section into the segments' container segments_.push_back( seg ); } return true; } //------------------------------------------------------------------------------ bool save_header( std::ostream& stream ) { return header->save( stream ); } //------------------------------------------------------------------------------ bool save_sections( std::ostream& stream ) { for ( unsigned int i = 0; i < sections_.size(); ++i ) { section* sec = sections_.at( i ); std::streampos headerPosition = (std::streamoff)header->get_sections_offset() + (std::streampos)header->get_section_entry_size() * sec->get_index(); sec->save( stream, headerPosition, sec->get_offset() ); } return true; } //------------------------------------------------------------------------------ bool save_segments( std::ostream& stream ) { for ( unsigned int i = 0; i < segments_.size(); ++i ) { segment* seg = segments_.at( i ); std::streampos headerPosition = header->get_segments_offset() + (std::streampos)header->get_segment_entry_size() * seg->get_index(); seg->save( stream, headerPosition, seg->get_offset() ); } return true; } //------------------------------------------------------------------------------ bool is_section_without_segment( unsigned int section_index ) { bool found = false; for ( unsigned int j = 0; !found && ( j < segments.size() ); ++j ) { for ( unsigned int k = 0; !found && ( k < segments[j]->get_sections_num() ); ++k ) { found = segments[j]->get_section_index_at( k ) == section_index; } } return !found; } //------------------------------------------------------------------------------ bool is_subsequence_of( segment* seg1, segment* seg2 ) { // Return 'true' if sections of seg1 are a subset of sections in seg2 const std::vector& sections1 = seg1->get_sections(); const std::vector& sections2 = seg2->get_sections(); bool found = false; if ( sections1.size() < sections2.size() ) { found = std::includes( sections2.begin(), sections2.end(), sections1.begin(), sections1.end() ); } return found; } //------------------------------------------------------------------------------ std::vector get_ordered_segments() { std::vector res; std::deque worklist; res.reserve( segments.size() ); std::copy( segments_.begin(), segments_.end(), std::back_inserter( worklist ) ); // Bring the segments which start at address 0 to the front size_t nextSlot = 0; for ( size_t i = 0; i < worklist.size(); ++i ) { if ( i != nextSlot && worklist[i]->is_offset_initialized() && worklist[i]->get_offset() == 0 ) { if ( worklist[nextSlot]->get_offset() == 0 ) { ++nextSlot; } std::swap( worklist[i], worklist[nextSlot] ); ++nextSlot; } } while ( !worklist.empty() ) { segment* seg = worklist.front(); worklist.pop_front(); size_t i = 0; for ( ; i < worklist.size(); ++i ) { if ( is_subsequence_of( seg, worklist[i] ) ) { break; } } if ( i < worklist.size() ) worklist.push_back( seg ); else res.push_back( seg ); } return res; } //------------------------------------------------------------------------------ bool layout_sections_without_segments() { for ( unsigned int i = 0; i < sections_.size(); ++i ) { if ( is_section_without_segment( i ) ) { section* sec = sections_[i]; Elf_Xword section_align = sec->get_addr_align(); if ( section_align > 1 && current_file_pos % section_align != 0 ) { current_file_pos += section_align - current_file_pos % section_align; } if ( 0 != sec->get_index() ) sec->set_offset( current_file_pos ); if ( SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() ) { current_file_pos += sec->get_size(); } } } return true; } //------------------------------------------------------------------------------ void calc_segment_alignment() { for ( std::vector::iterator s = segments_.begin(); s != segments_.end(); ++s ) { segment* seg = *s; for ( int i = 0; i < seg->get_sections_num(); ++i ) { section* sect = sections_[seg->get_section_index_at( i )]; if ( sect->get_addr_align() > seg->get_align() ) { seg->set_align( sect->get_addr_align() ); } } } } //------------------------------------------------------------------------------ bool layout_segments_and_their_sections() { std::vector worklist; std::vector section_generated( sections.size(), false ); // Get segments in a order in where segments which contain a // sub sequence of other segments are located at the end worklist = get_ordered_segments(); for ( unsigned int i = 0; i < worklist.size(); ++i ) { Elf_Xword segment_memory = 0; Elf_Xword segment_filesize = 0; Elf_Xword seg_start_pos = current_file_pos; segment* seg = worklist[i]; // Special case: PHDR segment // This segment contains the program headers but no sections if ( seg->get_type() == PT_PHDR && seg->get_sections_num() == 0 ) { seg_start_pos = header->get_segments_offset(); segment_memory = segment_filesize = header->get_segment_entry_size() * (Elf_Xword)header->get_segments_num(); } // Special case: else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) { seg_start_pos = 0; if ( seg->get_sections_num() ) { segment_memory = segment_filesize = current_file_pos; } } // New segments with not generated sections // have to be aligned else if ( seg->get_sections_num() && !section_generated[seg->get_section_index_at( 0 )] ) { Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1; Elf64_Off cur_page_alignment = current_file_pos % align; Elf64_Off req_page_alignment = seg->get_virtual_address() % align; Elf64_Off error = req_page_alignment - cur_page_alignment; current_file_pos += ( seg->get_align() + error ) % align; seg_start_pos = current_file_pos; } else if ( seg->get_sections_num() ) { seg_start_pos = sections[seg->get_section_index_at( 0 )]->get_offset(); } // Write segment's data for ( unsigned int j = 0; j < seg->get_sections_num(); ++j ) { Elf_Half index = seg->get_section_index_at( j ); section* sec = sections[index]; // The NULL section is always generated if ( SHT_NULL == sec->get_type() ) { section_generated[index] = true; continue; } Elf_Xword secAlign = 0; // Fix up the alignment if ( !section_generated[index] && sec->is_address_initialized() && SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() && 0 != sec->get_size() ) { // Align the sections based on the virtual addresses // when possible (this is what matters for execution) Elf64_Off req_offset = sec->get_address() - seg->get_virtual_address(); Elf64_Off cur_offset = current_file_pos - seg_start_pos; if ( req_offset < cur_offset ) { // something has gone awfully wrong, abort! // secAlign would turn out negative, seeking backwards and overwriting previous data return false; } secAlign = req_offset - cur_offset; } else if ( !section_generated[index] && !sec->is_address_initialized() ) { // If no address has been specified then only the section // alignment constraint has to be matched Elf_Xword align = sec->get_addr_align(); if ( align == 0 ) { align = 1; } Elf64_Off error = current_file_pos % align; secAlign = ( align - error ) % align; } else if ( section_generated[index] ) { // Alignment for already generated sections secAlign = sec->get_offset() - seg_start_pos - segment_filesize; } // Determine the segment file and memory sizes // Special case .tbss section (NOBITS) in non TLS segment if ( ( sec->get_flags() & SHF_ALLOC ) && !( ( sec->get_flags() & SHF_TLS ) && ( seg->get_type() != PT_TLS ) && ( SHT_NOBITS == sec->get_type() ) ) ) segment_memory += sec->get_size() + secAlign; if ( SHT_NOBITS != sec->get_type() ) segment_filesize += sec->get_size() + secAlign; // Nothing to be done when generating nested segments if ( section_generated[index] ) { continue; } current_file_pos += secAlign; // Set the section addresses when missing if ( !sec->is_address_initialized() ) sec->set_address( seg->get_virtual_address() + current_file_pos - seg_start_pos ); if ( 0 != sec->get_index() ) sec->set_offset( current_file_pos ); if ( SHT_NOBITS != sec->get_type() ) current_file_pos += sec->get_size(); section_generated[index] = true; } seg->set_file_size( segment_filesize ); // If we already have a memory size from loading an elf file (value > 0), // it must not shrink! // Memory size may be bigger than file size and it is the loader's job to do something // with the surplus bytes in memory, like initializing them with a defined value. if ( seg->get_memory_size() < segment_memory ) { seg->set_memory_size( segment_memory ); } seg->set_offset( seg_start_pos ); } return true; } //------------------------------------------------------------------------------ bool layout_section_table() { // Simply place the section table at the end for now Elf64_Off alignmentError = current_file_pos % 4; current_file_pos += ( 4 - alignmentError ) % 4; header->set_sections_offset( current_file_pos ); return true; } //------------------------------------------------------------------------------ public: friend class Sections; class Sections { public: //------------------------------------------------------------------------------ Sections( elfio* parent_ ) : parent( parent_ ) {} //------------------------------------------------------------------------------ Elf_Half size() const { return (Elf_Half)parent->sections_.size(); } //------------------------------------------------------------------------------ section* operator[]( unsigned int index ) const { section* sec = 0; if ( index < parent->sections_.size() ) { sec = parent->sections_[index]; } return sec; } //------------------------------------------------------------------------------ section* operator[]( const std::string& name ) const { section* sec = 0; std::vector::const_iterator it; for ( it = parent->sections_.begin(); it != parent->sections_.end(); ++it ) { if ( ( *it )->get_name() == name ) { sec = *it; break; } } return sec; } //------------------------------------------------------------------------------ section* add( const std::string& name ) { section* new_section = parent->create_section(); new_section->set_name( name ); Elf_Half str_index = parent->get_section_name_str_index(); section* string_table( parent->sections_[str_index] ); string_section_accessor str_writer( string_table ); Elf_Word pos = str_writer.add_string( name ); new_section->set_name_string_offset( pos ); return new_section; } //------------------------------------------------------------------------------ std::vector::iterator begin() { return parent->sections_.begin(); } //------------------------------------------------------------------------------ std::vector::iterator end() { return parent->sections_.end(); } //------------------------------------------------------------------------------ std::vector::const_iterator begin() const { return parent->sections_.cbegin(); } //------------------------------------------------------------------------------ std::vector::const_iterator end() const { return parent->sections_.cend(); } //------------------------------------------------------------------------------ private: elfio* parent; } sections; //------------------------------------------------------------------------------ public: friend class Segments; class Segments { public: //------------------------------------------------------------------------------ Segments( elfio* parent_ ) : parent( parent_ ) {} //------------------------------------------------------------------------------ Elf_Half size() const { return (Elf_Half)parent->segments_.size(); } //------------------------------------------------------------------------------ segment* operator[]( unsigned int index ) const { return parent->segments_[index]; } //------------------------------------------------------------------------------ segment* add() { return parent->create_segment(); } //------------------------------------------------------------------------------ std::vector::iterator begin() { return parent->segments_.begin(); } //------------------------------------------------------------------------------ std::vector::iterator end() { return parent->segments_.end(); } //------------------------------------------------------------------------------ std::vector::const_iterator begin() const { return parent->segments_.cbegin(); } //------------------------------------------------------------------------------ std::vector::const_iterator end() const { return parent->segments_.cend(); } //------------------------------------------------------------------------------ private: elfio* parent; } segments; //------------------------------------------------------------------------------ private: elf_header* header; std::vector sections_; std::vector segments_; endianess_convertor convertor; Elf_Xword current_file_pos; }; } // namespace ELFIO /*** Start of inlined file: elfio_symbols.hpp ***/ #ifndef ELFIO_SYMBOLS_HPP #define ELFIO_SYMBOLS_HPP namespace ELFIO { //------------------------------------------------------------------------------ template class symbol_section_accessor_template { public: //------------------------------------------------------------------------------ symbol_section_accessor_template( const elfio& elf_file_, S* symbol_section_ ) : elf_file( elf_file_ ), symbol_section( symbol_section_ ) { find_hash_section(); } //------------------------------------------------------------------------------ Elf_Xword get_symbols_num() const { Elf_Xword nRet = 0; if ( 0 != symbol_section->get_entry_size() ) { nRet = symbol_section->get_size() / symbol_section->get_entry_size(); } return nRet; } //------------------------------------------------------------------------------ bool get_symbol( Elf_Xword index, std::string& name, Elf64_Addr& value, Elf_Xword& size, unsigned char& bind, unsigned char& type, Elf_Half& section_index, unsigned char& other ) const { bool ret = false; if ( elf_file.get_class() == ELFCLASS32 ) { ret = generic_get_symbol( index, name, value, size, bind, type, section_index, other ); } else { ret = generic_get_symbol( index, name, value, size, bind, type, section_index, other ); } return ret; } //------------------------------------------------------------------------------ bool get_symbol( const std::string& name, Elf64_Addr& value, Elf_Xword& size, unsigned char& bind, unsigned char& type, Elf_Half& section_index, unsigned char& other ) const { bool ret = false; if ( 0 != get_hash_table_index() ) { Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data(); Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() + sizeof( Elf_Word ) ); Elf_Word val = elf_hash( (const unsigned char*)name.c_str() ); Elf_Word y = *(const Elf_Word*)( hash_section->get_data() + ( 2 + val % nbucket ) * sizeof( Elf_Word ) ); std::string str; get_symbol( y, str, value, size, bind, type, section_index, other ); while ( str != name && STN_UNDEF != y && y < nchain ) { y = *(const Elf_Word*)( hash_section->get_data() + ( 2 + nbucket + y ) * sizeof( Elf_Word ) ); get_symbol( y, str, value, size, bind, type, section_index, other ); } if ( str == name ) { ret = true; } } else { for ( Elf_Xword i = 0; i < get_symbols_num() && !ret; i++ ) { std::string symbol_name; if ( get_symbol( i, symbol_name, value, size, bind, type, section_index, other ) ) { if ( symbol_name == name ) { ret = true; } } } } return ret; } //------------------------------------------------------------------------------ bool get_symbol( const Elf64_Addr& value, std::string& name, Elf_Xword& size, unsigned char& bind, unsigned char& type, Elf_Half& section_index, unsigned char& other ) const { const endianess_convertor& convertor = elf_file.get_convertor(); Elf_Xword idx = 0; bool match = false; Elf64_Addr v = 0; if ( elf_file.get_class() == ELFCLASS32 ) { match = generic_search_symbols( [&]( const Elf32_Sym* sym ) { return convertor( sym->st_value ) == value; }, idx ); } else { match = generic_search_symbols( [&]( const Elf64_Sym* sym ) { return convertor( sym->st_value ) == value; }, idx ); } if ( match ) { return get_symbol( idx, name, v, size, bind, type, section_index, other ); } return false; } //------------------------------------------------------------------------------ Elf_Word add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, unsigned char info, unsigned char other, Elf_Half shndx ) { Elf_Word nRet; if ( symbol_section->get_size() == 0 ) { if ( elf_file.get_class() == ELFCLASS32 ) { nRet = generic_add_symbol( 0, 0, 0, 0, 0, 0 ); } else { nRet = generic_add_symbol( 0, 0, 0, 0, 0, 0 ); } } if ( elf_file.get_class() == ELFCLASS32 ) { nRet = generic_add_symbol( name, value, size, info, other, shndx ); } else { nRet = generic_add_symbol( name, value, size, info, other, shndx ); } return nRet; } //------------------------------------------------------------------------------ Elf_Word add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, unsigned char bind, unsigned char type, unsigned char other, Elf_Half shndx ) { return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx ); } //------------------------------------------------------------------------------ Elf_Word add_symbol( string_section_accessor& pStrWriter, const char* str, Elf64_Addr value, Elf_Xword size, unsigned char info, unsigned char other, Elf_Half shndx ) { Elf_Word index = pStrWriter.add_string( str ); return add_symbol( index, value, size, info, other, shndx ); } //------------------------------------------------------------------------------ Elf_Word add_symbol( string_section_accessor& pStrWriter, const char* str, Elf64_Addr value, Elf_Xword size, unsigned char bind, unsigned char type, unsigned char other, Elf_Half shndx ) { return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx ); } //------------------------------------------------------------------------------ Elf_Xword arrange_local_symbols( std::function func = nullptr ) { int nRet = 0; if ( elf_file.get_class() == ELFCLASS32 ) { nRet = generic_arrange_local_symbols( func ); } else { nRet = generic_arrange_local_symbols( func ); } return nRet; } //------------------------------------------------------------------------------ private: //------------------------------------------------------------------------------ void find_hash_section() { hash_section = 0; hash_section_index = 0; Elf_Half nSecNo = elf_file.sections.size(); for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) { const section* sec = elf_file.sections[i]; if ( sec->get_link() == symbol_section->get_index() ) { hash_section = sec; hash_section_index = i; } } } //------------------------------------------------------------------------------ Elf_Half get_string_table_index() const { return (Elf_Half)symbol_section->get_link(); } //------------------------------------------------------------------------------ Elf_Half get_hash_table_index() const { return hash_section_index; } //------------------------------------------------------------------------------ template const T* generic_get_symbol_ptr( Elf_Xword index ) const { if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) { const T* pSym = reinterpret_cast( symbol_section->get_data() + index * symbol_section->get_entry_size() ); return pSym; } return nullptr; } //------------------------------------------------------------------------------ template bool generic_search_symbols( std::function match, Elf_Xword& idx ) const { for ( Elf_Xword i = 0; i < get_symbols_num(); i++ ) { const T* symPtr = generic_get_symbol_ptr( i ); if ( symPtr == nullptr ) return false; if ( match( symPtr ) ) { idx = i; return true; } } return false; } //------------------------------------------------------------------------------ template bool generic_get_symbol( Elf_Xword index, std::string& name, Elf64_Addr& value, Elf_Xword& size, unsigned char& bind, unsigned char& type, Elf_Half& section_index, unsigned char& other ) const { bool ret = false; if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) { const T* pSym = reinterpret_cast( symbol_section->get_data() + index * symbol_section->get_entry_size() ); const endianess_convertor& convertor = elf_file.get_convertor(); section* string_section = elf_file.sections[get_string_table_index()]; string_section_accessor str_reader( string_section ); const char* pStr = str_reader.get_string( convertor( pSym->st_name ) ); if ( 0 != pStr ) { name = pStr; } value = convertor( pSym->st_value ); size = convertor( pSym->st_size ); bind = ELF_ST_BIND( pSym->st_info ); type = ELF_ST_TYPE( pSym->st_info ); section_index = convertor( pSym->st_shndx ); other = pSym->st_other; ret = true; } return ret; } //------------------------------------------------------------------------------ template Elf_Word generic_add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, unsigned char info, unsigned char other, Elf_Half shndx ) { const endianess_convertor& convertor = elf_file.get_convertor(); T entry; entry.st_name = convertor( name ); entry.st_value = value; entry.st_value = convertor( entry.st_value ); entry.st_size = size; entry.st_size = convertor( entry.st_size ); entry.st_info = convertor( info ); entry.st_other = convertor( other ); entry.st_shndx = convertor( shndx ); symbol_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1; return nRet; } //------------------------------------------------------------------------------ template Elf_Xword generic_arrange_local_symbols( std::function func ) { const endianess_convertor& convertor = elf_file.get_convertor(); const Elf_Xword size = symbol_section->get_entry_size(); Elf_Xword first_not_local = 1; // Skip the first entry. It is always NOTYPE Elf_Xword current = 0; Elf_Xword count = get_symbols_num(); while ( true ) { T* p1 = nullptr; T* p2 = nullptr; while ( first_not_local < count ) { p1 = const_cast( generic_get_symbol_ptr( first_not_local ) ); if ( ELF_ST_BIND( convertor( p1->st_info ) ) != STB_LOCAL ) break; ++first_not_local; } current = first_not_local + 1; while ( current < count ) { p2 = const_cast( generic_get_symbol_ptr( current ) ); if ( ELF_ST_BIND( convertor( p2->st_info ) ) == STB_LOCAL ) break; ++current; } if ( first_not_local < count && current < count ) { if ( func ) func( first_not_local, current ); // Swap the symbols T tmp; std::copy( p1, p1 + 1, &tmp ); std::copy( p2, p2 + 1, p1 ); std::copy( &tmp, &tmp + 1, p2 ); } else { // Update 'info' field of the section symbol_section->set_info( first_not_local ); break; } } // Elf_Word nRet = symbol_section->get_size() / sizeof(entry) - 1; return first_not_local; } //------------------------------------------------------------------------------ private: const elfio& elf_file; S* symbol_section; Elf_Half hash_section_index; const section* hash_section; }; using symbol_section_accessor = symbol_section_accessor_template
; using const_symbol_section_accessor = symbol_section_accessor_template; } // namespace ELFIO #endif // ELFIO_SYMBOLS_HPP /*** End of inlined file: elfio_symbols.hpp ***/ /*** Start of inlined file: elfio_note.hpp ***/ #ifndef ELFIO_NOTE_HPP #define ELFIO_NOTE_HPP namespace ELFIO { //------------------------------------------------------------------------------ // There are discrepancies in documentations. SCO documentation // (http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section) // requires 8 byte entries alignment for 64-bit ELF file, // but Oracle's definition uses the same structure // for 32-bit and 64-bit formats. // (https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html) // // It looks like EM_X86_64 Linux implementation is similar to Oracle's // definition. Therefore, the same alignment works for both formats //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ template class note_section_accessor_template { public: //------------------------------------------------------------------------------ note_section_accessor_template( const elfio& elf_file_, S* section_ ) : elf_file( elf_file_ ), note_section( section_ ) { process_section(); } //------------------------------------------------------------------------------ Elf_Word get_notes_num() const { return (Elf_Word)note_start_positions.size(); } //------------------------------------------------------------------------------ bool get_note( Elf_Word index, Elf_Word& type, std::string& name, void*& desc, Elf_Word& descSize ) const { if ( index >= note_section->get_size() ) { return false; } const char* pData = note_section->get_data() + note_start_positions[index]; int align = sizeof( Elf_Word ); const endianess_convertor& convertor = elf_file.get_convertor(); type = convertor( *(const Elf_Word*)( pData + 2 * align ) ); Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) ); descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) ); Elf_Xword max_name_size = note_section->get_size() - note_start_positions[index]; if ( namesz < 1 || namesz > max_name_size || (Elf_Xword)namesz + descSize > max_name_size ) { return false; } name.assign( pData + 3 * align, namesz - 1 ); if ( 0 == descSize ) { desc = 0; } else { desc = const_cast( pData + 3 * align + ( ( namesz + align - 1 ) / align ) * align ); } return true; } //------------------------------------------------------------------------------ void add_note( Elf_Word type, const std::string& name, const void* desc, Elf_Word descSize ) { const endianess_convertor& convertor = elf_file.get_convertor(); int align = sizeof( Elf_Word ); Elf_Word nameLen = (Elf_Word)name.size() + 1; Elf_Word nameLenConv = convertor( nameLen ); std::string buffer( reinterpret_cast( &nameLenConv ), align ); Elf_Word descSizeConv = convertor( descSize ); buffer.append( reinterpret_cast( &descSizeConv ), align ); type = convertor( type ); buffer.append( reinterpret_cast( &type ), align ); buffer.append( name ); buffer.append( 1, '\x00' ); const char pad[] = { '\0', '\0', '\0', '\0' }; if ( nameLen % align != 0 ) { buffer.append( pad, align - nameLen % align ); } if ( desc != 0 && descSize != 0 ) { buffer.append( reinterpret_cast( desc ), descSize ); if ( descSize % align != 0 ) { buffer.append( pad, align - descSize % align ); } } note_start_positions.push_back( note_section->get_size() ); note_section->append_data( buffer ); } private: //------------------------------------------------------------------------------ void process_section() { const endianess_convertor& convertor = elf_file.get_convertor(); const char* data = note_section->get_data(); Elf_Xword size = note_section->get_size(); Elf_Xword current = 0; note_start_positions.clear(); // Is it empty? if ( 0 == data || 0 == size ) { return; } Elf_Word align = sizeof( Elf_Word ); while ( current + (Elf_Xword)3 * align <= size ) { note_start_positions.push_back( current ); Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) ); Elf_Word descsz = convertor( *(const Elf_Word*)( data + current + sizeof( namesz ) ) ); current += (Elf_Xword)3 * sizeof( Elf_Word ) + ( ( namesz + align - 1 ) / align ) * (Elf_Xword)align + ( ( descsz + align - 1 ) / align ) * (Elf_Xword)align; } } //------------------------------------------------------------------------------ private: const elfio& elf_file; S* note_section; std::vector note_start_positions; }; using note_section_accessor = note_section_accessor_template
; using const_note_section_accessor = note_section_accessor_template; } // namespace ELFIO #endif // ELFIO_NOTE_HPP /*** End of inlined file: elfio_note.hpp ***/ /*** Start of inlined file: elfio_relocation.hpp ***/ #ifndef ELFIO_RELOCATION_HPP #define ELFIO_RELOCATION_HPP namespace ELFIO { template struct get_sym_and_type; template <> struct get_sym_and_type { static int get_r_sym( Elf_Xword info ) { return ELF32_R_SYM( (Elf_Word)info ); } static int get_r_type( Elf_Xword info ) { return ELF32_R_TYPE( (Elf_Word)info ); } }; template <> struct get_sym_and_type { static int get_r_sym( Elf_Xword info ) { return ELF32_R_SYM( (Elf_Word)info ); } static int get_r_type( Elf_Xword info ) { return ELF32_R_TYPE( (Elf_Word)info ); } }; template <> struct get_sym_and_type { static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } }; template <> struct get_sym_and_type { static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } }; //------------------------------------------------------------------------------ template class relocation_section_accessor_template { public: //------------------------------------------------------------------------------ relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) : elf_file( elf_file_ ), relocation_section( section_ ) { } //------------------------------------------------------------------------------ Elf_Xword get_entries_num() const { Elf_Xword nRet = 0; if ( 0 != relocation_section->get_entry_size() ) { nRet = relocation_section->get_size() / relocation_section->get_entry_size(); } return nRet; } //------------------------------------------------------------------------------ bool get_entry( Elf_Xword index, Elf64_Addr& offset, Elf_Word& symbol, Elf_Word& type, Elf_Sxword& addend ) const { if ( index >= get_entries_num() ) { // Is index valid return false; } if ( elf_file.get_class() == ELFCLASS32 ) { if ( SHT_REL == relocation_section->get_type() ) { generic_get_entry_rel( index, offset, symbol, type, addend ); } else if ( SHT_RELA == relocation_section->get_type() ) { generic_get_entry_rela( index, offset, symbol, type, addend ); } } else { if ( SHT_REL == relocation_section->get_type() ) { generic_get_entry_rel( index, offset, symbol, type, addend ); } else if ( SHT_RELA == relocation_section->get_type() ) { generic_get_entry_rela( index, offset, symbol, type, addend ); } } return true; } //------------------------------------------------------------------------------ bool get_entry( Elf_Xword index, Elf64_Addr& offset, Elf64_Addr& symbolValue, std::string& symbolName, Elf_Word& type, Elf_Sxword& addend, Elf_Sxword& calcValue ) const { // Do regular job Elf_Word symbol; bool ret = get_entry( index, offset, symbol, type, addend ); // Find the symbol Elf_Xword size; unsigned char bind; unsigned char symbolType; Elf_Half section; unsigned char other; symbol_section_accessor symbols( elf_file, elf_file.sections[get_symbol_table_index()] ); ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size, bind, symbolType, section, other ); if ( ret ) { // Was it successful? switch ( type ) { case R_386_NONE: // none calcValue = 0; break; case R_386_32: // S + A calcValue = symbolValue + addend; break; case R_386_PC32: // S + A - P calcValue = symbolValue + addend - offset; break; case R_386_GOT32: // G + A - P calcValue = 0; break; case R_386_PLT32: // L + A - P calcValue = 0; break; case R_386_COPY: // none calcValue = 0; break; case R_386_GLOB_DAT: // S case R_386_JMP_SLOT: // S calcValue = symbolValue; break; case R_386_RELATIVE: // B + A calcValue = addend; break; case R_386_GOTOFF: // S + A - GOT calcValue = 0; break; case R_386_GOTPC: // GOT + A - P calcValue = 0; break; default: // Not recognized symbol! calcValue = 0; break; } } return ret; } //------------------------------------------------------------------------------ bool set_entry( Elf_Xword index, Elf64_Addr offset, Elf_Word symbol, Elf_Word type, Elf_Sxword addend ) { if ( index >= get_entries_num() ) { // Is index valid return false; } if ( elf_file.get_class() == ELFCLASS32 ) { if ( SHT_REL == relocation_section->get_type() ) { generic_set_entry_rel( index, offset, symbol, type, addend ); } else if ( SHT_RELA == relocation_section->get_type() ) { generic_set_entry_rela( index, offset, symbol, type, addend ); } } else { if ( SHT_REL == relocation_section->get_type() ) { generic_set_entry_rel( index, offset, symbol, type, addend ); } else if ( SHT_RELA == relocation_section->get_type() ) { generic_set_entry_rela( index, offset, symbol, type, addend ); } } return true; } //------------------------------------------------------------------------------ void add_entry( Elf64_Addr offset, Elf_Xword info ) { if ( elf_file.get_class() == ELFCLASS32 ) { generic_add_entry( offset, info ); } else { generic_add_entry( offset, info ); } } //------------------------------------------------------------------------------ void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type ) { Elf_Xword info; if ( elf_file.get_class() == ELFCLASS32 ) { info = ELF32_R_INFO( (Elf_Xword)symbol, type ); } else { info = ELF64_R_INFO( (Elf_Xword)symbol, type ); } add_entry( offset, info ); } //------------------------------------------------------------------------------ void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) { if ( elf_file.get_class() == ELFCLASS32 ) { generic_add_entry( offset, info, addend ); } else { generic_add_entry( offset, info, addend ); } } //------------------------------------------------------------------------------ void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type, Elf_Sxword addend ) { Elf_Xword info; if ( elf_file.get_class() == ELFCLASS32 ) { info = ELF32_R_INFO( (Elf_Xword)symbol, type ); } else { info = ELF64_R_INFO( (Elf_Xword)symbol, type ); } add_entry( offset, info, addend ); } //------------------------------------------------------------------------------ void add_entry( string_section_accessor str_writer, const char* str, symbol_section_accessor sym_writer, Elf64_Addr value, Elf_Word size, unsigned char sym_info, unsigned char other, Elf_Half shndx, Elf64_Addr offset, unsigned char type ) { Elf_Word str_index = str_writer.add_string( str ); Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size, sym_info, other, shndx ); add_entry( offset, sym_index, type ); } //------------------------------------------------------------------------------ void swap_symbols( Elf_Xword first, Elf_Xword second ) { Elf64_Addr offset; Elf_Word symbol; Elf_Word rtype; Elf_Sxword addend; for ( Elf_Word i = 0; i < get_entries_num(); i++ ) { get_entry( i, offset, symbol, rtype, addend ); if ( symbol == first ) { set_entry( i, offset, (Elf_Word)second, rtype, addend ); } if ( symbol == second ) { set_entry( i, offset, (Elf_Word)first, rtype, addend ); } } } //------------------------------------------------------------------------------ private: //------------------------------------------------------------------------------ Elf_Half get_symbol_table_index() const { return (Elf_Half)relocation_section->get_link(); } //------------------------------------------------------------------------------ template void generic_get_entry_rel( Elf_Xword index, Elf64_Addr& offset, Elf_Word& symbol, Elf_Word& type, Elf_Sxword& addend ) const { const endianess_convertor& convertor = elf_file.get_convertor(); const T* pEntry = reinterpret_cast( relocation_section->get_data() + index * relocation_section->get_entry_size() ); offset = convertor( pEntry->r_offset ); Elf_Xword tmp = convertor( pEntry->r_info ); symbol = get_sym_and_type::get_r_sym( tmp ); type = get_sym_and_type::get_r_type( tmp ); addend = 0; } //------------------------------------------------------------------------------ template void generic_get_entry_rela( Elf_Xword index, Elf64_Addr& offset, Elf_Word& symbol, Elf_Word& type, Elf_Sxword& addend ) const { const endianess_convertor& convertor = elf_file.get_convertor(); const T* pEntry = reinterpret_cast( relocation_section->get_data() + index * relocation_section->get_entry_size() ); offset = convertor( pEntry->r_offset ); Elf_Xword tmp = convertor( pEntry->r_info ); symbol = get_sym_and_type::get_r_sym( tmp ); type = get_sym_and_type::get_r_type( tmp ); addend = convertor( pEntry->r_addend ); } //------------------------------------------------------------------------------ template void generic_set_entry_rel( Elf_Xword index, Elf64_Addr offset, Elf_Word symbol, Elf_Word type, Elf_Sxword ) { const endianess_convertor& convertor = elf_file.get_convertor(); T* pEntry = const_cast( reinterpret_cast( relocation_section->get_data() + index * relocation_section->get_entry_size() ) ); if ( elf_file.get_class() == ELFCLASS32 ) { pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); } else { pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); } pEntry->r_offset = offset; pEntry->r_offset = convertor( pEntry->r_offset ); pEntry->r_info = convertor( pEntry->r_info ); } //------------------------------------------------------------------------------ template void generic_set_entry_rela( Elf_Xword index, Elf64_Addr offset, Elf_Word symbol, Elf_Word type, Elf_Sxword addend ) { const endianess_convertor& convertor = elf_file.get_convertor(); T* pEntry = const_cast( reinterpret_cast( relocation_section->get_data() + index * relocation_section->get_entry_size() ) ); if ( elf_file.get_class() == ELFCLASS32 ) { pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); } else { pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); } pEntry->r_offset = offset; pEntry->r_addend = addend; pEntry->r_offset = convertor( pEntry->r_offset ); pEntry->r_info = convertor( pEntry->r_info ); pEntry->r_addend = convertor( pEntry->r_addend ); } //------------------------------------------------------------------------------ template void generic_add_entry( Elf64_Addr offset, Elf_Xword info ) { const endianess_convertor& convertor = elf_file.get_convertor(); T entry; entry.r_offset = offset; entry.r_info = info; entry.r_offset = convertor( entry.r_offset ); entry.r_info = convertor( entry.r_info ); relocation_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); } //------------------------------------------------------------------------------ template void generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) { const endianess_convertor& convertor = elf_file.get_convertor(); T entry; entry.r_offset = offset; entry.r_info = info; entry.r_addend = addend; entry.r_offset = convertor( entry.r_offset ); entry.r_info = convertor( entry.r_info ); entry.r_addend = convertor( entry.r_addend ); relocation_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); } //------------------------------------------------------------------------------ private: const elfio& elf_file; S* relocation_section; }; using relocation_section_accessor = relocation_section_accessor_template
; using const_relocation_section_accessor = relocation_section_accessor_template; } // namespace ELFIO #endif // ELFIO_RELOCATION_HPP /*** End of inlined file: elfio_relocation.hpp ***/ /*** Start of inlined file: elfio_dynamic.hpp ***/ #ifndef ELFIO_DYNAMIC_HPP #define ELFIO_DYNAMIC_HPP namespace ELFIO { //------------------------------------------------------------------------------ template class dynamic_section_accessor_template { public: //------------------------------------------------------------------------------ dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) : elf_file( elf_file_ ), dynamic_section( section_ ) { } //------------------------------------------------------------------------------ Elf_Xword get_entries_num() const { Elf_Xword nRet = 0; if ( 0 != dynamic_section->get_entry_size() ) { nRet = dynamic_section->get_size() / dynamic_section->get_entry_size(); } return nRet; } //------------------------------------------------------------------------------ bool get_entry( Elf_Xword index, Elf_Xword& tag, Elf_Xword& value, std::string& str ) const { if ( index >= get_entries_num() ) { // Is index valid return false; } if ( elf_file.get_class() == ELFCLASS32 ) { generic_get_entry_dyn( index, tag, value ); } else { generic_get_entry_dyn( index, tag, value ); } // If the tag may have a string table reference, prepare the string if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH || tag == DT_RUNPATH ) { string_section_accessor strsec = elf_file.sections[get_string_table_index()]; const char* result = strsec.get_string( value ); if ( 0 == result ) { str.clear(); return false; } str = result; } else { str.clear(); } return true; } //------------------------------------------------------------------------------ void add_entry( Elf_Xword tag, Elf_Xword value ) { if ( elf_file.get_class() == ELFCLASS32 ) { generic_add_entry( tag, value ); } else { generic_add_entry( tag, value ); } } //------------------------------------------------------------------------------ void add_entry( Elf_Xword tag, const std::string& str ) { string_section_accessor strsec = elf_file.sections[get_string_table_index()]; Elf_Xword value = strsec.add_string( str ); add_entry( tag, value ); } //------------------------------------------------------------------------------ private: //------------------------------------------------------------------------------ Elf_Half get_string_table_index() const { return (Elf_Half)dynamic_section->get_link(); } //------------------------------------------------------------------------------ template void generic_get_entry_dyn( Elf_Xword index, Elf_Xword& tag, Elf_Xword& value ) const { const endianess_convertor& convertor = elf_file.get_convertor(); // Check unusual case when dynamic section has no data if ( dynamic_section->get_data() == 0 || ( index + 1 ) * dynamic_section->get_entry_size() > dynamic_section->get_size() ) { tag = DT_NULL; value = 0; return; } const T* pEntry = reinterpret_cast( dynamic_section->get_data() + index * dynamic_section->get_entry_size() ); tag = convertor( pEntry->d_tag ); switch ( tag ) { case DT_NULL: case DT_SYMBOLIC: case DT_TEXTREL: case DT_BIND_NOW: value = 0; break; case DT_NEEDED: case DT_PLTRELSZ: case DT_RELASZ: case DT_RELAENT: case DT_STRSZ: case DT_SYMENT: case DT_SONAME: case DT_RPATH: case DT_RELSZ: case DT_RELENT: case DT_PLTREL: case DT_INIT_ARRAYSZ: case DT_FINI_ARRAYSZ: case DT_RUNPATH: case DT_FLAGS: case DT_PREINIT_ARRAYSZ: value = convertor( pEntry->d_un.d_val ); break; case DT_PLTGOT: case DT_HASH: case DT_STRTAB: case DT_SYMTAB: case DT_RELA: case DT_INIT: case DT_FINI: case DT_REL: case DT_DEBUG: case DT_JMPREL: case DT_INIT_ARRAY: case DT_FINI_ARRAY: case DT_PREINIT_ARRAY: default: value = convertor( pEntry->d_un.d_ptr ); break; } } //------------------------------------------------------------------------------ template void generic_add_entry( Elf_Xword tag, Elf_Xword value ) { const endianess_convertor& convertor = elf_file.get_convertor(); T entry; switch ( tag ) { case DT_NULL: case DT_SYMBOLIC: case DT_TEXTREL: case DT_BIND_NOW: value = 0; case DT_NEEDED: case DT_PLTRELSZ: case DT_RELASZ: case DT_RELAENT: case DT_STRSZ: case DT_SYMENT: case DT_SONAME: case DT_RPATH: case DT_RELSZ: case DT_RELENT: case DT_PLTREL: case DT_INIT_ARRAYSZ: case DT_FINI_ARRAYSZ: case DT_RUNPATH: case DT_FLAGS: case DT_PREINIT_ARRAYSZ: entry.d_un.d_val = convertor( value ); break; case DT_PLTGOT: case DT_HASH: case DT_STRTAB: case DT_SYMTAB: case DT_RELA: case DT_INIT: case DT_FINI: case DT_REL: case DT_DEBUG: case DT_JMPREL: case DT_INIT_ARRAY: case DT_FINI_ARRAY: case DT_PREINIT_ARRAY: default: entry.d_un.d_ptr = convertor( value ); break; } entry.d_tag = convertor( tag ); dynamic_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); } //------------------------------------------------------------------------------ private: const elfio& elf_file; S* dynamic_section; }; using dynamic_section_accessor = dynamic_section_accessor_template
; using const_dynamic_section_accessor = dynamic_section_accessor_template; } // namespace ELFIO #endif // ELFIO_DYNAMIC_HPP /*** End of inlined file: elfio_dynamic.hpp ***/ /*** Start of inlined file: elfio_modinfo.hpp ***/ #ifndef ELFIO_MODINFO_HPP #define ELFIO_MODINFO_HPP #include #include namespace ELFIO { //------------------------------------------------------------------------------ template class modinfo_section_accessor_template { public: //------------------------------------------------------------------------------ modinfo_section_accessor_template( S* section_ ) : modinfo_section( section_ ) { process_section(); } //------------------------------------------------------------------------------ Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); } //------------------------------------------------------------------------------ bool get_attribute( Elf_Word no, std::string& field, std::string& value ) const { if ( no < content.size() ) { field = content[no].first; value = content[no].second; return true; } return false; } //------------------------------------------------------------------------------ bool get_attribute( std::string field_name, std::string& value ) const { for ( auto i = content.begin(); i != content.end(); i++ ) { if ( field_name == i->first ) { value = i->second; return true; } } return false; } //------------------------------------------------------------------------------ Elf_Word add_attribute( std::string field, std::string value ) { Elf_Word current_position = 0; if ( modinfo_section ) { // Strings are addeded to the end of the current section data current_position = (Elf_Word)modinfo_section->get_size(); std::string attribute = field + "=" + value; modinfo_section->append_data( attribute + '\0' ); content.push_back( std::pair( field, value ) ); } return current_position; } //------------------------------------------------------------------------------ private: void process_section() { const char* pdata = modinfo_section->get_data(); if ( pdata ) { ELFIO::Elf_Xword i = 0; while ( i < modinfo_section->get_size() ) { while ( i < modinfo_section->get_size() && !pdata[i] ) i++; if ( i < modinfo_section->get_size() ) { std::string info = pdata + i; size_t loc = info.find( '=' ); std::pair attribute( info.substr( 0, loc ), info.substr( loc + 1 ) ); content.push_back( attribute ); i += info.length(); } } } } //------------------------------------------------------------------------------ private: S* modinfo_section; std::vector> content; }; using modinfo_section_accessor = modinfo_section_accessor_template
; using const_modinfo_section_accessor = modinfo_section_accessor_template; } // namespace ELFIO #endif // ELFIO_MODINFO_HPP /*** End of inlined file: elfio_modinfo.hpp ***/ #ifdef _MSC_VER #pragma warning( pop ) #endif #endif // ELFIO_HPP /*** End of inlined file: elfio.hpp ***/ namespace ELFIO { static struct class_table_t { const char key; const char* str; } class_table[] = { { ELFCLASS32, "ELF32" }, { ELFCLASS64, "ELF64" }, }; static struct endian_table_t { const char key; const char* str; } endian_table[] = { { ELFDATANONE, "None" }, { ELFDATA2LSB, "Little endian" }, { ELFDATA2MSB, "Big endian" }, }; static struct version_table_t { const Elf64_Word key; const char* str; } version_table[] = { { EV_NONE, "None" }, { EV_CURRENT, "Current" }, }; static struct type_table_t { const Elf32_Half key; const char* str; } type_table[] = { { ET_NONE, "No file type" }, { ET_REL, "Relocatable file" }, { ET_EXEC, "Executable file" }, { ET_DYN, "Shared object file" }, { ET_CORE, "Core file" }, }; static struct machine_table_t { const Elf64_Half key; const char* str; } machine_table[] = { { EM_NONE, "No machine" }, { EM_M32, "AT&T WE 32100" }, { EM_SPARC, "SUN SPARC" }, { EM_386, "Intel 80386" }, { EM_68K, "Motorola m68k family" }, { EM_88K, "Motorola m88k family" }, { EM_486, "Intel 80486// Reserved for future use" }, { EM_860, "Intel 80860" }, { EM_MIPS, "MIPS R3000 (officially, big-endian only)" }, { EM_S370, "IBM System/370" }, { EM_MIPS_RS3_LE, "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" }, { EM_res011, "Reserved" }, { EM_res012, "Reserved" }, { EM_res013, "Reserved" }, { EM_res014, "Reserved" }, { EM_PARISC, "HPPA" }, { EM_res016, "Reserved" }, { EM_VPP550, "Fujitsu VPP500" }, { EM_SPARC32PLUS, "Sun's v8plus" }, { EM_960, "Intel 80960" }, { EM_PPC, "PowerPC" }, { EM_PPC64, "64-bit PowerPC" }, { EM_S390, "IBM S/390" }, { EM_SPU, "Sony/Toshiba/IBM SPU" }, { EM_res024, "Reserved" }, { EM_res025, "Reserved" }, { EM_res026, "Reserved" }, { EM_res027, "Reserved" }, { EM_res028, "Reserved" }, { EM_res029, "Reserved" }, { EM_res030, "Reserved" }, { EM_res031, "Reserved" }, { EM_res032, "Reserved" }, { EM_res033, "Reserved" }, { EM_res034, "Reserved" }, { EM_res035, "Reserved" }, { EM_V800, "NEC V800 series" }, { EM_FR20, "Fujitsu FR20" }, { EM_RH32, "TRW RH32" }, { EM_MCORE, "Motorola M*Core // May also be taken by Fujitsu MMA" }, { EM_RCE, "Old name for MCore" }, { EM_ARM, "ARM" }, { EM_OLD_ALPHA, "Digital Alpha" }, { EM_SH, "Renesas (formerly Hitachi) / SuperH SH" }, { EM_SPARCV9, "SPARC v9 64-bit" }, { EM_TRICORE, "Siemens Tricore embedded processor" }, { EM_ARC, "ARC Cores" }, { EM_H8_300, "Renesas (formerly Hitachi) H8/300" }, { EM_H8_300H, "Renesas (formerly Hitachi) H8/300H" }, { EM_H8S, "Renesas (formerly Hitachi) H8S" }, { EM_H8_500, "Renesas (formerly Hitachi) H8/500" }, { EM_IA_64, "Intel IA-64 Processor" }, { EM_MIPS_X, "Stanford MIPS-X" }, { EM_COLDFIRE, "Motorola Coldfire" }, { EM_68HC12, "Motorola M68HC12" }, { EM_MMA, "Fujitsu Multimedia Accelerator" }, { EM_PCP, "Siemens PCP" }, { EM_NCPU, "Sony nCPU embedded RISC processor" }, { EM_NDR1, "Denso NDR1 microprocesspr" }, { EM_STARCORE, "Motorola Star*Core processor" }, { EM_ME16, "Toyota ME16 processor" }, { EM_ST100, "STMicroelectronics ST100 processor" }, { EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor" }, { EM_X86_64, "Advanced Micro Devices X86-64 processor" }, { EM_PDSP, "Sony DSP Processor" }, { EM_PDP10, "Digital Equipment Corp. PDP-10" }, { EM_PDP11, "Digital Equipment Corp. PDP-11" }, { EM_FX66, "Siemens FX66 microcontroller" }, { EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller" }, { EM_ST7, "STMicroelectronics ST7 8-bit microcontroller" }, { EM_68HC16, "Motorola MC68HC16 Microcontroller" }, { EM_68HC11, "Motorola MC68HC11 Microcontroller" }, { EM_68HC08, "Motorola MC68HC08 Microcontroller" }, { EM_68HC05, "Motorola MC68HC05 Microcontroller" }, { EM_SVX, "Silicon Graphics SVx" }, { EM_ST19, "STMicroelectronics ST19 8-bit cpu" }, { EM_VAX, "Digital VAX" }, { EM_CRIS, "Axis Communications 32-bit embedded processor" }, { EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu" }, { EM_FIREPATH, "Element 14 64-bit DSP processor" }, { EM_ZSP, "LSI Logic's 16-bit DSP processor" }, { EM_MMIX, "Donald Knuth's educational 64-bit processor" }, { EM_HUANY, "Harvard's machine-independent format" }, { EM_PRISM, "SiTera Prism" }, { EM_AVR, "Atmel AVR 8-bit microcontroller" }, { EM_FR30, "Fujitsu FR30" }, { EM_D10V, "Mitsubishi D10V" }, { EM_D30V, "Mitsubishi D30V" }, { EM_V850, "NEC v850" }, { EM_M32R, "Renesas M32R (formerly Mitsubishi M32R)" }, { EM_MN10300, "Matsushita MN10300" }, { EM_MN10200, "Matsushita MN10200" }, { EM_PJ, "picoJava" }, { EM_OPENRISC, "OpenRISC 32-bit embedded processor" }, { EM_ARC_A5, "ARC Cores Tangent-A5" }, { EM_XTENSA, "Tensilica Xtensa Architecture" }, { EM_VIDEOCORE, "Alphamosaic VideoCore processor" }, { EM_TMM_GPP, "Thompson Multimedia General Purpose Processor" }, { EM_NS32K, "National Semiconductor 32000 series" }, { EM_TPC, "Tenor Network TPC processor" }, { EM_SNP1K, "Trebia SNP 1000 processor" }, { EM_ST200, "STMicroelectronics ST200 microcontroller" }, { EM_IP2K, "Ubicom IP2022 micro controller" }, { EM_MAX, "MAX Processor" }, { EM_CR, "National Semiconductor CompactRISC" }, { EM_F2MC16, "Fujitsu F2MC16" }, { EM_MSP430, "TI msp430 micro controller" }, { EM_BLACKFIN, "ADI Blackfin" }, { EM_SE_C33, "S1C33 Family of Seiko Epson processors" }, { EM_SEP, "Sharp embedded microprocessor" }, { EM_ARCA, "Arca RISC Microprocessor" }, { EM_UNICORE, "Microprocessor series from PKU-Unity Ltd. and MPRC of " "Peking University" }, { EM_EXCESS, "eXcess: 16/32/64-bit configurable embedded CPU" }, { EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor" }, { EM_ALTERA_NIOS2, "Altera Nios II soft-core processor" }, { EM_CRX, "National Semiconductor CRX" }, { EM_XGATE, "Motorola XGATE embedded processor" }, { EM_C166, "Infineon C16x/XC16x processor" }, { EM_M16C, "Renesas M16C series microprocessors" }, { EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller" }, { EM_CE, "Freescale Communication Engine RISC core" }, { EM_M32C, "Renesas M32C series microprocessors" }, { EM_res121, "Reserved" }, { EM_res122, "Reserved" }, { EM_res123, "Reserved" }, { EM_res124, "Reserved" }, { EM_res125, "Reserved" }, { EM_res126, "Reserved" }, { EM_res127, "Reserved" }, { EM_res128, "Reserved" }, { EM_res129, "Reserved" }, { EM_res130, "Reserved" }, { EM_TSK3000, "Altium TSK3000 core" }, { EM_RS08, "Freescale RS08 embedded processor" }, { EM_res133, "Reserved" }, { EM_ECOG2, "Cyan Technology eCOG2 microprocessor" }, { EM_SCORE, "Sunplus Score" }, { EM_SCORE7, "Sunplus S+core7 RISC processor" }, { EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor" }, { EM_VIDEOCORE3, "Broadcom VideoCore III processor" }, { EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" }, { EM_SE_C17, "Seiko Epson C17 family" }, { EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family" }, { EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family" }, { EM_TI_C5500, "Texas Instruments TMS320C55x DSP family" }, { EM_res143, "Reserved" }, { EM_res144, "Reserved" }, { EM_res145, "Reserved" }, { EM_res146, "Reserved" }, { EM_res147, "Reserved" }, { EM_res148, "Reserved" }, { EM_res149, "Reserved" }, { EM_res150, "Reserved" }, { EM_res151, "Reserved" }, { EM_res152, "Reserved" }, { EM_res153, "Reserved" }, { EM_res154, "Reserved" }, { EM_res155, "Reserved" }, { EM_res156, "Reserved" }, { EM_res157, "Reserved" }, { EM_res158, "Reserved" }, { EM_res159, "Reserved" }, { EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor" }, { EM_CYPRESS_M8C, "Cypress M8C microprocessor" }, { EM_R32C, "Renesas R32C series microprocessors" }, { EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family" }, { EM_QDSP6, "QUALCOMM DSP6 Processor" }, { EM_8051, "Intel 8051 and variants" }, { EM_STXP7X, "STMicroelectronics STxP7x family" }, { EM_NDS32, "Andes Technology compact code size embedded RISC processor family" }, { EM_ECOG1, "Cyan Technology eCOG1X family" }, { EM_ECOG1X, "Cyan Technology eCOG1X family" }, { EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core Micro-controllers" }, { EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor" }, { EM_MANIK, "M2000 Reconfigurable RISC Microprocessor" }, { EM_CRAYNV2, "Cray Inc. NV2 vector architecture" }, { EM_RX, "Renesas RX family" }, { EM_METAG, "Imagination Technologies META processor architecture" }, { EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture" }, { EM_ECOG16, "Cyan Technology eCOG16 family" }, { EM_CR16, "National Semiconductor CompactRISC 16-bit processor" }, { EM_ETPU, "Freescale Extended Time Processing Unit" }, { EM_SLE9X, "Infineon Technologies SLE9X core" }, { EM_L1OM, "Intel L1OM" }, { EM_INTEL181, "Reserved by Intel" }, { EM_INTEL182, "Reserved by Intel" }, { EM_res183, "Reserved by ARM" }, { EM_res184, "Reserved by ARM" }, { EM_AVR32, "Atmel Corporation 32-bit microprocessor family" }, { EM_STM8, "STMicroeletronics STM8 8-bit microcontroller" }, { EM_TILE64, "Tilera TILE64 multicore architecture family" }, { EM_TILEPRO, "Tilera TILEPro multicore architecture family" }, { EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core" }, { EM_CUDA, "NVIDIA CUDA architecture " }, }; static struct section_type_table_t { const Elf64_Half key; const char* str; } section_type_table[] = { { SHT_NULL, "NULL" }, { SHT_PROGBITS, "PROGBITS" }, { SHT_SYMTAB, "SYMTAB" }, { SHT_STRTAB, "STRTAB" }, { SHT_RELA, "RELA" }, { SHT_HASH, "HASH" }, { SHT_DYNAMIC, "DYNAMIC" }, { SHT_NOTE, "NOTE" }, { SHT_NOBITS, "NOBITS" }, { SHT_REL, "REL" }, { SHT_SHLIB, "SHLIB" }, { SHT_DYNSYM, "DYNSYM" }, { SHT_INIT_ARRAY, "INIT_ARRAY" }, { SHT_FINI_ARRAY, "FINI_ARRAY" }, { SHT_PREINIT_ARRAY, "PREINIT_ARRAY" }, { SHT_GROUP, "GROUP" }, { SHT_SYMTAB_SHNDX, "SYMTAB_SHNDX " }, }; static struct segment_type_table_t { const Elf_Word key; const char* str; } segment_type_table[] = { { PT_NULL, "NULL" }, { PT_LOAD, "LOAD" }, { PT_DYNAMIC, "DYNAMIC" }, { PT_INTERP, "INTERP" }, { PT_NOTE, "NOTE" }, { PT_SHLIB, "SHLIB" }, { PT_PHDR, "PHDR" }, { PT_TLS, "TLS" }, }; static struct segment_flag_table_t { const Elf_Word key; const char* str; } segment_flag_table[] = { { 0, "" }, { 1, "X" }, { 2, "W" }, { 3, "WX" }, { 4, "R" }, { 5, "RX" }, { 6, "RW" }, { 7, "RWX" }, }; static struct symbol_bind_t { const Elf_Word key; const char* str; } symbol_bind_table[] = { { STB_LOCAL, "LOCAL" }, { STB_GLOBAL, "GLOBAL" }, { STB_WEAK, "WEAK" }, { STB_LOOS, "LOOS" }, { STB_HIOS, "HIOS" }, { STB_MULTIDEF, "MULTIDEF" }, { STB_LOPROC, "LOPROC" }, { STB_HIPROC, "HIPROC" }, }; static struct symbol_type_t { const Elf_Word key; const char* str; } symbol_type_table[] = { { STT_NOTYPE, "NOTYPE" }, { STT_OBJECT, "OBJECT" }, { STT_FUNC, "FUNC" }, { STT_SECTION, "SECTION" }, { STT_FILE, "FILE" }, { STT_COMMON, "COMMON" }, { STT_TLS, "TLS" }, { STT_LOOS, "LOOS" }, { STT_HIOS, "HIOS" }, { STT_LOPROC, "LOPROC" }, { STT_HIPROC, "HIPROC" }, }; static struct dynamic_tag_t { const Elf_Word key; const char* str; } dynamic_tag_table[] = { { DT_NULL, "NULL" }, { DT_NEEDED, "NEEDED" }, { DT_PLTRELSZ, "PLTRELSZ" }, { DT_PLTGOT, "PLTGOT" }, { DT_HASH, "HASH" }, { DT_STRTAB, "STRTAB" }, { DT_SYMTAB, "SYMTAB" }, { DT_RELA, "RELA" }, { DT_RELASZ, "RELASZ" }, { DT_RELAENT, "RELAENT" }, { DT_STRSZ, "STRSZ" }, { DT_SYMENT, "SYMENT" }, { DT_INIT, "INIT" }, { DT_FINI, "FINI" }, { DT_SONAME, "SONAME" }, { DT_RPATH, "RPATH" }, { DT_SYMBOLIC, "SYMBOLIC" }, { DT_REL, "REL" }, { DT_RELSZ, "RELSZ" }, { DT_RELENT, "RELENT" }, { DT_PLTREL, "PLTREL" }, { DT_DEBUG, "DEBUG" }, { DT_TEXTREL, "TEXTREL" }, { DT_JMPREL, "JMPREL" }, { DT_BIND_NOW, "BIND_NOW" }, { DT_INIT_ARRAY, "INIT_ARRAY" }, { DT_FINI_ARRAY, "FINI_ARRAY" }, { DT_INIT_ARRAYSZ, "INIT_ARRAYSZ" }, { DT_FINI_ARRAYSZ, "FINI_ARRAYSZ" }, { DT_RUNPATH, "RUNPATH" }, { DT_FLAGS, "FLAGS" }, { DT_ENCODING, "ENCODING" }, { DT_PREINIT_ARRAY, "PREINIT_ARRAY" }, { DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ" }, { DT_MAXPOSTAGS, "MAXPOSTAGS" }, }; static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64; //------------------------------------------------------------------------------ class dump { #define DUMP_DEC_FORMAT( width ) \ std::setw( width ) << std::setfill( ' ' ) << std::dec << std::right #define DUMP_HEX_FORMAT( width ) \ std::setw( width ) << std::setfill( '0' ) << std::hex << std::right #define DUMP_STR_FORMAT( width ) \ std::setw( width ) << std::setfill( ' ' ) << std::hex << std::left public: //------------------------------------------------------------------------------ static void header( std::ostream& out, const elfio& reader ) { if ( !reader.get_header_size() ) { return; } out << "ELF Header" << std::endl << std::endl << " Class: " << str_class( reader.get_class() ) << std::endl << " Encoding: " << str_endian( reader.get_encoding() ) << std::endl << " ELFVersion: " << str_version( reader.get_elf_version() ) << std::endl << " Type: " << str_type( reader.get_type() ) << std::endl << " Machine: " << str_machine( reader.get_machine() ) << std::endl << " Version: " << str_version( reader.get_version() ) << std::endl << " Entry: " << "0x" << std::hex << reader.get_entry() << std::endl << " Flags: " << "0x" << std::hex << reader.get_flags() << std::endl << std::endl; } //------------------------------------------------------------------------------ static void section_headers( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.sections.size(); if ( n == 0 ) { return; } out << "Section Headers:" << std::endl; if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit out << "[ Nr ] Type Addr Size ES Flg Lk Inf " "Al Name" << std::endl; } else { // Output for 64-bit out << "[ Nr ] Type Addr Size " " ES Flg" << std::endl << " Lk Inf Al Name" << std::endl; } for ( Elf_Half i = 0; i < n; ++i ) { // For all sections section* sec = reader.sections[i]; section_header( out, i, sec, reader.get_class() ); } out << "Key to Flags: W (write), A (alloc), X (execute)\n\n" << std::endl; } //------------------------------------------------------------------------------ static void section_header( std::ostream& out, Elf_Half no, const section* sec, unsigned char elf_class ) { std::ios_base::fmtflags original_flags = out.flags(); if ( elf_class == ELFCLASS32 ) { // Output for 32-bit out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " " << DUMP_HEX_FORMAT( 8 ) << sec->get_address() << " " << DUMP_HEX_FORMAT( 8 ) << sec->get_size() << " " << DUMP_HEX_FORMAT( 2 ) << sec->get_entry_size() << " " << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " " << DUMP_HEX_FORMAT( 2 ) << sec->get_link() << " " << DUMP_HEX_FORMAT( 3 ) << sec->get_info() << " " << DUMP_HEX_FORMAT( 2 ) << sec->get_addr_align() << " " << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl; } else { // Output for 64-bit out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " " << DUMP_HEX_FORMAT( 16 ) << sec->get_address() << " " << DUMP_HEX_FORMAT( 16 ) << sec->get_size() << " " << DUMP_HEX_FORMAT( 4 ) << sec->get_entry_size() << " " << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " " << std::endl << " " << DUMP_HEX_FORMAT( 4 ) << sec->get_link() << " " << DUMP_HEX_FORMAT( 4 ) << sec->get_info() << " " << DUMP_HEX_FORMAT( 4 ) << sec->get_addr_align() << " " << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl; } out.flags( original_flags ); return; } //------------------------------------------------------------------------------ static void segment_headers( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.segments.size(); if ( n == 0 ) { return; } out << "Segment headers:" << std::endl; if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit out << "[ Nr ] Type VirtAddr PhysAddr FileSize Mem.Size " "Flags Align" << std::endl; } else { // Output for 64-bit out << "[ Nr ] Type VirtAddr PhysAddr " "Flags" << std::endl << " FileSize Mem.Size " "Align" << std::endl; } for ( Elf_Half i = 0; i < n; ++i ) { segment* seg = reader.segments[i]; segment_header( out, i, seg, reader.get_class() ); } out << std::endl; } //------------------------------------------------------------------------------ static void segment_header( std::ostream& out, Elf_Half no, const segment* seg, unsigned int elf_class ) { std::ios_base::fmtflags original_flags = out.flags(); if ( elf_class == ELFCLASS32 ) { // Output for 32-bit out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_virtual_address() << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_physical_address() << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_file_size() << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_memory_size() << " " << DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() ) << " " << DUMP_HEX_FORMAT( 8 ) << seg->get_align() << " " << std::endl; } else { // Output for 64-bit out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_virtual_address() << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_physical_address() << " " << DUMP_STR_FORMAT( 16 ) << str_segment_flag( seg->get_flags() ) << " " << std::endl << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_file_size() << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_memory_size() << " " << DUMP_HEX_FORMAT( 16 ) << seg->get_align() << " " << std::endl; } out.flags( original_flags ); } //------------------------------------------------------------------------------ static void symbol_tables( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.sections.size(); for ( Elf_Half i = 0; i < n; ++i ) { // For all sections section* sec = reader.sections[i]; if ( SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type() ) { symbol_section_accessor symbols( reader, sec ); Elf_Xword sym_no = symbols.get_symbols_num(); if ( sym_no > 0 ) { out << "Symbol table (" << sec->get_name() << ")" << std::endl; if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit out << "[ Nr ] Value Size Type Bind " "Sect Name" << std::endl; } else { // Output for 64-bit out << "[ Nr ] Value Size Type " " Bind Sect" << std::endl << " Name" << std::endl; } for ( Elf_Xword i = 0; i < sym_no; ++i ) { std::string name; Elf64_Addr value = 0; Elf_Xword size = 0; unsigned char bind = 0; unsigned char type = 0; Elf_Half section = 0; unsigned char other = 0; symbols.get_symbol( i, name, value, size, bind, type, section, other ); symbol_table( out, i, name, value, size, bind, type, section, reader.get_class() ); } out << std::endl; } } } } //------------------------------------------------------------------------------ static void symbol_table( std::ostream& out, Elf_Xword no, std::string& name, Elf64_Addr value, Elf_Xword size, unsigned char bind, unsigned char type, Elf_Half section, unsigned int elf_class ) { std::ios_base::fmtflags original_flags = out.flags(); if ( elf_class == ELFCLASS32 ) { // Output for 32-bit out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_HEX_FORMAT( 8 ) << value << " " << DUMP_HEX_FORMAT( 8 ) << size << " " << DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 ) << section << " " << DUMP_STR_FORMAT( 1 ) << name << " " << std::endl; } else { // Output for 64-bit out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_HEX_FORMAT( 16 ) << value << " " << DUMP_HEX_FORMAT( 16 ) << size << " " << DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 ) << section << " " << std::endl << " " << DUMP_STR_FORMAT( 1 ) << name << " " << std::endl; } out.flags( original_flags ); } //------------------------------------------------------------------------------ static void notes( std::ostream& out, const elfio& reader ) { Elf_Half no = reader.sections.size(); for ( Elf_Half i = 0; i < no; ++i ) { // For all sections section* sec = reader.sections[i]; if ( SHT_NOTE == sec->get_type() ) { // Look at notes note_section_accessor notes( reader, sec ); Elf_Word no_notes = notes.get_notes_num(); if ( no > 0 ) { out << "Note section (" << sec->get_name() << ")" << std::endl << " No Type Name" << std::endl; for ( Elf_Word j = 0; j < no_notes; ++j ) { // For all notes Elf_Word type; std::string name; void* desc; Elf_Word descsz; if ( notes.get_note( j, type, name, desc, descsz ) ) { // 'name' usually contains \0 at the end. Try to fix it name = name.c_str(); note( out, j, type, name ); } } out << std::endl; } } } } //------------------------------------------------------------------------------ static void modinfo( std::ostream& out, const elfio& reader ) { Elf_Half no = reader.sections.size(); for ( Elf_Half i = 0; i < no; ++i ) { // For all sections section* sec = reader.sections[i]; if ( ".modinfo" == sec->get_name() ) { // Look for the section out << "Section .modinfo" << std::endl; const_modinfo_section_accessor modinfo( sec ); for ( Elf_Word i = 0; i < modinfo.get_attribute_num(); i++ ) { std::string field; std::string value; if ( modinfo.get_attribute( i, field, value ) ) { out << " " << std::setw( 20 ) << field << std::setw( 0 ) << " = " << value << std::endl; } } out << std::endl; break; } } } //------------------------------------------------------------------------------ static void note( std::ostream& out, int no, Elf_Word type, const std::string& name ) { out << " [" << DUMP_DEC_FORMAT( 2 ) << no << "] " << DUMP_HEX_FORMAT( 8 ) << type << " " << DUMP_STR_FORMAT( 1 ) << name << std::endl; } //------------------------------------------------------------------------------ static void dynamic_tags( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.sections.size(); for ( Elf_Half i = 0; i < n; ++i ) { // For all sections section* sec = reader.sections[i]; if ( SHT_DYNAMIC == sec->get_type() ) { dynamic_section_accessor dynamic( reader, sec ); Elf_Xword dyn_no = dynamic.get_entries_num(); if ( dyn_no > 0 ) { out << "Dynamic section (" << sec->get_name() << ")" << std::endl; out << "[ Nr ] Tag Name/Value" << std::endl; for ( Elf_Xword i = 0; i < dyn_no; ++i ) { Elf_Xword tag = 0; Elf_Xword value = 0; std::string str; dynamic.get_entry( i, tag, value, str ); dynamic_tag( out, i, tag, value, str, reader.get_class() ); if ( DT_NULL == tag ) { break; } } out << std::endl; } } } } //------------------------------------------------------------------------------ static void dynamic_tag( std::ostream& out, Elf_Xword no, Elf_Xword tag, Elf_Xword value, std::string str, unsigned int /*elf_class*/ ) { out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " "; if ( str.empty() ) { out << DUMP_HEX_FORMAT( 16 ) << value << " "; } else { out << DUMP_STR_FORMAT( 32 ) << str << " "; } out << std::endl; } //------------------------------------------------------------------------------ static void section_data( std::ostream& out, const section* sec ) { std::ios_base::fmtflags original_flags = out.flags(); out << sec->get_name() << std::endl; const char* pdata = sec->get_data(); if ( pdata ) { ELFIO::Elf_Xword i; for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES ); ++i ) { if ( i % 16 == 0 ) { out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]"; } out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF ); if ( i % 16 == 15 ) { out << std::endl; } } if ( i % 16 != 0 ) { out << std::endl; } out.flags( original_flags ); } return; } //------------------------------------------------------------------------------ static void section_datas( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.sections.size(); if ( n == 0 ) { return; } out << "Section Data:" << std::endl; for ( Elf_Half i = 1; i < n; ++i ) { // For all sections section* sec = reader.sections[i]; if ( sec->get_type() == SHT_NOBITS ) { continue; } section_data( out, sec ); } out << std::endl; } //------------------------------------------------------------------------------ static void segment_data( std::ostream& out, Elf_Half no, const segment* seg ) { std::ios_base::fmtflags original_flags = out.flags(); out << "Segment # " << no << std::endl; const char* pdata = seg->get_data(); if ( pdata ) { ELFIO::Elf_Xword i; for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES ); ++i ) { if ( i % 16 == 0 ) { out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]"; } out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF ); if ( i % 16 == 15 ) { out << std::endl; } } if ( i % 16 != 0 ) { out << std::endl; } out.flags( original_flags ); } return; } //------------------------------------------------------------------------------ static void segment_datas( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.segments.size(); if ( n == 0 ) { return; } out << "Segment Data:" << std::endl; for ( Elf_Half i = 0; i < n; ++i ) { // For all sections segment* seg = reader.segments[i]; segment_data( out, i, seg ); } out << std::endl; } private: //------------------------------------------------------------------------------ template std::string static find_value_in_table( const T& table, const K& key ) { std::string res = "?"; for ( unsigned int i = 0; i < sizeof( table ) / sizeof( table[0] ); ++i ) { if ( table[i].key == key ) { res = table[i].str; break; } } return res; } //------------------------------------------------------------------------------ template static std::string format_assoc( const T& table, const K& key ) { std::string str = find_value_in_table( table, key ); if ( str == "?" ) { std::ostringstream oss; oss << str << " (0x" << std::hex << key << ")"; str = oss.str(); } return str; } //------------------------------------------------------------------------------ template static std::string format_assoc( const T& table, const char key ) { return format_assoc( table, (const int)key ); } //------------------------------------------------------------------------------ static std::string section_flags( Elf_Xword flags ) { std::string ret = ""; if ( flags & SHF_WRITE ) { ret += "W"; } if ( flags & SHF_ALLOC ) { ret += "A"; } if ( flags & SHF_EXECINSTR ) { ret += "X"; } return ret; } //------------------------------------------------------------------------------ #define STR_FUNC_TABLE( name ) \ template static std::string str_##name( const T key ) \ { \ return format_assoc( name##_table, key ); \ } STR_FUNC_TABLE( class ) STR_FUNC_TABLE( endian ) STR_FUNC_TABLE( version ) STR_FUNC_TABLE( type ) STR_FUNC_TABLE( machine ) STR_FUNC_TABLE( section_type ) STR_FUNC_TABLE( segment_type ) STR_FUNC_TABLE( segment_flag ) STR_FUNC_TABLE( symbol_bind ) STR_FUNC_TABLE( symbol_type ) STR_FUNC_TABLE( dynamic_tag ) #undef STR_FUNC_TABLE #undef DUMP_DEC_FORMAT #undef DUMP_HEX_FORMAT #undef DUMP_STR_FORMAT }; // class dump }; // namespace ELFIO #endif // ELFIO_DUMP_HPP /*** End of inlined file: elfio_dump.hpp ***/ ukui-biometric-auth/tests/kt-test-utils/cpp-stub/stub.h0000664000175000017500000002341715167732644022173 0ustar fengfeng#ifndef __STUB_H__ #define __STUB_H__ #ifdef _WIN32 //windows #include #include #else //linux #include #include #include #endif //c #include #include //c++ #include #define ADDR(CLASS_NAME,MEMBER_NAME) (&CLASS_NAME::MEMBER_NAME) /********************************************************** replace function **********************************************************/ #ifdef _WIN32 #define CACHEFLUSH(addr, size) FlushInstructionCache(GetCurrentProcess(), addr, size) #else #define CACHEFLUSH(addr, size) __builtin___clear_cache(addr, addr + size) #endif #if defined(__aarch64__) || defined(_M_ARM64) #define CODESIZE 16U #define CODESIZE_MIN 16U #define CODESIZE_MAX CODESIZE // ldr x9, +8 // br x9 // addr #define REPLACE_FAR(t, fn, fn_stub)\ ((uint32_t*)fn)[0] = 0x58000040 | 9;\ ((uint32_t*)fn)[1] = 0xd61f0120 | (9 << 5);\ *(long long *)(fn + 8) = (long long )fn_stub;\ CACHEFLUSH((char *)fn, CODESIZE); #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) #elif defined(__arm__) || defined(_M_ARM) #define CODESIZE 8U #define CODESIZE_MIN 8U #define CODESIZE_MAX CODESIZE // ldr pc, [pc, #-4] #define REPLACE_FAR(t, fn, fn_stub)\ ((uint32_t*)fn)[0] = 0xe51ff004;\ ((uint32_t*)fn)[1] = (uint32_t)fn_stub;\ CACHEFLUSH((char *)fn, CODESIZE); #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) #elif defined(__mips64) #define CACHEFLUSH(addr, size) __builtin___clear_cache(addr, addr + size) #define CODESIZE 80U #define CODESIZE_MIN 80U #define CODESIZE_MAX CODESIZE //mips没有PC指针,所以需�手动入栈出栈 //120000ce0: 67bdffe0 daddiu sp, sp, -32 //入栈 //120000ce4: ffbf0018 sd ra, 24(sp) //120000ce8: ffbe0010 sd s8, 16(sp) //120000cec: ffbc0008 sd gp, 8(sp) //120000cf0: 03a0f025 move s8, sp //120000d2c: 03c0e825 move sp, s8 //出栈 //120000d30: dfbf0018 ld ra, 24(sp) //120000d34: dfbe0010 ld s8, 16(sp) //120000d38: dfbc0008 ld gp, 8(sp) //120000d3c: 67bd0020 daddiu sp, sp, 32 //120000d40: 03e00008 jr ra #define REPLACE_FAR(t, fn, fn_stub)\ ((uint32_t *)fn)[0] = 0x67bdffe0;\ ((uint32_t *)fn)[1] = 0xffbf0018;\ ((uint32_t *)fn)[2] = 0xffbe0010;\ ((uint32_t *)fn)[3] = 0xffbc0008;\ ((uint32_t *)fn)[4] = 0x03a0f025;\ *(uint16_t *)(fn + 20) = (long long)fn_stub >> 32;\ *(fn + 22) = 0x19;\ *(fn + 23) = 0x24;\ ((uint32_t *)fn)[6] = 0x0019cc38;\ *(uint16_t *)(fn + 28) = (long long)fn_stub >> 16;\ *(fn + 30) = 0x39;\ *(fn + 31) = 0x37;\ ((uint32_t *)fn)[8] = 0x0019cc38;\ *(uint16_t *)(fn + 36) = (long long)fn_stub;\ *(fn + 38) = 0x39;\ *(fn + 39) = 0x37;\ ((uint32_t *)fn)[10] = 0x0320f809;\ ((uint32_t *)fn)[11] = 0x00000000;\ ((uint32_t *)fn)[12] = 0x00000000;\ ((uint32_t *)fn)[13] = 0x03c0e825;\ ((uint32_t *)fn)[14] = 0xdfbf0018;\ ((uint32_t *)fn)[15] = 0xdfbe0010;\ ((uint32_t *)fn)[16] = 0xdfbc0008;\ ((uint32_t *)fn)[17] = 0x67bd0020;\ ((uint32_t *)fn)[18] = 0x03e00008;\ ((uint32_t *)fn)[19] = 0x00000000;\ CACHEFLUSH((char *)fn, CODESIZE); #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) #elif defined(__thumb__) || defined(_M_THUMB) #error "Thumb is not supported" #else //__i386__ _x86_64__ #define CODESIZE 13U #define CODESIZE_MIN 5U #define CODESIZE_MAX CODESIZE //13 byte(jmp m16:64) //movabs $0x102030405060708,%r11 //jmpq *%r11 static void REPLACE_FAR(void *t, char *fn, char *fn_stub) { *fn = 0x49; *(fn + 1) = 0xbb; *(long long *)(fn + 2) = (long long)fn_stub; *(fn + 10) = 0x41; *(fn + 11) = 0xff; *(fn + 12) = 0xe3; CACHEFLUSH((char *)fn, CODESIZE); } //5 byte(jmp rel32) #define REPLACE_NEAR(t, fn, fn_stub)\ *fn = 0xE9;\ *(int *)(fn + 1) = (int)(fn_stub - fn - CODESIZE_MIN);\ CACHEFLUSH((char *)fn, CODESIZE); #endif struct func_stub { char *fn; unsigned char code_buf[CODESIZE]; bool far_jmp; }; class Stub { public: Stub() { #ifdef _WIN32 SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); m_pagesize = sys_info.dwPageSize; #else m_pagesize = sysconf(_SC_PAGE_SIZE); #endif if (m_pagesize < 0) { m_pagesize = 4096; } } ~Stub() { clear(); } virtual void clear() { std::map::iterator iter; struct func_stub *pstub; for(iter=m_result.begin(); iter != m_result.end(); iter++) { pstub = iter->second; #ifdef _WIN32 DWORD lpflOldProtect; if(0 != VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect)) #else if (0 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) #endif { if(pstub->far_jmp) { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX); } else { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN); } #ifdef _WIN32 VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect); #else CACHEFLUSH(pstub->fn,CODESIZE); mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC); #endif } iter->second = NULL; delete pstub; } m_result.clear(); return; } template bool set(T addr, S addr_stub) { char * fn; char * fn_stub; fn = addrof(addr); fn_stub = addrof(addr_stub); struct func_stub *pstub; std::map::iterator iter = m_result.find(fn); if (iter == m_result.end()) { pstub = new func_stub; //start pstub->fn = fn; if(distanceof(fn, fn_stub)) { pstub->far_jmp = true; std::memcpy(pstub->code_buf, fn, CODESIZE_MAX); } else { pstub->far_jmp = false; std::memcpy(pstub->code_buf, fn, CODESIZE_MIN); } } else { pstub = iter->second; pstub->far_jmp = distanceof(fn, fn_stub); } #ifdef _WIN32 DWORD lpflOldProtect; if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), static_cast(m_pagesize * 2), PROT_READ | PROT_WRITE | PROT_EXEC)) #endif { //throw("stub set memory protect to w+r+x faild"); return false; } if(pstub->far_jmp) { REPLACE_FAR(this, fn, fn_stub); } else { REPLACE_NEAR(this, fn, fn_stub); } #ifdef _WIN32 if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC)) #endif { //throw("stub set memory protect to r+x failed"); return false; } m_result.insert(std::pair(fn,pstub)); return true; } template bool reset(T addr) { char * fn; fn = addrof(addr); std::map::iterator iter = m_result.find(fn); if (iter == m_result.end()) { return true; } struct func_stub *pstub; pstub = iter->second; #ifdef _WIN32 DWORD lpflOldProtect; if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) #endif { //throw("stub reset memory protect to w+r+x faild"); return false; } if(pstub->far_jmp) { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX); } else { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN); } #ifdef _WIN32 if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect)) #else CACHEFLUSH(pstub->fn,CODESIZE); if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC)) #endif { //throw("stub reset memory protect to r+x failed"); return false; } m_result.erase(iter); delete pstub; return true; } protected: char *pageof(char* addr) { #ifdef _WIN32 return (char *)((unsigned long long)addr & ~(m_pagesize - 1)); #else return (char *)((unsigned long)addr & ~(m_pagesize - 1)); #endif } template char* addrof(T addr) { union { T _s; char* _d; }ut; ut._s = addr; return ut._d; } bool distanceof(char* addr, char* addr_stub) { std::ptrdiff_t diff = addr_stub >= addr ? addr_stub - addr : addr - addr_stub; if((sizeof(addr) > 4) && (((diff >> 31) - 1) > 0)) { return true; } return false; } protected: #ifdef _WIN32 //LLP64 long long m_pagesize; #else //LP64 long m_pagesize; #endif std::map m_result; }; #endif ukui-biometric-auth/tests/kt-test-utils/cpp-stub-ext/0000775000175000017500000000000015167732630021627 5ustar fengfengukui-biometric-auth/tests/kt-test-utils/cpp-stub-ext/stubext.h0000664000175000017500000000734115167732630023503 0ustar fengfeng #ifndef STUBEXT_H #define STUBEXT_H /* * Author: Zhang Yu * Maintainer: Zhang Yu * * MIT License * * Copyright (c) 2020 Zhang Yu * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ //需修改Stub的�用�员函数和�员��为�护类型 #include "stub.h" #include "stub-shadow.h" #ifdef DEBUG_STUB_INVOKE // use to make sure the stub function is invoked. # define __DBG_STUB_INVOKE__ printf("stub at %s:%d is invoked.\n", __FILE__, __LINE__); #else # define __DBG_STUB_INVOKE__ #endif #define VADDR(CLASS_NAME, MEMBER_NAME) (typename stub_ext::VFLocator::Func)(&CLASS_NAME::MEMBER_NAME) namespace stub_ext { class StubExt : public Stub { public: StubExt() : Stub() { } template bool set_lamda(T addr, Lamda lamda) { char *fn = addrof(addr); if (m_result.find(fn) != m_result.end()) reset(addr); Wrapper *wrapper = nullptr; auto addr_stub = depictShadow(&wrapper, addr, lamda); if (set(addr, addr_stub)) { m_wrappers.insert(std::make_pair(fn, wrapper)); return true; } else { freeWrapper(wrapper); } return false; } template void reset(T addr) { Stub::reset(addr); char *fn = addrof(addr); auto iter = m_wrappers.find(fn); if (iter != m_wrappers.end()) { freeWrapper(iter->second); m_wrappers.erase(iter); } } ~StubExt() { clear(); } void clear() override { Stub::clear(); for (auto iter = m_wrappers.begin(); iter != m_wrappers.end(); ++iter) { freeWrapper(iter->second); } m_wrappers.clear(); } template static void *get_ctor_addr(bool start = true) { // the start vairable must be true, or the compiler will optimize out. if (start) goto Start; Call_Constructor: // This line of code will not be executed. // The purpose of the code is to allow the compiler to generate the assembly code that calls the constructor. T(); Start: // The address of the line of code T() obtained by assembly char *p = (char *)&&Call_Constructor; // https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html // CALL rel32 void *ret = 0; char pos; char call = 0xe8; do { pos = *p; if (pos == call) { ret = p + 5 + (*(int *)(p + 1)); } } while (!ret && (++p)); return ret; } protected: std::map m_wrappers; }; } #endif // STUBEXT_H ukui-biometric-auth/tests/kt-test-utils/cpp-stub-ext/stub-shadow.cpp0000664000175000017500000000314715167732630024600 0ustar fengfeng/* * Author: Zhang Yu * Maintainer: Zhang Yu * * MIT License * * Copyright (c) 2020 Zhang Yu * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "stub-shadow.h" namespace stub_ext { WrapperMap stub_wrappers; Wrapper::Wrapper() { } Wrapper::~Wrapper() { } void freeWrapper(Wrapper *wrapper) { if (!wrapper) return; for (auto iter = stub_wrappers.begin(); iter != stub_wrappers.end();) { if (iter->second == wrapper) iter = stub_wrappers.erase(iter); else ++iter; } delete wrapper; } } ukui-biometric-auth/tests/kt-test-utils/cpp-stub-ext/stub-shadow.h0000664000175000017500000001143415167732630024243 0ustar fengfeng #ifndef STUBSHADOW_H #define STUBSHADOW_H /* * Author: Zhang Yu * Maintainer: Zhang Yu * * MIT License * * Copyright (c) 2020 Zhang Yu * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include namespace stub_ext { #define LAMDA_FUNCTION_TYPE decltype(&Lamda::operator()) class Wrapper { public: Wrapper(); virtual ~Wrapper(); }; typedef std::unordered_map WrapperMap; extern WrapperMap stub_wrappers; template class LamdaWrapper : public Wrapper { public: LamdaWrapper(Lamda func): Wrapper(),_func(func){} ~LamdaWrapper(){} Lamda _func; }; template struct VFLocator { }; template struct VFLocator { typedef Ret (*Func)(Obj*, Args...); }; template struct VFLocator { typedef Ret (*Func)(Obj*, Args...); }; template struct LamdaCaller { }; template struct LamdaCaller { template static Ret call(LamdaWrapper *wrapper, OrgArgs&&... args) { return wrapper->_func(std::forward(args)...); } }; template struct LamdaCaller { template static Ret call(LamdaWrapper *wrapper, OrgArgs&&... args) { return wrapper->_func(); } }; template struct FuncShadow { }; template struct FuncShadow { typedef Ret (*Shadow)(Args...); typedef Ret RetType; static Ret call(Args ...args) { Shadow shadow = &call; long id = (long)shadow; auto iter = stub_wrappers.find(id); assert(stub_wrappers.find(id) != stub_wrappers.end()); LamdaWrapper *wrapper = dynamic_cast *>(iter->second); return LamdaCaller::call(wrapper, args...); } }; template struct FuncShadow { typedef Ret (*Shadow)(Obj *,Args...); typedef Ret RetType; static Ret call(Obj *obj, Args ...args) { Shadow shadow = &call; long id = (long)shadow; auto iter = stub_wrappers.find(id); assert(stub_wrappers.find(id) != stub_wrappers.end()); LamdaWrapper *wrapper = dynamic_cast *>(iter->second); return LamdaCaller::call(wrapper, obj, args...); } }; template struct FuncShadow { typedef Ret (*Shadow)(Obj *,Args...); typedef Ret RetType; static Ret call(Obj *obj, Args ...args) { Shadow shadow = &call; long id = (long)shadow; auto iter = stub_wrappers.find(id); assert(stub_wrappers.find(id) != stub_wrappers.end()); LamdaWrapper *wrapper = dynamic_cast *>(iter->second); return LamdaCaller::call(wrapper, obj, args...); } }; template typename FuncShadow::Shadow depictShadow(Wrapper **wrapper, Func func, Lamda lamda) { *wrapper = new LamdaWrapper(lamda); typename FuncShadow::Shadow shadow = &FuncShadow::call; long id = (long)shadow; assert(stub_wrappers.find(id) == stub_wrappers.end()); stub_wrappers.insert(std::make_pair(id,*wrapper)); return shadow; } void freeWrapper(Wrapper *wrapper); } #endif // STUBSHADOW_H ukui-biometric-auth/tests/unit_test_loginoptionswidget/0000775000175000017500000000000015167732644022576 5ustar fengfengukui-biometric-auth/tests/unit_test_loginoptionswidget/CMakeLists.txt0000664000175000017500000000435715167732630025342 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(PkgConfig REQUIRED) find_package(Qt5 COMPONENTS Core Gui DBus Widgets Svg REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) find_package(OpenCV REQUIRED) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") qt5_add_resources(polkit_SRCS ../../polkit-agent/assets.qrc) # 定义�文件列表,对应原�的SOURCES�� set(SOURCES main.cpp ../../bioauth/src/uniauthservice.cpp ../../bioauth/src/biotypes.cpp ../../bioauth/src/giodbus.cpp ../../bioauth/src/bioauth.cpp ../../bioauth/src/biodevices.cpp ../../bioauth/src/loginoptionswidget.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../bioauth/include/uniauthservice.h ../../bioauth/include/bioauth.h ../../bioauth/include/biodevices.h ../../bioauth/include/loginoptionswidget.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ../../bioauth/include ../../common ${GIOUNIX2_INCLUDE_DIRS} ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_loginoptionswidget ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_loginoptionswidget Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets Qt5::Svg ${OpenCV_LIBS} ${GIOUNIX2_LIBRARIES} ) # 链接 GTest 库 target_link_libraries(unit_test_loginoptionswidget GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_loginoptionswidget/main.cpp0000664000175000017500000003453715167732644024242 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include "../../bioauth/include/loginoptionswidget.h" // �设这个头文件存在,并包�了BioAuth类的声明 TEST(LoginOptionsWidgetTest, init) { LoginOptionsWidget loginWidget; EXPECT_EQ(loginWidget.getLoginOptCount(),0); EXPECT_EQ(loginWidget.convertDeviceType(0),0); int nLoginOptType,nDrvId; loginWidget.getCurLoginOpt(nLoginOptType,nDrvId); loginWidget.getFirstDevInfo(); loginWidget.updateUIStatus(false); loginWidget.updateUIStatus(true); loginWidget.updateUkeyUIStatus(0); loginWidget.updateUkeyUIStatus(1); loginWidget.updateUkeyUIStatus(8); loginWidget.setUser(1000); loginWidget.setCurrentDevice(-1); loginWidget.setCurrentDevice("test"); loginWidget.setDeviceDisable(100,false); loginWidget.setDeviceDisable(100,true); loginWidget.isDeviceDisable(false); loginWidget.lockStatusChanged(false); loginWidget.lockStatusChanged(true); loginWidget.readDevicesInfo(); loginWidget.onIdentifyComplete(1000,true,0); loginWidget.onIdentifyComplete(1000,false,0); loginWidget.onIdentifyComplete(-1,true,0); loginWidget.onAuthFinished(); loginWidget.onStatusChanged(1000,"test"); loginWidget.onFrameWritten(1000); loginWidget.onUSBDeviceCountChange(0); loginWidget.onUSBDeviceCountChange(1); loginWidget.onOptionSelected(-1); loginWidget.onOptionSelected(0); loginWidget.onOptionSelected(1); loginWidget.setQRCodeMsg(""); loginWidget.setQRCodeMsg("test"); EXPECT_EQ(loginWidget.GetDefaultDevice(1000),""); EXPECT_EQ(loginWidget.GetDefaultDevice(1000,0),""); loginWidget.startAuth(nullptr,1000); loginWidget.stopAuth(); loginWidget.SetExtraInfo("test1","test2"); EXPECT_EQ(loginWidget.getHasUkeyOptions(),false); loginWidget.setSelectedPassword(); loginWidget.setAllDeviceDisable(true); loginWidget.setAllDeviceDisable(false); loginWidget.notifyOptionsChange(-1); loginWidget.notifyOptionsChange(0); loginWidget.notifyOptionsChange(1); loginWidget.optionSelected(LOGINOPT_TYPE_GENERAL_UKEY,nullptr); QImage image; loginWidget.updateImage(image); loginWidget.authComplete(1000,-1,-1); loginWidget.updateAuthMsg("test"); loginWidget.updateWndSize(0,100); loginWidget.initUI(); loginWidget.initConnections(); loginWidget.addOptionButton(LOGINOPT_TYPE_PASSWORD,0,"LOGINOPT_TYPE_PASSWORD"); loginWidget.addOptionButton(LOGINOPT_TYPE_GENERAL_UKEY,1,"LOGINOPT_TYPE_GENERAL_UKEY"); loginWidget.addOptionButton(LOGINOPT_TYPE_FACE,2,"LOGINOPT_TYPE_FACE"); loginWidget.addOptionButton(LOGINOPT_TYPE_FINGERPRINT,3,"LOGINOPT_TYPE_FINGERPRINT"); loginWidget.addOptionButton(LOGINOPT_TYPE_IRIS,4,"LOGINOPT_TYPE_IRIS"); loginWidget.addOptionButton(LOGINOPT_TYPE_VOICEPRINT,5,"LOGINOPT_TYPE_VOICEPRINT"); loginWidget.addOptionButton(LOGINOPT_TYPE_FINGERVEIN,6,"LOGINOPT_TYPE_FINGERVEIN"); loginWidget.addOptionButton(LOGINOPT_TYPE_QRCODE,7,"LOGINOPT_TYPE_QRCODE"); loginWidget.onOptionSelected(-1); loginWidget.onOptionSelected(0); loginWidget.onOptionSelected(1); loginWidget.clearOptionButtons(); loginWidget.updateOptionButtons(); loginWidget.startAuth_(); loginWidget.stopAuth(); QPixmap pix = QIcon::fromTheme("ukui-loading-0-symbolic").pixmap(24, 24); loginWidget.PixmapToRound(pix,32); QPixmap pix1; loginWidget.PixmapToRound(pix1,32); loginWidget.scaledPixmap(1024,768,"/usr/share/backgrounds/1-warty-final-ubuntukylin.jpg"); loginWidget.scaledPixmap(1024,768,"/usr/share/backgrounds/test-warty-final-ubuntukylin.jpg"); loginWidget.scaledPixmap(1024,768,"/usr/share/ukui-biometric/images/ukui-loginopt-face.svg"); loginWidget.scaledPixmap(1024,768,"/usr/share/ukui-biometric/images/FingerPrint.gif"); loginWidget.scaledPixmap(1024,768,"/usr/share/ukui-biometric/ukui-biometric.conf"); loginWidget.updatePixmap(); loginWidget.drawSymbolicColoredPixmap(pix,"white"); loginWidget.drawSymbolicColoredPixmap(pix,"blue"); loginWidget.drawSymbolicColoredPixmap(pix,"gray"); loginWidget.drawSymbolicColoredPixmap(pix,"black"); loginWidget.drawSymbolicColoredPixmap(pix,"red"); QImage img; QImage img1 = pix1.toImage(); loginWidget.setFaceImg(img,1); loginWidget.setFaceImg(img,2); loginWidget.setFaceImg(img,3); loginWidget.setFaceImg(img1,1); loginWidget.convertDeviceType(BIOTYPE_FINGERPRINT); loginWidget.convertDeviceType(BIOTYPE_FINGERVEIN); loginWidget.convertDeviceType(BIOTYPE_IRIS); loginWidget.convertDeviceType(BIOTYPE_FACE); loginWidget.convertDeviceType(BIOTYPE_VOICEPRINT); loginWidget.convertDeviceType(UniT_General_Ukey); loginWidget.convertDeviceType(UniT_Advanced_Ukey); loginWidget.convertDeviceType(REMOTE_QRCODE_TYPE); loginWidget.convertDeviceType(-1); } TEST(LoginOptionsWidgetTest, noProxy) { LoginOptionsWidget loginWidget; loginWidget.m_biomericProxy = nullptr; loginWidget.SetExtraInfo("test1","test2"); } // 模拟startAuth的调用 TEST(LoginOptionsWidgetTest, startAuth) { DeviceInfoPtr pDeviceInfo = std::make_shared(); pDeviceInfo->device_id = 100; pDeviceInfo->device_shortname = "TestDevice"; pDeviceInfo->device_fullname = "Test Device Full Name"; pDeviceInfo->driver_enable = 1; pDeviceInfo->device_available = 1; pDeviceInfo->biotype = BIOTYPE_FINGERPRINT; pDeviceInfo->stotype = 0; pDeviceInfo->eigtype = 0; pDeviceInfo->vertype = 0; pDeviceInfo->idtype = 0; pDeviceInfo->bustype = 0; pDeviceInfo->dev_status = 0; pDeviceInfo->ops_status = 0; LoginOptionsWidget loginWidget; loginWidget.onOptionSelected(-1); loginWidget.onOptionSelected(0); loginWidget.onOptionSelected(1); loginWidget.m_mapDevices[LOGINOPT_TYPE_FINGERPRINT].push_back(pDeviceInfo); loginWidget.setCurrentDevice("TestDevice"); loginWidget.setCurrentDevice(100); loginWidget.setCurrentDevice(pDeviceInfo); loginWidget.startAuth(pDeviceInfo,1000); loginWidget.m_isInAuth = true; loginWidget.stopAuth(); loginWidget.onStatusChanged(100,"this is test"); } // 模拟认�完� TEST(LoginOptionsWidgetTest, onIdentifyComplete) { LoginOptionsWidget loginWidget; loginWidget.m_isStopped = false; loginWidget.onIdentifyComplete(-1,-1,-1); loginWidget.onIdentifyComplete(0,-1,-1); loginWidget.onIdentifyComplete(0,-1,1000); loginWidget.onIdentifyComplete(0,-1,200); loginWidget.onIdentifyComplete(-1,-1,-3); } //模拟device管� TEST(LoginOptionsWidgetTest, testAllDevice) { DeviceInfoPtr pDeviceInfo = std::make_shared(); pDeviceInfo->device_id = 100; pDeviceInfo->device_shortname = "TestDevice"; pDeviceInfo->device_fullname = "Test Device Full Name"; pDeviceInfo->driver_enable = 1; pDeviceInfo->device_available = 1; pDeviceInfo->biotype = BIOTYPE_FINGERPRINT; pDeviceInfo->stotype = 0; pDeviceInfo->eigtype = 0; pDeviceInfo->vertype = 0; pDeviceInfo->idtype = 0; pDeviceInfo->bustype = 0; pDeviceInfo->dev_status = 0; pDeviceInfo->ops_status = 0; DeviceInfoPtr pDeviceInfo1 = std::make_shared(); pDeviceInfo1->device_id = 101; pDeviceInfo1->device_shortname = "TestDevice1"; pDeviceInfo1->device_fullname = "Test Device Full Name"; pDeviceInfo1->driver_enable = 1; pDeviceInfo1->device_available = 1; pDeviceInfo1->biotype = BIOTYPE_FINGERVEIN; pDeviceInfo1->stotype = 0; pDeviceInfo1->eigtype = 0; pDeviceInfo1->vertype = 0; pDeviceInfo1->idtype = 0; pDeviceInfo1->bustype = 0; pDeviceInfo1->dev_status = 0; pDeviceInfo1->ops_status = 0; DeviceInfoPtr pDeviceInfo2 = std::make_shared(); pDeviceInfo2->device_id = 102; pDeviceInfo2->device_shortname = "TestDevice2"; pDeviceInfo2->device_fullname = "Test Device Full Name"; pDeviceInfo2->driver_enable = 1; pDeviceInfo2->device_available = 1; pDeviceInfo2->biotype = BIOTYPE_IRIS; pDeviceInfo2->stotype = 0; pDeviceInfo2->eigtype = 0; pDeviceInfo2->vertype = 0; pDeviceInfo2->idtype = 0; pDeviceInfo2->bustype = 0; pDeviceInfo2->dev_status = 0; pDeviceInfo2->ops_status = 0; DeviceInfoPtr pDeviceInfo3 = std::make_shared(); pDeviceInfo3->device_id = 103; pDeviceInfo3->device_shortname = "TestDevice3"; pDeviceInfo3->device_fullname = "Test Device Full Name"; pDeviceInfo3->driver_enable = 1; pDeviceInfo3->device_available = 1; pDeviceInfo3->biotype = BIOTYPE_FACE; pDeviceInfo3->stotype = 0; pDeviceInfo3->eigtype = 0; pDeviceInfo3->vertype = 0; pDeviceInfo3->idtype = 0; pDeviceInfo3->bustype = 0; pDeviceInfo3->dev_status = 0; pDeviceInfo3->ops_status = 0; DeviceInfoPtr pDeviceInfo4 = std::make_shared(); pDeviceInfo4->device_id = 104; pDeviceInfo4->device_shortname = "TestDevice4"; pDeviceInfo4->device_fullname = "Test Device Full Name"; pDeviceInfo4->driver_enable = 1; pDeviceInfo4->device_available = 1; pDeviceInfo4->biotype = BIOTYPE_VOICEPRINT; pDeviceInfo4->stotype = 0; pDeviceInfo4->eigtype = 0; pDeviceInfo4->vertype = 0; pDeviceInfo4->idtype = 0; pDeviceInfo4->bustype = 0; pDeviceInfo4->dev_status = 0; pDeviceInfo4->ops_status = 0; DeviceInfoPtr pDeviceInfo5 = std::make_shared(); pDeviceInfo5->device_id = 105; pDeviceInfo5->device_shortname = "TestDevice5"; pDeviceInfo5->device_fullname = "Test Device Full Name"; pDeviceInfo5->driver_enable = 1; pDeviceInfo5->device_available = 1; pDeviceInfo5->biotype = 6; pDeviceInfo5->stotype = 0; pDeviceInfo5->eigtype = 0; pDeviceInfo5->vertype = 0; pDeviceInfo5->idtype = 0; pDeviceInfo5->bustype = 0; pDeviceInfo5->dev_status = 0; pDeviceInfo5->ops_status = 0; DeviceInfoPtr pDeviceInfo6 = std::make_shared(); pDeviceInfo6->device_id = 106; pDeviceInfo6->device_shortname = "TestDevice6"; pDeviceInfo6->device_fullname = "Test Device Full Name"; pDeviceInfo6->driver_enable = 1; pDeviceInfo6->device_available = 1; pDeviceInfo6->biotype = 6; pDeviceInfo6->stotype = 0; pDeviceInfo6->eigtype = 0; pDeviceInfo6->vertype = 0; pDeviceInfo6->idtype = 0; pDeviceInfo6->bustype = 0; pDeviceInfo6->dev_status = 0; pDeviceInfo6->ops_status = 0; DeviceInfoPtr pDeviceInfo7 = std::make_shared(); pDeviceInfo7->device_id = 107; pDeviceInfo7->device_shortname = "TestDevice7"; pDeviceInfo7->device_fullname = "Test Device Full Name"; pDeviceInfo7->driver_enable = 1; pDeviceInfo7->device_available = 1; pDeviceInfo7->biotype = 7; pDeviceInfo7->stotype = 0; pDeviceInfo7->eigtype = 0; pDeviceInfo7->vertype = 0; pDeviceInfo7->idtype = 0; pDeviceInfo7->bustype = 0; pDeviceInfo7->dev_status = 0; pDeviceInfo7->ops_status = 0; DeviceInfoPtr pDeviceInfo8 = std::make_shared(); pDeviceInfo8->device_id = 108; pDeviceInfo8->device_shortname = "TestDevice8"; pDeviceInfo8->device_fullname = "Test Device Full Name"; pDeviceInfo8->driver_enable = 1; pDeviceInfo8->device_available = 1; pDeviceInfo8->biotype = 8; pDeviceInfo8->stotype = 0; pDeviceInfo8->eigtype = 0; pDeviceInfo8->vertype = 0; pDeviceInfo8->idtype = 0; pDeviceInfo8->bustype = 0; pDeviceInfo8->dev_status = 0; pDeviceInfo8->ops_status = 0; LoginOptionsWidget loginWidget; loginWidget.m_mapDevices[0].push_back(pDeviceInfo); loginWidget.m_mapDevices[1].push_back(pDeviceInfo1); loginWidget.m_mapDevices[2].push_back(pDeviceInfo2); loginWidget.m_mapDevices[3].push_back(pDeviceInfo2); loginWidget.m_mapDevices[4].push_back(pDeviceInfo4); loginWidget.m_mapDevices[5].push_back(pDeviceInfo5); loginWidget.m_mapDevices[6].push_back(pDeviceInfo6); loginWidget.m_mapDevices[7].push_back(pDeviceInfo7); loginWidget.m_mapDevices[8].push_back(pDeviceInfo8); loginWidget.addOptionButton(LOGINOPT_TYPE_PASSWORD,0,"LOGINOPT_TYPE_PASSWORD"); loginWidget.addOptionButton(LOGINOPT_TYPE_PASSWORD,0,"LOGINOPT_TYPE_PASSWORD"); loginWidget.addOptionButton(LOGINOPT_TYPE_GENERAL_UKEY,1,"LOGINOPT_TYPE_GENERAL_UKEY"); loginWidget.addOptionButton(LOGINOPT_TYPE_FACE,2,"LOGINOPT_TYPE_FACE"); loginWidget.addOptionButton(LOGINOPT_TYPE_FINGERPRINT,3,"LOGINOPT_TYPE_FINGERPRINT"); loginWidget.addOptionButton(LOGINOPT_TYPE_IRIS,4,"LOGINOPT_TYPE_IRIS"); loginWidget.addOptionButton(LOGINOPT_TYPE_VOICEPRINT,5,"LOGINOPT_TYPE_VOICEPRINT"); loginWidget.addOptionButton(LOGINOPT_TYPE_FINGERVEIN,6,"LOGINOPT_TYPE_FINGERVEIN"); loginWidget.addOptionButton(LOGINOPT_TYPE_QRCODE,7,"LOGINOPT_TYPE_QRCODE"); loginWidget.setCurrentDevice(100); int nLoginOptType,nDrvId; loginWidget.getCurLoginOpt(nLoginOptType,nDrvId); loginWidget.getFirstDevInfo(); loginWidget.updateOptionButtons(); loginWidget.setSelectedPassword(); loginWidget.startAuth(pDeviceInfo,1000); loginWidget.startAuth(pDeviceInfo1,1000); loginWidget.startAuth(pDeviceInfo2,1000); loginWidget.startAuth(pDeviceInfo3,1000); loginWidget.startAuth(pDeviceInfo4,1000); loginWidget.startAuth(pDeviceInfo5,1000); loginWidget.startAuth(pDeviceInfo6,1000); loginWidget.startAuth(pDeviceInfo7,1000); loginWidget.startAuth(pDeviceInfo8,1000); } // 创建一个全局的QApplication对象,因为Qt测试通常需�一个事件循环 int main(int argc, char **argv) { QApplication a(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_modebutton/0000775000175000017500000000000015167732644021026 5ustar fengfengukui-biometric-auth/tests/unit_test_modebutton/CMakeLists.txt0000664000175000017500000000327015167732644023570 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(QGS REQUIRED gsettings-qt6) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES ../../polkit-agent/src/modeButton.cpp main.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../polkit-agent/src/modeButton.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ${QGS_INCLUDE_DIRS} ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_modebutton ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_modebutton Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ${QGS_LIBRARIES} ) # 链接 GTest 库 target_link_libraries(unit_test_modebutton GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_modebutton/main.cpp0000664000175000017500000000722515167732644022464 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include "../../polkit-agent/src/modeButton.h" // Test fixture for ModeButton class ModeButtonTest : public ::testing::Test { protected: }; TEST_F(ModeButtonTest, TestDefaultConstructor) { ModeButton button(nullptr); EXPECT_EQ(button.isShowPwd(), false); EXPECT_EQ(button.size(), QSize(24, 24)); } TEST_F(ModeButtonTest, TestIconConstructor) { ModeButton button("testIcon", nullptr); // Since we can't directly assert the icon, we assume the constructor sets up the internal state correctly EXPECT_EQ(button.size(), QSize(24, 24)); // Further checks would involve mocking QIcon::fromTheme and verifying interactions } TEST_F(ModeButtonTest, TestShowPasswordToggle) { ModeButton button(nullptr); // Mock QGSettings to return a theme name that is not dark or black button.initStyleTheme(); // Initially, pwdShow should be false EXPECT_EQ(button.isShowPwd(), false); // Simulate a click event emit button.clicked(); // Now pwdShow should be true EXPECT_EQ(button.isShowPwd(), true); // Simulate another click event emit button.clicked(); // Now pwdShow should be false again EXPECT_EQ(button.isShowPwd(), false); } TEST_F(ModeButtonTest, TestHoverEffect) { ModeButton button(nullptr); // Mock QGSettings to return a theme name that is not dark or black button.initStyleTheme(); // Simulate entering the hover state QEvent enterEvent(QEvent::Enter); QApplication::sendEvent(&button, &enterEvent); // Verify the icon is set to white (or appropriate hover color) // This would involve checking the internal state or mocking QIcon::pixmap and QPixmap::fromImage // Since we can't directly access the icon, we assume setModeIcon handles it correctly // Simulate leaving the hover state QEvent leaveEvent(QEvent::Leave); QApplication::sendEvent(&button, &leaveEvent); // Verify the icon is set back to gray (or appropriate non-hover color) // Similarly, we assume setModeIcon handles it correctly } TEST_F(ModeButtonTest, TestThemeChange) { ModeButton button(nullptr); button.initStyleTheme(); button.setModeIcon(); button.m_styleSettings->changed("styleName"); QPixmap pixmap = QIcon::fromTheme("ukui-eye-display-symbolic").pixmap(24,24); pixmap = button.drawSymbolicColoredPixmap(pixmap, "black"); pixmap = button.drawSymbolicColoredPixmap(pixmap, "blue"); pixmap = button.drawSymbolicColoredPixmap(pixmap, "gray"); pixmap = button.drawSymbolicColoredPixmap(pixmap, "white"); pixmap = button.drawSymbolicColoredPixmap(pixmap, "red"); button.m_strThemeName = "ukui-dark"; button.setModeIcon(); button.m_strThemeName = "ukui-black"; button.setModeIcon(); } int main(int argc, char **argv) { QApplication app(argc, argv);; ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_biodevices/0000775000175000017500000000000015167732644020762 5ustar fengfengukui-biometric-auth/tests/unit_test_biodevices/CMakeLists.txt0000664000175000017500000000423215167732630023516 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(PkgConfig REQUIRED) find_package(Qt5 COMPONENTS Core Gui DBus Widgets Svg REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) find_package(OpenCV REQUIRED) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES main.cpp ../../bioauth/src/uniauthservice.cpp ../../bioauth/src/biotypes.cpp ../../bioauth/src/giodbus.cpp ../../bioauth/src/bioauth.cpp ../../bioauth/src/biodevices.cpp ../../bioauth/src/loginoptionswidget.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../bioauth/include/uniauthservice.h ../../bioauth/include/bioauth.h ../../bioauth/include/biodevices.h ../../bioauth/include/loginoptionswidget.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ../../bioauth/include ../../common ${GIOUNIX2_INCLUDE_DIRS} ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_biodevices ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_biodevices Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets Qt5::Svg ${OpenCV_LIBS} ${GIOUNIX2_LIBRARIES} ) # 链接 GTest 库 target_link_libraries(unit_test_biodevices GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_biodevices/main.cpp0000664000175000017500000001021515167732644022411 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include "../../bioauth/include/biodevices.h" // �设这个头文件存在,并包�了BioAuth类的声明 TEST(BioDevicesTest, init) { BioDevices devices; EXPECT_EQ(devices.count(),0); devices.setUId(1000); devices.getAllDevices(); devices.getUserDevices(1000); devices.getDevices(0); devices.getDefaultDevice(1000); devices.getDefaultDevice(1000,0); devices.GetLastDevice("kylin"); devices.SetLastDevice("kylin",100); devices.SetLastDevice("kylin",-1); devices.SetLastDevice("testx",100); devices.findDevice("testDevice"); devices.findDevice(100); devices.getFirstDevice(1000); devices.GetDevList(); devices.getFeatureCount(1000,0,-1); devices.bioTypeToString_tr(0); devices.bioTypeToString_tr(1); devices.bioTypeToString_tr(2); devices.bioTypeToString_tr(3); devices.bioTypeToString_tr(4); devices.bioTypeToString_tr(5); devices.bioTypeToString_tr(6); devices.bioTypeToString_tr(7); devices.bioTypeToString_tr(8); devices.setIsShowHotPlug(true); devices.setIsShowHotPlug(false); devices.GetUserDevFeatureCount(1000,100); devices.GetUserDevCount(1000); devices.GetUserFeatures(1000); devices.getUseFirstDevice(); devices.getFailedTimes(); devices.GetHiddenSwitchButton(); devices.GetQRCodeEnable(); devices.GetBioAuthEnable(); devices.getAllDefDevices(); devices.UpdateStatus(100); devices.UpdateStatus(-1); devices.GetBioAuthEnable(1000); devices.GetDirveIsIdle(100); devices.recordAuthDrive("test",100,true); devices.recordAuthDrive("test",100,false); devices.onUSBDeviceHotPlug(10,-1,10); devices.onUSBDeviceHotPlug(10,1,10); devices.m_uniAuthService = nullptr; devices.setUId(1000); devices.getAllDevices(); devices.getUserDevices(1000); devices.getDevices(0); devices.getDefaultDevice(1000); devices.getDefaultDevice(1000,0); devices.GetLastDevice("kylin"); devices.SetLastDevice("kylin",100); devices.SetLastDevice("kylin",-1); devices.findDevice("testDevice"); devices.findDevice(100); devices.getFirstDevice(1000); devices.GetDevList(); devices.getFeatureCount(1000,0,-1); devices.bioTypeToString_tr(0); devices.bioTypeToString_tr(1); devices.bioTypeToString_tr(2); devices.bioTypeToString_tr(3); devices.bioTypeToString_tr(4); devices.bioTypeToString_tr(5); devices.bioTypeToString_tr(6); devices.bioTypeToString_tr(7); devices.bioTypeToString_tr(8); devices.setIsShowHotPlug(true); devices.setIsShowHotPlug(false); devices.GetUserDevFeatureCount(1000,100); devices.GetUserDevCount(1000); devices.GetUserFeatures(1000); devices.getUseFirstDevice(); devices.getFailedTimes(); devices.GetHiddenSwitchButton(); devices.GetQRCodeEnable(); devices.GetBioAuthEnable(); devices.getAllDefDevices(); devices.UpdateStatus(100); devices.UpdateStatus(-1); devices.GetBioAuthEnable(1000); devices.GetDirveIsIdle(100); devices.recordAuthDrive("test",100,true); devices.recordAuthDrive("test",100,false); devices.onUSBDeviceHotPlug(10,-1,10); devices.onUSBDeviceHotPlug(10,1,10); } // 创建一个全局的QApplication对象,因为Qt测试通常需�一个事件循环 int main(int argc, char **argv) { QApplication a(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_pam_tally/0000775000175000017500000000000015167732644020630 5ustar fengfengukui-biometric-auth/tests/unit_test_pam_tally/CMakeLists.txt0000664000175000017500000000312515167732630023364 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES ../../polkit-agent/src/pam-tally.c main.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../polkit-agent/src/pam-tally.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_pam_tally ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_pam_tally Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ) # 链接 GTest 库 target_link_libraries(unit_test_pam_tally GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_pam_tally/main.cpp0000664000175000017500000001034015167732644022256 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "../../polkit-agent/src/pam-tally.h" #include #include #include #include #include #include #include #define CONFIG_FILE "/usr/share/lightdm/lightdm.conf.d/96-kylin-setting.conf" // 辅助函数,用于模拟�置文件内容 void write_config_file(const char* content) { FILE* file = fopen(CONFIG_FILE, "w"); if (file) { fputs(content, file); fclose(file); } else { perror("Failed to open config file for writing"); exit(EXIT_FAILURE); } } // 辅助函数,用于清�共享内存 void cleanup_shm() { } class PamTallyTest : public ::testing::Test { protected: void SetUp() override { // 在�个测试用例之��行 cleanup_shm(); // 确��次测试�清�共享内存 } void TearDown() override { // 在�个测试用例之��行 cleanup_shm(); // 确��次测试�清�共享内存 } }; TEST_F(PamTallyTest, PamTallyInit) { // 测试pam_tally_init函数 write_config_file("open-other-authentication=0\n"); // 确��置关闭其他认� // 临时修改/etc/pam.d/common-auth文件以进行测试 //const char* auth_file_content = "auth required pam_deny.so deny=3 unlock_time=600 root_unlock_time=1800\n"; //FILE* auth_file = fopen("/etc/pam.d/common-auth", "w"); //if (auth_file) { // fputs(auth_file_content, auth_file); // fclose(auth_file); //} else { // perror("Failed to open auth file for writing"); // exit(EXIT_FAILURE); //} int result = pam_tally_init(); EXPECT_EQ(result, 1); // 预期�始化�功 } TEST_F(PamTallyTest, PamTallyIsCanUnlock) { // 测试pam_tally_is_canUnlock函数 pam_tally_init(); // �始化pam_tally并设置解�时间为600秒 pam_tally_add_failed(); // 添加一次失败,�足以达到失败次数上� EXPECT_EQ(pam_tally_is_canUnlock(), 1); // 预期�以解�,因为失败次数未达到上� // 添加足够多的失败次数以达到上�,并检查是��以解� for (int i = 0; i < 2; ++i) { pam_tally_add_failed(); } time_t start_time = time(NULL); EXPECT_EQ(pam_tally_is_canUnlock(), 0); // 预期�能解�,因为失败次数已达到上�且未过解�时间 // 等待超过解�时间�,�次检查是��以解� sleep(601); // �设解�时间为600秒,这里等待601秒以确�超过解�时间 EXPECT_EQ(pam_tally_is_canUnlock(), 1); // 预期现在�以解�,因为已�超过解�时间 } TEST_F(PamTallyTest, PamTallyUnlockTime) { // 测试pam_tally_is_canUnlock函数 pam_tally_init(); // �始化pam_tally并设置解�时间为600秒 pam_tally_add_failed(); // 添加一次失败,�足以达到失败次数上� int failed_count = 0; int time_left = 0; int deny = 0; int fail_time = 0; int unlock_time = 0; pam_tally_unlock_time_left(1000, &failed_count, &time_left, &deny, &fail_time, &unlock_time); EXPECT_EQ(failed_count, 0); EXPECT_EQ(time_left, 0); EXPECT_EQ(deny, 0); EXPECT_EQ(fail_time, 0); EXPECT_EQ(unlock_time, 0); pam_tally_root_unlock_time_left(&failed_count, &time_left, &deny, &fail_time, &unlock_time); EXPECT_EQ(failed_count, 0); EXPECT_EQ(time_left, 0); EXPECT_EQ(deny, 0); EXPECT_EQ(fail_time, 0); EXPECT_EQ(unlock_time, 0); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_servicemanager/0000775000175000017500000000000015167732644021641 5ustar fengfengukui-biometric-auth/tests/unit_test_servicemanager/CMakeLists.txt0000664000175000017500000000313515167732631024377 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus REQUIRED) find_package(PkgConfig REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES ../../uniauth-backend/src/servicemanager.cpp main.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../uniauth-backend/src/servicemanager.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_servicemanager ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_servicemanager Qt5::Core Qt5::Gui Qt5::DBus ) # 链接 GTest 库 target_link_libraries(unit_test_servicemanager GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_servicemanager/main.cpp0000664000175000017500000000321115167732644023266 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "../../uniauth-backend/src/servicemanager.h" #include #include #define SERVICE "biometric-authentication.service" #define DBUS_SERVICE "org.ukui.Biometric" #define DBUS_PATH "/org/ukui/Biometric" #define DBUS_INTERFACE "org.ukui.Biometric" #define FD_DBUS_SERVICE "org.freedesktop.DBus" #define FD_DBUS_PATH "/org/freedesktop/DBus" #define FD_DBUS_INTERFACE "org.freedesktop.DBus" // gtest 测试用例 TEST(ServiceManagerTest, SerializationAndDeserialization) { ServiceManager *sm = ServiceManager::instance(); sm->connectToService(); sm->serviceStatusChanged(true); sm->serviceStatusChanged(false); sm->dbusNameOwnerChanged(DBUS_SERVICE,DBUS_SERVICE,DBUS_SERVICE); sm->onDBusNameOwnerChanged(DBUS_SERVICE,DBUS_SERVICE,DBUS_SERVICE); sm->serviceExists(); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_sessionmanager/0000775000175000017500000000000015167732644021664 5ustar fengfengukui-biometric-auth/tests/unit_test_sessionmanager/CMakeLists.txt0000664000175000017500000000316015167732631024420 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES ../../polkit-agent/src/sessionmanager.cpp main.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../polkit-agent/src/sessionmanager.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_sessionmanager ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_sessionmanager Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ) # 链接 GTest 库 target_link_libraries(unit_test_sessionmanager GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_sessionmanager/main.cpp0000664000175000017500000000270615167732644023321 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ // sessionmanager_test.cpp #include #include #include #include #include #include #include #include "../../polkit-agent/src/sessionmanager.h" // Test fixture for SessionManager class SessionManagerTest : public ::testing::Test { protected: void SetUp() override { sessionManager = new SessionManager(); } void TearDown() override { delete sessionManager; } SessionManager* sessionManager; }; TEST_F(SessionManagerTest, testSessionManagerTest) { EXPECT_TRUE(sessionManager != nullptr); } int main(int argc, char **argv) { QCoreApplication app(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_common/0000775000175000017500000000000015167732644020136 5ustar fengfengukui-biometric-auth/tests/unit_test_common/CMakeLists.txt0000664000175000017500000000311715167732630022673 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES ../../common/generic.cpp main.cpp unit_test_common.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../common/generic.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_common ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_common Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ) # 链接 GTest 库 target_link_libraries(unit_test_common GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_common/main.cpp0000664000175000017500000000156115167732644021571 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include int main(int argc, char **argv) { QGuiApplication a(argc, argv); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/unit_test_common/unit_test_common.cpp0000664000175000017500000000227515167732644024236 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include "../../common/generic.h" #include "stubext.h" using namespace stub_ext; bool enableDebug = true; QString logPrefix = "[test]:"; class GenericTest : public testing::Test { protected: }; TEST_F(GenericTest, outputMessage) { qInstallMessageHandler(outputMessage); qDebug()<<"test1"; qWarning()<<"test2"; qInfo()<<"test3"; qCritical()<<"test4"; enableDebug = false; qDebug()<<"test5"; } ukui-biometric-auth/tests/unit_test_users/0000775000175000017500000000000015167732644020007 5ustar fengfengukui-biometric-auth/tests/unit_test_users/CMakeLists.txt0000664000175000017500000000310315167732631022540 0ustar fengfeng# CMake 最低版本�求 cmake_minimum_required(VERSION 3.10) find_package(Qt5 COMPONENTS Core Gui DBus Widgets REQUIRED) find_package(PkgConfig REQUIRED) # 包� GTest 库和 pthread 库 find_package(GTest REQUIRED) find_package(Threads REQUIRED) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 开�代�覆盖率相关编译选项(对应QMAKE_LFLAGS和QMAKE_CXXFLAGS中代�覆盖率相关设置) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage --coverage -fno-inline -fno-access-control") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") # 定义�文件列表,对应原�的SOURCES�� set(SOURCES ../../polkit-agent/src/users.cpp main.cpp ) # 定义头文件列表,对应原�的HEADERS�� set(HEADERS ../../polkit-agent/src/users.h ) # 包�头文件的路径设置,对应原�的INCLUDEPATH�� include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub ${CMAKE_CURRENT_SOURCE_DIR}/../kt-test-utils/cpp-stub-ext ) # 使用qt5_wrap_cpp生�元对象代�相关的�文件 qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) # 添加�执行文件或库目标,将元对象代��文件一起添加进去 add_executable(unit_test_users ${SOURCES} ${MOC_SOURCES}) # 链接Qt相关的库 target_link_libraries(unit_test_users Qt5::Core Qt5::Gui Qt5::DBus Qt5::Widgets ) # 链接 GTest 库 target_link_libraries(unit_test_users GTest::GTest GTest::Main Threads::Threads ) ukui-biometric-auth/tests/unit_test_users/main.cpp0000664000175000017500000000652115167732644021443 0ustar fengfeng/* * Copyright (C) 2024 KylinSoftCo., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "../../polkit-agent/src/users.h" #include #include #include #include #include #include #include class UsersTest : public ::testing::Test { protected: void SetUp() override { users = new Users(nullptr); } void TearDown() override { delete users; } Users *users; }; TEST_F(UsersTest, testGetUsers) { QList userList = users->getUsers(); EXPECT_EQ(userList.size(), 0); // Initially, the list should be empty // Load users should populate the list users->loadUsers(); userList = users->getUsers(); EXPECT_EQ(userList.size(), 2); // After loading, we expect 2 users EXPECT_EQ(userList[0].name, QString("testuser")); EXPECT_EQ(userList[0].uid, quint64(1000)); EXPECT_EQ(userList[1].name, QString("")); // The second user might not be fully populated in this mock } TEST_F(UsersTest, testGetUserByName) { users->loadUsers(); UserItem user = users->getUserByName("testuser"); EXPECT_EQ(user.name, QString("testuser")); EXPECT_EQ(user.realName, QString("Test User")); EXPECT_EQ(user.uid, quint64(1000)); user = users->getUserByName("nonexistent"); EXPECT_EQ(user.name, QString("nonexistent")); EXPECT_EQ(user.uid, ::getuid()); // Fallback uid should be the current uid user = users->getUserByName("root"); user = users->getUserByName("kylin"); qDebug()<getDefaultIcon(); EXPECT_EQ(defaultIcon, QString(":/image/assets/iconFace.png")); } TEST_F(UsersTest, testOnUserAddedAndDeleted) { // Set up a temporary directory and file to test icon loading QTemporaryDir tempDir; QFile tempFile(tempDir.filePath("icon.png")); tempFile.open(QIODevice::WriteOnly); tempFile.close(); // Load users users->loadUsers(); QList userList = users->getUsers(); EXPECT_EQ(userList.size(), 2); // Emit userAdded signal (simulate DBus signal) QDBusObjectPath path("/user/newuser"); QMetaObject::invokeMethod(users, "onUserAdded", Q_ARG(QDBusObjectPath, path)); userList = users->getUsers(); EXPECT_EQ(userList.size(), 3); // Now we should have 3 users // Emit userDeleted signal (simulate DBus signal) QMetaObject::invokeMethod(users, "onUserDeleted", Q_ARG(QDBusObjectPath, path)); userList = users->getUsers(); EXPECT_EQ(userList.size(), 2); // Back to 2 users } int main(int argc, char **argv) { QCoreApplication app(argc, argv); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ukui-biometric-auth/tests/auto_test.sh0000664000175000017500000000303515167732644017114 0ustar fengfeng#!/bin/bash # 设置退出脚本当命令失败时 (�零退出状�) #set -e # 函数:�行�元测试 run_unit_tests() { local pattern="unit_test_*" # �历所有匹�模�的目录 for dir in $pattern; do if [ -d "$dir" ] && [ -x "$dir/$(basename "$dir")" ]; then echo "Running tests in $dir..." # 执行�元测试 (cd "$dir" && "./$(basename "$dir")") # 收集代�覆盖率数� echo "Collecting coverage data..." (cd "$dir" && (find ./ -name '*.o' | xargs gcov --preserve-paths)) else echo "Skipping non-existent or non-executable directory: $dir, $dir/$(basename "$dir")" fi done } # 上传 result.zip 到平� URL=$1 upload_result() { echo "current pwd : $(pwd)" # 收集覆盖率信� lcov -d . -c -o r.info # 删除�需�的文件或路径 lcov -r r.info "$(pwd)/unit_test_*" "$(pwd)/../registeredSession/universalinterface.cpp" "/usr/include/*" "/opt/*" -o coverage.info # 生�html覆盖率报告 genhtml "$(pwd)/coverage.info" -o result # 打包 zip -r result.zip result # 上传平� curl --insecure -X POST -F "file=@/$(pwd)/result.zip" -F "package=ukui-control-center" -F "username=hesisheng" $URL echo "all parameter : $@" } # 编译项目 echo "Compiling the project..." cmake . && make # �行�个�元测试 echo "Running unit tests..." run_unit_tests # 上传到平� #upload_result echo "All tests have been run successfully, and coverage data has been collected." ukui-biometric-auth/readme.txt0000664000175000017500000000044515167732630015402 0ustar fengfengbioctl status 获�生物特�总开关状� bioctl status greeter|screensaver|polkit|sudo|su|login 获�应用开关状� bioctl enable|disable 打开|关闭 生物特�总开关 bioctl enable|disable greeter|screensaver|polkit|sudo|su|login 打开|关闭 应用生物特�开关