2017-05-24 10:46:42 +00:00
|
|
|
/*
|
|
|
|
* notify.c: Notification implementation
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "notify.h"
|
|
|
|
|
2017-11-07 15:10:28 +00:00
|
|
|
#if defined(ENABLE_NOTIFY) && (defined(__APPLE__))
|
2017-05-24 10:46:42 +00:00
|
|
|
|
2017-10-31 08:29:05 +00:00
|
|
|
#include "libopensc/internal.h"
|
2017-05-24 10:46:42 +00:00
|
|
|
#include "libopensc/log.h"
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
static pid_t child = -1;
|
|
|
|
|
|
|
|
void sc_notify_init(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_close(void)
|
|
|
|
{
|
|
|
|
if (child > 0) {
|
|
|
|
int i, status;
|
|
|
|
for (i = 0; child != waitpid(child, &status, WNOHANG); i++) {
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
kill(child, SIGKILL);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
kill(child, SIGTERM);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* SIGTERM was our last resort */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
usleep(100);
|
|
|
|
}
|
|
|
|
child = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-08 14:10:43 +00:00
|
|
|
#endif
|
|
|
|
|
2017-06-13 11:35:32 +00:00
|
|
|
#if defined(ENABLE_NOTIFY) && defined(_WIN32)
|
|
|
|
|
2017-07-04 14:12:06 +00:00
|
|
|
#include "common/compat_strlcpy.h"
|
2017-06-19 09:57:18 +00:00
|
|
|
#include "invisible_window.h"
|
2017-06-13 11:35:32 +00:00
|
|
|
#include "wchar_from_char_str.h"
|
|
|
|
#include <shellapi.h>
|
2017-07-04 14:12:06 +00:00
|
|
|
#include <shlwapi.h>
|
2017-06-13 11:35:32 +00:00
|
|
|
|
2017-07-11 14:41:18 +00:00
|
|
|
// {83C35893-99C6-4600-BFDB-45925C53BDD9}
|
|
|
|
static const GUID myGUID = { 0x83c35893, 0x99c6, 0x4600, { 0xbf, 0xdb, 0x45, 0x92, 0x5c, 0x53, 0xbd, 0xd9 } };
|
2017-06-13 11:35:32 +00:00
|
|
|
HINSTANCE sc_notify_instance = NULL;
|
2018-07-26 12:44:20 +00:00
|
|
|
HWND sc_notify_hwnd = NULL;
|
2017-06-19 09:57:18 +00:00
|
|
|
BOOL delete_icon = TRUE;
|
2017-06-13 11:35:32 +00:00
|
|
|
#define IDI_SMARTCARD 102
|
2018-07-26 12:44:20 +00:00
|
|
|
#define WMAPP_NOTIFYCALLBACK (WM_APP + 1)
|
2017-06-19 09:57:18 +00:00
|
|
|
static BOOL RestoreTooltip();
|
2018-07-26 12:44:20 +00:00
|
|
|
void ShowContextMenu(HWND hwnd, POINT pt);
|
2017-06-13 11:35:32 +00:00
|
|
|
|
|
|
|
// we need commctrl v6 for LoadIconMetric()
|
|
|
|
#include <commctrl.h>
|
|
|
|
|
|
|
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2018-07-26 12:44:20 +00:00
|
|
|
switch (message) {
|
|
|
|
case WM_COMMAND:
|
|
|
|
{
|
|
|
|
int const wmId = LOWORD(wParam);
|
|
|
|
// Parse the menu selection:
|
|
|
|
switch (wmId)
|
|
|
|
{
|
|
|
|
case WMAPP_EXIT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return DefWindowProc(hwnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WMAPP_NOTIFYCALLBACK:
|
|
|
|
switch (LOWORD(lParam)) {
|
|
|
|
case NIN_BALLOONTIMEOUT:
|
|
|
|
case NIN_BALLOONUSERCLICK:
|
|
|
|
RestoreTooltip();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CONTEXTMENU:
|
|
|
|
{
|
|
|
|
POINT const pt = { LOWORD(wParam), HIWORD(wParam) };
|
|
|
|
ShowContextMenu(hwnd, pt);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return DefWindowProc(hwnd, message, wParam, lParam);
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
|
2018-07-26 12:44:20 +00:00
|
|
|
return 0;
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
|
2017-06-19 09:57:18 +00:00
|
|
|
static const char* lpszClassName = "NOTIFY_CLASS";
|
2017-06-13 11:35:32 +00:00
|
|
|
|
|
|
|
static BOOL AddNotificationIcon(void)
|
|
|
|
{
|
2017-07-04 14:12:06 +00:00
|
|
|
NOTIFYICONDATA nid = {0};
|
2017-06-13 11:35:32 +00:00
|
|
|
TCHAR path[MAX_PATH]={0};
|
|
|
|
BOOL r;
|
|
|
|
|
2018-07-26 12:44:20 +00:00
|
|
|
sc_notify_hwnd = create_invisible_window(lpszClassName, WndProc,
|
|
|
|
sc_notify_instance);
|
|
|
|
if (!sc_notify_hwnd) {
|
2017-07-04 14:12:06 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-07-11 14:41:18 +00:00
|
|
|
nid.cbSize = sizeof(NOTIFYICONDATA);
|
2018-07-26 12:44:20 +00:00
|
|
|
nid.hWnd = sc_notify_hwnd;
|
2017-06-13 11:35:32 +00:00
|
|
|
// add the icon, setting the icon, tooltip, and callback message.
|
|
|
|
// the icon will be identified with the GUID
|
|
|
|
nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_SHOWTIP | NIF_GUID;
|
|
|
|
nid.guidItem = myGUID;
|
|
|
|
nid.uCallbackMessage = WMAPP_NOTIFYCALLBACK;
|
|
|
|
LoadIconMetric(sc_notify_instance, MAKEINTRESOURCEW(IDI_SMARTCARD), LIM_SMALL, &nid.hIcon);
|
|
|
|
if (GetModuleFileName(NULL, path, ARRAYSIZE(path))) {
|
2017-06-19 09:57:18 +00:00
|
|
|
const char *basename = strrchr(path, '\\');
|
|
|
|
if (basename) {
|
|
|
|
basename++;
|
|
|
|
if (0 != strcmp(basename, "opensc-notify.exe")) {
|
2018-04-14 17:38:34 +00:00
|
|
|
/* Allow creation of system tray icon only for
|
2017-06-19 09:57:18 +00:00
|
|
|
* "opensc-notify.exe" to avoid creation of the same icon by
|
|
|
|
* multiple processes. */
|
|
|
|
delete_icon = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
strlcpy(nid.szTip, path, ARRAYSIZE(nid.szTip));
|
2017-06-13 11:35:32 +00:00
|
|
|
} else {
|
|
|
|
strcpy(nid.szTip, PACKAGE_NAME);
|
|
|
|
}
|
|
|
|
|
2018-07-26 12:44:20 +00:00
|
|
|
r = Shell_NotifyIcon(NIM_ADD, &nid);
|
|
|
|
if (TRUE == r) {
|
|
|
|
nid.uVersion = NOTIFYICON_VERSION_4;
|
|
|
|
r = Shell_NotifyIcon(NIM_SETVERSION, &nid);
|
|
|
|
}
|
2017-06-13 11:35:32 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL DeleteNotificationIcon(void)
|
|
|
|
{
|
|
|
|
BOOL r;
|
2017-07-04 14:12:06 +00:00
|
|
|
NOTIFYICONDATA nid = {0};
|
2017-06-13 11:35:32 +00:00
|
|
|
|
2017-06-19 09:57:18 +00:00
|
|
|
if (!delete_icon) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-07-11 14:41:18 +00:00
|
|
|
nid.cbSize = sizeof(NOTIFYICONDATA);
|
2017-06-13 11:35:32 +00:00
|
|
|
nid.uFlags = NIF_GUID;
|
|
|
|
nid.guidItem = myGUID;
|
|
|
|
|
|
|
|
r = Shell_NotifyIcon(NIM_DELETE, &nid);
|
2017-06-19 09:57:18 +00:00
|
|
|
|
2018-07-26 12:44:20 +00:00
|
|
|
r &= delete_invisible_window(sc_notify_hwnd, lpszClassName,
|
2017-06-19 09:57:18 +00:00
|
|
|
sc_notify_instance);
|
2018-07-26 12:44:20 +00:00
|
|
|
sc_notify_hwnd = NULL;
|
2017-06-13 11:35:32 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL RestoreTooltip()
|
|
|
|
{
|
|
|
|
// After the balloon is dismissed, restore the tooltip.
|
2017-07-04 14:12:06 +00:00
|
|
|
NOTIFYICONDATA nid = {0};
|
2017-06-13 11:35:32 +00:00
|
|
|
|
2017-07-11 14:41:18 +00:00
|
|
|
nid.cbSize = sizeof(NOTIFYICONDATA);
|
2017-06-13 11:35:32 +00:00
|
|
|
nid.uFlags = NIF_SHOWTIP | NIF_GUID;
|
|
|
|
nid.guidItem = myGUID;
|
|
|
|
|
|
|
|
return Shell_NotifyIcon(NIM_MODIFY, &nid);
|
|
|
|
}
|
|
|
|
|
2018-07-26 12:44:20 +00:00
|
|
|
void ShowContextMenu(HWND hwnd, POINT pt)
|
|
|
|
{
|
|
|
|
HMENU hMenu;
|
|
|
|
hMenu=CreatePopupMenu();
|
|
|
|
|
|
|
|
if (hMenu) {
|
2018-07-26 13:01:16 +00:00
|
|
|
AppendMenu(hMenu, MF_STRING, WMAPP_EXIT, ui_get_str(NULL, NULL, NULL, NOTIFY_EXIT));
|
2018-07-26 12:44:20 +00:00
|
|
|
|
|
|
|
// our window must be foreground before calling TrackPopupMenu or the menu will not disappear when the user clicks away
|
|
|
|
SetForegroundWindow(hwnd);
|
|
|
|
|
|
|
|
// respect menu drop alignment
|
|
|
|
UINT uFlags = TPM_RIGHTBUTTON;
|
|
|
|
if (GetSystemMetrics(SM_MENUDROPALIGNMENT) != 0) {
|
|
|
|
uFlags |= TPM_RIGHTALIGN;
|
|
|
|
} else {
|
|
|
|
uFlags |= TPM_LEFTALIGN;
|
|
|
|
}
|
|
|
|
|
|
|
|
TrackPopupMenuEx(hMenu, uFlags, pt.x, pt.y, hwnd, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-13 11:35:32 +00:00
|
|
|
static void notify_shell(struct sc_context *ctx,
|
2017-08-02 15:14:26 +00:00
|
|
|
const char *title, const char *text, LPCTSTR icon_path, int icon_index)
|
2017-06-13 11:35:32 +00:00
|
|
|
{
|
2017-07-04 14:12:06 +00:00
|
|
|
NOTIFYICONDATA nid = {0};
|
2017-08-02 15:14:26 +00:00
|
|
|
HICON icon = NULL;
|
2017-06-13 11:35:32 +00:00
|
|
|
|
2017-07-11 14:41:18 +00:00
|
|
|
nid.cbSize = sizeof(NOTIFYICONDATA);
|
2017-06-13 11:35:32 +00:00
|
|
|
nid.uFlags = NIF_GUID;
|
|
|
|
nid.guidItem = myGUID;
|
|
|
|
|
|
|
|
if (title) {
|
2017-06-19 09:57:18 +00:00
|
|
|
strlcpy(nid.szInfoTitle, title, ARRAYSIZE(nid.szInfoTitle));
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
if (text) {
|
|
|
|
nid.uFlags |= NIF_INFO;
|
2017-06-19 09:57:18 +00:00
|
|
|
strlcpy(nid.szInfo, text, ARRAYSIZE(nid.szInfo));
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
2017-08-02 15:14:26 +00:00
|
|
|
if (icon_path) {
|
|
|
|
ExtractIconEx(icon_path, icon_index, &icon, NULL, 1);
|
|
|
|
if (icon) {
|
|
|
|
nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
|
|
|
|
nid.hBalloonIcon = icon;
|
|
|
|
}
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Shell_NotifyIcon(NIM_MODIFY, &nid);
|
2017-08-02 15:14:26 +00:00
|
|
|
|
|
|
|
if (icon) {
|
|
|
|
DestroyIcon(icon);
|
|
|
|
}
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_init(void)
|
|
|
|
{
|
|
|
|
if (!sc_notify_instance) {
|
|
|
|
/* returns the HINSTANCE of the exe. If the code executes in a DLL,
|
|
|
|
* sc_notify_instance_notify should be pre-initialized */
|
|
|
|
sc_notify_instance = GetModuleHandle(NULL);
|
|
|
|
}
|
|
|
|
AddNotificationIcon();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_close(void)
|
|
|
|
{
|
|
|
|
DeleteNotificationIcon();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify(const char *title, const char *text)
|
|
|
|
{
|
2017-08-02 15:14:26 +00:00
|
|
|
notify_shell(NULL, title, text, NULL, 0);
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
|
|
|
|
struct sc_pkcs15_card *p15card, enum ui_str id)
|
|
|
|
{
|
2017-06-19 09:57:18 +00:00
|
|
|
const char *title, *text;
|
2017-08-02 15:14:26 +00:00
|
|
|
LPCTSTR icon_path = NULL;
|
|
|
|
int icon_index = 0;
|
2017-06-13 11:35:32 +00:00
|
|
|
title = ui_get_str(ctx, atr, p15card, id);
|
|
|
|
text = ui_get_str(ctx, atr, p15card, id+1);
|
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
case NOTIFY_CARD_INSERTED:
|
2017-08-02 15:14:26 +00:00
|
|
|
icon_path = TEXT("%SYSTEMROOT%\\system32\\SCardDlg.dll");
|
|
|
|
icon_index = 3;
|
2017-06-13 11:35:32 +00:00
|
|
|
break;
|
|
|
|
case NOTIFY_CARD_REMOVED:
|
2017-08-02 15:14:26 +00:00
|
|
|
icon_path = TEXT("%SYSTEMROOT%\\system32\\SCardDlg.dll");
|
|
|
|
icon_index = 2;
|
2017-06-13 11:35:32 +00:00
|
|
|
break;
|
|
|
|
case NOTIFY_PIN_GOOD:
|
2017-08-02 15:14:26 +00:00
|
|
|
icon_path = TEXT("%SYSTEMROOT%\\system32\\certmgr.dll");
|
|
|
|
icon_index = 16;
|
2017-06-13 11:35:32 +00:00
|
|
|
break;
|
|
|
|
case NOTIFY_PIN_BAD:
|
2017-08-02 15:14:26 +00:00
|
|
|
icon_path = TEXT("%SYSTEMROOT%\\system32\\certmgr.dll");
|
|
|
|
icon_index = 11;
|
2017-06-13 11:35:32 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-08-02 15:14:26 +00:00
|
|
|
notify_shell(ctx, title, text, icon_path, icon_index);
|
2017-06-13 11:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(ENABLE_NOTIFY) && defined(__APPLE__)
|
2017-06-08 14:10:43 +00:00
|
|
|
|
2017-05-24 10:46:42 +00:00
|
|
|
static void notify_proxy(struct sc_context *ctx,
|
|
|
|
const char *title, const char* subtitle,
|
|
|
|
const char *text, const char *icon, const char *sound,
|
|
|
|
const char *group)
|
|
|
|
{
|
|
|
|
/* terminal-notifier does not reliably activate keychain when clicked on
|
|
|
|
* the notification
|
|
|
|
* (https://github.com/julienXX/terminal-notifier/issues/196), that's why
|
|
|
|
* we're including NotificationProxy which has similar features */
|
|
|
|
const char notificationproxy[] = "/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications/NotificationProxy.app/Contents/MacOS/NotificationProxy";
|
|
|
|
|
2018-04-27 10:47:27 +00:00
|
|
|
if (ctx && ctx->app_name
|
|
|
|
&& (0 == strcmp(ctx->app_name, "opensc-pkcs11")
|
|
|
|
|| 0 == strcmp(ctx->app_name, "onepin-opensc-pkcs11"))) {
|
|
|
|
/* some programs don't like forking when loading our PKCS#11 module,
|
|
|
|
* see https://github.com/OpenSC/OpenSC/issues/1174.
|
|
|
|
* TODO implementing an XPC service which sends the notification should
|
|
|
|
* work, though. See
|
|
|
|
* https://github.com/OpenSC/OpenSC/issues/1304#issuecomment-376656003 */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-24 10:46:42 +00:00
|
|
|
if (child > 0) {
|
|
|
|
int status;
|
|
|
|
if (0 == waitpid(child, &status, WNOHANG)) {
|
|
|
|
kill(child, SIGKILL);
|
|
|
|
usleep(100);
|
|
|
|
if (0 == waitpid(child, &status, WNOHANG)) {
|
|
|
|
sc_log(ctx, "Can't kill %ld, skipping current notification", (long) child);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
child = fork();
|
|
|
|
switch (child) {
|
|
|
|
case 0:
|
|
|
|
/* child process */
|
|
|
|
|
|
|
|
/* for some reason the user _tokend can call brew's installation of
|
|
|
|
* terminal-notifier, but it cannot call `/usr/bin/open` with
|
|
|
|
* NotificationProxy.app that we're shipping... However, while
|
|
|
|
* `sudo -u _tokend /usr/local/bin/terminal-notifier -title test`
|
|
|
|
* works in the terminal, it hangs when executed from the tokend
|
|
|
|
* process. For now, we try to deliver the notification anyway
|
|
|
|
* making sure that we are waiting for only one forked process. */
|
|
|
|
if (0 > execl(notificationproxy, notificationproxy,
|
|
|
|
title ? title : "",
|
|
|
|
subtitle ? subtitle : "",
|
|
|
|
text ? text : "",
|
|
|
|
icon ? icon : "",
|
|
|
|
group ? group : "",
|
|
|
|
sound ? sound : "",
|
|
|
|
(char *) NULL)) {
|
|
|
|
perror("exec failed");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
sc_log(ctx, "failed to fork for notification");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (ctx) {
|
|
|
|
sc_log(ctx, "Created %ld for notification:", (long) child);
|
|
|
|
sc_log(ctx, "%s %s %s %s %s %s %s", notificationproxy,
|
|
|
|
title ? title : "",
|
|
|
|
subtitle ? subtitle : "",
|
|
|
|
text ? text : "",
|
|
|
|
icon ? icon : "",
|
|
|
|
group ? group : "",
|
|
|
|
sound ? sound : "");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify(const char *title, const char *text)
|
|
|
|
{
|
|
|
|
notify_proxy(NULL, title, NULL, text, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
|
|
|
|
struct sc_pkcs15_card *p15card, enum ui_str id)
|
|
|
|
{
|
|
|
|
const char *title, *text, *icon, *group;
|
|
|
|
title = ui_get_str(ctx, atr, p15card, id);
|
|
|
|
text = ui_get_str(ctx, atr, p15card, id+1);
|
|
|
|
|
|
|
|
if (p15card && p15card->card && p15card->card->reader) {
|
|
|
|
group = p15card->card->reader->name;
|
|
|
|
} else {
|
|
|
|
group = ctx ? ctx->app_name : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
case NOTIFY_CARD_INSERTED:
|
|
|
|
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/VCard.icns";
|
|
|
|
break;
|
|
|
|
case NOTIFY_CARD_REMOVED:
|
|
|
|
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/EjectMediaIcon.icns";
|
|
|
|
break;
|
|
|
|
case NOTIFY_PIN_GOOD:
|
|
|
|
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/UnlockedIcon.icns";
|
|
|
|
break;
|
|
|
|
case NOTIFY_PIN_BAD:
|
|
|
|
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/LockedIcon.icns";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
icon = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
notify_proxy(ctx, title, NULL, text, icon, NULL, group);
|
|
|
|
}
|
|
|
|
|
2017-06-08 14:10:43 +00:00
|
|
|
#elif defined(ENABLE_NOTIFY) && defined(ENABLE_GIO2)
|
|
|
|
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
2017-11-07 15:10:28 +00:00
|
|
|
static GApplication *application = NULL;
|
|
|
|
|
2017-06-08 14:10:43 +00:00
|
|
|
void sc_notify_init(void)
|
|
|
|
{
|
|
|
|
sc_notify_close();
|
2018-04-24 07:50:04 +00:00
|
|
|
application = g_application_new("org.opensc.notify", G_APPLICATION_NON_UNIQUE);
|
2017-06-08 14:10:43 +00:00
|
|
|
if (application) {
|
|
|
|
g_application_register(application, NULL, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_close(void)
|
|
|
|
{
|
|
|
|
if (application) {
|
|
|
|
g_object_unref(application);
|
|
|
|
application = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void notify_gio(struct sc_context *ctx,
|
|
|
|
const char *title, const char *text, const char *icon,
|
|
|
|
const char *group)
|
|
|
|
{
|
2018-04-25 07:34:47 +00:00
|
|
|
if (application
|
|
|
|
&& g_application_get_is_registered(application)
|
|
|
|
&& g_application_get_dbus_connection(application)) {
|
2017-11-08 11:23:05 +00:00
|
|
|
GIcon *gicon = NULL;
|
2018-04-25 07:34:47 +00:00
|
|
|
GNotification *notification = g_notification_new(title);
|
2017-11-08 11:23:05 +00:00
|
|
|
if (!notification) {
|
|
|
|
return;
|
|
|
|
}
|
2017-06-08 14:10:43 +00:00
|
|
|
|
2017-11-08 11:23:05 +00:00
|
|
|
if (text) {
|
2018-04-25 07:34:47 +00:00
|
|
|
g_notification_set_body(notification, text);
|
2017-11-08 11:23:05 +00:00
|
|
|
}
|
|
|
|
if (icon) {
|
2018-04-25 07:34:47 +00:00
|
|
|
gicon = g_themed_icon_new(icon);
|
2017-11-08 11:23:05 +00:00
|
|
|
if (gicon) {
|
2018-04-25 07:34:47 +00:00
|
|
|
g_notification_set_icon(notification, gicon);
|
2017-11-08 11:23:05 +00:00
|
|
|
}
|
2017-06-08 14:10:43 +00:00
|
|
|
}
|
|
|
|
|
2017-11-08 11:23:05 +00:00
|
|
|
g_application_send_notification(application, group, notification);
|
2017-06-08 14:10:43 +00:00
|
|
|
|
2017-11-08 11:23:05 +00:00
|
|
|
if (gicon) {
|
|
|
|
g_object_unref(gicon);
|
|
|
|
}
|
|
|
|
g_object_unref(notification);
|
2017-06-08 14:10:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-24 10:46:42 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
void sc_notify_init(void) {}
|
|
|
|
void sc_notify_close(void) {}
|
|
|
|
void sc_notify(const char *title, const char *text) {}
|
|
|
|
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
|
|
|
|
struct sc_pkcs15_card *p15card, enum ui_str id) {}
|
|
|
|
|
|
|
|
#endif
|
2017-06-08 14:10:43 +00:00
|
|
|
|
2017-11-07 15:10:28 +00:00
|
|
|
#if defined(ENABLE_NOTIFY) && defined(ENABLE_GIO2)
|
2017-06-08 14:10:43 +00:00
|
|
|
void sc_notify(const char *title, const char *text)
|
|
|
|
{
|
|
|
|
notify_gio(NULL, title, text, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
|
|
|
|
struct sc_pkcs15_card *p15card, enum ui_str id)
|
|
|
|
{
|
|
|
|
const char *title, *text, *icon, *group;
|
|
|
|
title = ui_get_str(ctx, atr, p15card, id);
|
|
|
|
text = ui_get_str(ctx, atr, p15card, id+1);
|
|
|
|
|
|
|
|
if (p15card && p15card->card && p15card->card->reader) {
|
|
|
|
group = p15card->card->reader->name;
|
|
|
|
} else {
|
|
|
|
group = ctx ? ctx->app_name : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (id) {
|
|
|
|
case NOTIFY_CARD_INSERTED:
|
2018-04-25 08:35:44 +00:00
|
|
|
icon = "contact-new";
|
2017-06-08 14:10:43 +00:00
|
|
|
break;
|
|
|
|
case NOTIFY_CARD_REMOVED:
|
2018-04-25 08:35:44 +00:00
|
|
|
icon = "media-eject";
|
2017-06-08 14:10:43 +00:00
|
|
|
break;
|
|
|
|
case NOTIFY_PIN_GOOD:
|
|
|
|
icon = "changes-allow";
|
|
|
|
break;
|
|
|
|
case NOTIFY_PIN_BAD:
|
|
|
|
icon = "changes-prevent";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
icon = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
notify_gio(ctx, title, text, icon, group);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|