Linux: Added support for notifications

This commit is contained in:
Frank Morgner 2017-06-08 16:10:43 +02:00
parent 417a409406
commit cd62c6cdf5
5 changed files with 257 additions and 8 deletions

View File

@ -463,6 +463,37 @@ case "${host}" in
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
@ -482,8 +513,14 @@ esac
if test "${enable_notify}" = "yes"; then
if test "${have_notify}" = "yes"; then
AC_DEFINE([ENABLE_NOTIFY], [1], [Use notification libraries and header files])
OPTIONAL_NOTIFY_CFLAGS="${NOTIFY_CFLAGS}"
OPTIONAL_NOTIFY_LIBS="${NOTIFY_LIBS}"
if test "${have_gdbus}" = "yes"; then
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
AC_MSG_ERROR([notification linkage required, but no notification provider was found])
fi
@ -1087,8 +1124,9 @@ OPENCT_CFLAGS: ${OPENCT_CFLAGS}
OPENCT_LIBS: ${OPENCT_LIBS}
PCSC_CFLAGS: ${PCSC_CFLAGS}
CRYPTOTOKENKIT_CFLAGS: ${CRYPTOTOKENKIT_CFLAGS}
NOTIFY_CFLAGS: ${NOTIFY_CFLAGS}
NOTIFY_LIBS: ${NOTIFY_LIBS}
GDBUS: ${GDBUS}
GIO2_CFLAGS: ${GIO2_CFLAGS}
GIO2_LIBS: ${GIO2_LIBS}
EOF

View File

@ -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 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 --

View File

@ -949,7 +949,7 @@ void sc_remote_data_init(struct sc_remote_data *rdata)
static unsigned long sc_CRC_tab32[256];
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;
unsigned long crc;

View File

@ -24,6 +24,25 @@
#include "ui/notify.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
main (int argc, char **argv)
{
@ -33,7 +52,7 @@ main (int argc, char **argv)
text = argv[2];
/* fall through */
case 2:
text = argv[1];
title = argv[1];
/* fall through */
case 1:
break;
@ -44,6 +63,7 @@ main (int argc, char **argv)
}
sc_notify_init();
sc_notify(title, text);
Sleep(250);
sc_notify_close();
return 0;

View File

@ -24,7 +24,7 @@
#include "notify.h"
#if defined(ENABLE_NOTIFY) && defined(__APPLE__)
#if defined(ENABLE_NOTIFY) && (defined(__APPLE__) || defined(GDBUS))
#include "libopensc/log.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,
const char *title, const char* subtitle,
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);
}
#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
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) {}
#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