Linux: Added support for notifications
This commit is contained in:
parent
417a409406
commit
cd62c6cdf5
46
configure.ac
46
configure.ac
@ -463,6 +463,37 @@ case "${host}" in
|
|||||||
have_notify="yes"
|
have_notify="yes"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
AC_PATH_PROG([GDBUS], [gdbus], [not found])
|
||||||
|
if test "${GDBUS}" = "not found"; then
|
||||||
|
have_notify="no"
|
||||||
|
have_gdbus="no"
|
||||||
|
else
|
||||||
|
have_notify="yes"
|
||||||
|
have_gdbus="yes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "${have_notify}" = "no"; then
|
||||||
|
PKG_CHECK_MODULES( [GIO2], [gio-2.0],
|
||||||
|
[ have_notify="yes"
|
||||||
|
have_gio2="yes" ],
|
||||||
|
[ have_notify="no"
|
||||||
|
have_gio2="no" ])
|
||||||
|
saved_CFLAGS="${CFLAGS}"
|
||||||
|
CFLAGS="${CFLAGS} ${GIO2_CFLAGS}"
|
||||||
|
AC_CHECK_HEADERS(gio/gio.h, [],
|
||||||
|
[ AC_MSG_WARN([glib2 headers not found])
|
||||||
|
have_notify="no"
|
||||||
|
have_gio2="no" ])
|
||||||
|
CFLAGS="${saved_CFLAGS}"
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS ${GIO2_LIBS}"
|
||||||
|
AC_MSG_CHECKING([for g_application_send_notification])
|
||||||
|
AC_TRY_LINK_FUNC(g_application_send_notification, [ AC_MSG_RESULT([yes]) ],
|
||||||
|
[ AC_MSG_WARN([Cannot link against glib2])
|
||||||
|
have_notify="no"
|
||||||
|
have_gio2="no" ])
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@ -482,8 +513,14 @@ esac
|
|||||||
if test "${enable_notify}" = "yes"; then
|
if test "${enable_notify}" = "yes"; then
|
||||||
if test "${have_notify}" = "yes"; then
|
if test "${have_notify}" = "yes"; then
|
||||||
AC_DEFINE([ENABLE_NOTIFY], [1], [Use notification libraries and header files])
|
AC_DEFINE([ENABLE_NOTIFY], [1], [Use notification libraries and header files])
|
||||||
OPTIONAL_NOTIFY_CFLAGS="${NOTIFY_CFLAGS}"
|
if test "${have_gdbus}" = "yes"; then
|
||||||
OPTIONAL_NOTIFY_LIBS="${NOTIFY_LIBS}"
|
AC_DEFINE_UNQUOTED([GDBUS], ["${GDBUS}"], [Path to gdbus])
|
||||||
|
fi
|
||||||
|
if test "${have_gio2}" = "yes"; then
|
||||||
|
AC_DEFINE([ENABLE_GIO2], [1], [Use glib2 libraries and header files])
|
||||||
|
OPTIONAL_NOTIFY_CFLAGS="${GIO2_CFLAGS}"
|
||||||
|
OPTIONAL_NOTIFY_LIBS="${GIO2_LIBS}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
AC_MSG_ERROR([notification linkage required, but no notification provider was found])
|
AC_MSG_ERROR([notification linkage required, but no notification provider was found])
|
||||||
fi
|
fi
|
||||||
@ -1087,8 +1124,9 @@ OPENCT_CFLAGS: ${OPENCT_CFLAGS}
|
|||||||
OPENCT_LIBS: ${OPENCT_LIBS}
|
OPENCT_LIBS: ${OPENCT_LIBS}
|
||||||
PCSC_CFLAGS: ${PCSC_CFLAGS}
|
PCSC_CFLAGS: ${PCSC_CFLAGS}
|
||||||
CRYPTOTOKENKIT_CFLAGS: ${CRYPTOTOKENKIT_CFLAGS}
|
CRYPTOTOKENKIT_CFLAGS: ${CRYPTOTOKENKIT_CFLAGS}
|
||||||
NOTIFY_CFLAGS: ${NOTIFY_CFLAGS}
|
GDBUS: ${GDBUS}
|
||||||
NOTIFY_LIBS: ${NOTIFY_LIBS}
|
GIO2_CFLAGS: ${GIO2_CFLAGS}
|
||||||
|
GIO2_LIBS: ${GIO2_LIBS}
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -1333,7 +1333,7 @@ scconf_block *sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *drive
|
|||||||
* @param value pointer to data used for CRC calculation
|
* @param value pointer to data used for CRC calculation
|
||||||
* @param len length of data used for CRC calculation
|
* @param len length of data used for CRC calculation
|
||||||
*/
|
*/
|
||||||
unsigned sc_crc32(unsigned char *value, size_t len);
|
unsigned sc_crc32(const unsigned char *value, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to initialize the @c sc_remote_data structure --
|
* Used to initialize the @c sc_remote_data structure --
|
||||||
|
@ -949,7 +949,7 @@ void sc_remote_data_init(struct sc_remote_data *rdata)
|
|||||||
|
|
||||||
static unsigned long sc_CRC_tab32[256];
|
static unsigned long sc_CRC_tab32[256];
|
||||||
static int sc_CRC_tab32_initialized = 0;
|
static int sc_CRC_tab32_initialized = 0;
|
||||||
unsigned sc_crc32(unsigned char *value, size_t len)
|
unsigned sc_crc32(const unsigned char *value, size_t len)
|
||||||
{
|
{
|
||||||
size_t ii, jj;
|
size_t ii, jj;
|
||||||
unsigned long crc;
|
unsigned long crc;
|
||||||
|
@ -24,6 +24,25 @@
|
|||||||
#include "ui/notify.h"
|
#include "ui/notify.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
void Sleep(unsigned int Milliseconds)
|
||||||
|
{
|
||||||
|
struct timespec req, rem;
|
||||||
|
|
||||||
|
if (Milliseconds > 999) {
|
||||||
|
req.tv_sec = Milliseconds / 1000; /* Must be Non-Negative */
|
||||||
|
req.tv_nsec = (Milliseconds - (req.tv_sec * 1000)) * 1000000; /* Must be in range of 0 to 999999999 */
|
||||||
|
} else {
|
||||||
|
req.tv_sec = 0; /* Must be Non-Negative */
|
||||||
|
req.tv_nsec = Milliseconds * 1000000; /* Must be in range of 0 to 999999999 */
|
||||||
|
}
|
||||||
|
|
||||||
|
nanosleep(&req , &rem);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -33,7 +52,7 @@ main (int argc, char **argv)
|
|||||||
text = argv[2];
|
text = argv[2];
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 2:
|
case 2:
|
||||||
text = argv[1];
|
title = argv[1];
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 1:
|
case 1:
|
||||||
break;
|
break;
|
||||||
@ -44,6 +63,7 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
sc_notify_init();
|
sc_notify_init();
|
||||||
sc_notify(title, text);
|
sc_notify(title, text);
|
||||||
|
Sleep(250);
|
||||||
sc_notify_close();
|
sc_notify_close();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
193
src/ui/notify.c
193
src/ui/notify.c
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
|
||||||
#if defined(ENABLE_NOTIFY) && defined(__APPLE__)
|
#if defined(ENABLE_NOTIFY) && (defined(__APPLE__) || defined(GDBUS))
|
||||||
|
|
||||||
#include "libopensc/log.h"
|
#include "libopensc/log.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -61,6 +61,10 @@ void sc_notify_close(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_NOTIFY) && defined(__APPLE__)
|
||||||
|
|
||||||
static void notify_proxy(struct sc_context *ctx,
|
static void notify_proxy(struct sc_context *ctx,
|
||||||
const char *title, const char* subtitle,
|
const char *title, const char* subtitle,
|
||||||
const char *text, const char *icon, const char *sound,
|
const char *text, const char *icon, const char *sound,
|
||||||
@ -165,6 +169,151 @@ void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
|
|||||||
notify_proxy(ctx, title, NULL, text, icon, NULL, group);
|
notify_proxy(ctx, title, NULL, text, icon, NULL, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(ENABLE_NOTIFY) && defined(GDBUS)
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
/* save the notification's id for replacement with a new one */
|
||||||
|
uint32_t message_id = 0;
|
||||||
|
|
||||||
|
static void notify_gio(struct sc_context *ctx,
|
||||||
|
const char *title, const char *text, const char *icon,
|
||||||
|
const char *group)
|
||||||
|
{
|
||||||
|
char message_id_str[22];
|
||||||
|
int pipefd[2];
|
||||||
|
int pass_to_pipe = 1;
|
||||||
|
snprintf(message_id_str, sizeof message_id_str, "%"PRIu32, message_id);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == pipe(pipefd)) {
|
||||||
|
pass_to_pipe = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
switch (child) {
|
||||||
|
case 0:
|
||||||
|
/* child process */
|
||||||
|
if (pass_to_pipe) {
|
||||||
|
/* close reading end of the pipe */
|
||||||
|
close(pipefd[0]);
|
||||||
|
/* send stdout to the pipe */
|
||||||
|
dup2(pipefd[1], 1);
|
||||||
|
/* this descriptor is no longer needed */
|
||||||
|
close(pipefd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 > execl(GDBUS, GDBUS,
|
||||||
|
"call", "--session",
|
||||||
|
"--dest", "org.freedesktop.Notifications",
|
||||||
|
"--object-path", "/org/freedesktop/Notifications",
|
||||||
|
"--method", "org.freedesktop.Notifications.Notify",
|
||||||
|
"org.opensc-project",
|
||||||
|
message_id_str,
|
||||||
|
icon ? icon : "",
|
||||||
|
title ? title : "",
|
||||||
|
text ? text : "",
|
||||||
|
"[]", "{}", "5000",
|
||||||
|
(char *) NULL)) {
|
||||||
|
perror("exec failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
sc_log(ctx, "failed to fork for notification");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* parent process */
|
||||||
|
|
||||||
|
if (ctx) {
|
||||||
|
sc_log(ctx, "Created %ld for notification:", (long) child);
|
||||||
|
sc_log(ctx, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", GDBUS,
|
||||||
|
"call", "--session",
|
||||||
|
"--dest", "org.freedesktop.Notifications",
|
||||||
|
"--object-path", "/org/freedesktop/Notifications",
|
||||||
|
"--method", "org.freedesktop.Notifications.Notify",
|
||||||
|
"org.opensc-project",
|
||||||
|
message_id_str,
|
||||||
|
icon ? icon : "",
|
||||||
|
title ? title : "",
|
||||||
|
text ? text : "",
|
||||||
|
"[]", "{}", "5000");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pass_to_pipe) {
|
||||||
|
/* close the write end of the pipe */
|
||||||
|
close(pipefd[1]);
|
||||||
|
memset(message_id_str, '\0', sizeof message_id_str);
|
||||||
|
if (0 < read(pipefd[0], message_id_str, sizeof(message_id_str))) {
|
||||||
|
message_id_str[(sizeof message_id_str) - 1] = '\0';
|
||||||
|
sscanf(message_id_str, "(uint32 %"SCNu32",)", &message_id);
|
||||||
|
}
|
||||||
|
/* close the read end of the pipe */
|
||||||
|
close(pipefd[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ENABLE_NOTIFY) && defined(ENABLE_GIO2)
|
||||||
|
|
||||||
|
static GtkApplication *application = NULL;
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
void sc_notify_init(void)
|
||||||
|
{
|
||||||
|
sc_notify_close();
|
||||||
|
application = g_application_new("org.opensc-project", G_APPLICATION_FLAGS_NONE);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GIcon *gicon = NULL;
|
||||||
|
GNotification *notification = g_notification_new (title);
|
||||||
|
if (!notification) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_notification_set_body (notification, text);
|
||||||
|
if (icon) {
|
||||||
|
gicon = g_themed_icon_new (icon);
|
||||||
|
if (gicon) {
|
||||||
|
g_notification_set_icon (notification, gicon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_application_send_notification(application, group, notification);
|
||||||
|
|
||||||
|
if (gicon) {
|
||||||
|
g_object_unref(gicon);
|
||||||
|
}
|
||||||
|
g_object_unref(notification);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void sc_notify_init(void) {}
|
void sc_notify_init(void) {}
|
||||||
@ -174,3 +323,45 @@ void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
|
|||||||
struct sc_pkcs15_card *p15card, enum ui_str id) {}
|
struct sc_pkcs15_card *p15card, enum ui_str id) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_NOTIFY) && (defined(ENABLE_GIO2) || defined(GDBUS))
|
||||||
|
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:
|
||||||
|
icon = "dialog-information";
|
||||||
|
break;
|
||||||
|
case NOTIFY_CARD_REMOVED:
|
||||||
|
icon = "media-removed";
|
||||||
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user