cmd-x-apple-push-service.c [plain text]
#include "imap-common.h"
#include "imap-id.h"
#include "str.h"
#include "home-expand.h"
#include "mail-user.h"
#include "imap-quote.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/socket.h>
#define APS_VERSION "1"
typedef struct msg_data_s {
unsigned long msg;
unsigned long pid;
char d1[128];
char d2[512];
char d3[512];
char d4[512];
} msg_data_t;
static void do_notify(const char *username, const char *aps_acct_id,
const char *aps_dev_token, const char *aps_sub_topic)
{
const char *push_notify_path = "/var/dovecot/push_notify";
msg_data_t msg_data;
memset(&msg_data, 0, sizeof(struct msg_data_s));
msg_data.msg = 2;
strlcpy(msg_data.d1, username, sizeof(msg_data.d1));
strlcpy(msg_data.d2, aps_acct_id, sizeof(msg_data.d2));
strlcpy(msg_data.d3, aps_dev_token, sizeof(msg_data.d3));
strlcpy(msg_data.d4, aps_sub_topic, sizeof(msg_data.d4));
int soc = socket( AF_UNIX, SOCK_DGRAM, 0 );
if ( soc < 0 ) {
i_warning( "open notify socket failed(%d): %m", soc );
return;
}
struct sockaddr_un sock_addr;
memset( &sock_addr, 0, sizeof(struct sockaddr_un));
sock_addr.sun_family = AF_UNIX;
strlcpy( sock_addr.sun_path, push_notify_path, sizeof(sock_addr.sun_path) );
socklen_t sock_len = sizeof(sock_addr.sun_family) + strlen(sock_addr.sun_path) + 1;
int rc = connect(soc, (struct sockaddr *) &sock_addr, sock_len);
if ( rc < 0 ) {
i_warning("connect to notify socket %s failed: %m",
push_notify_path);
close(soc);
return;
}
rc = send(soc, (void *)&msg_data, sizeof(msg_data), 0);
if ( rc < 0 )
i_warning("send to notify socket %s failed: %m",
push_notify_path);
close(soc);
}
static const char *aps_reply_generate (struct client_command_context *cmd,
const struct imap_arg *args)
{
const char *aps_topic = cmd->client->set->aps_topic;
const char *aps_ver=NULL;
const char *aps_acct_id=NULL;
const char *aps_dev_token=NULL;
const char *aps_sub_topic=NULL;
const char *key, *value;
if (aps_topic == NULL || *aps_topic == '\0')
return NULL;
while (imap_arg_get_astring(&args[0], &key) &&
imap_arg_get_astring(&args[1], &value)) {
if (strcasecmp(key, "aps-version") == 0)
aps_ver = t_strdup(value);
else if (strcasecmp(key, "aps-account-id") == 0)
aps_acct_id = t_strdup(value);
else if (strcasecmp(key, "aps-device-token") == 0)
aps_dev_token = t_strdup(value);
else if (strcasecmp(key, "aps-subtopic") == 0)
aps_sub_topic = t_strdup(value);
else
return NULL;
args += 2;
}
if ( aps_ver && aps_acct_id && aps_dev_token && aps_sub_topic ) {
do_notify(cmd->client->user->username, aps_acct_id,
aps_dev_token, aps_sub_topic);
string_t *str = t_str_new(256);
imap_dquote_append( str, "aps-version" );
str_append_c(str, ' ');
imap_dquote_append( str, APS_VERSION );
str_append_c(str, ' ');
imap_dquote_append( str, "aps-topic" );
str_append_c(str, ' ');
imap_dquote_append( str, aps_topic );
return str_c(str);
}
return NULL;
}
bool cmd_x_apple_push_service(struct client_command_context *cmd)
{
const struct imap_arg *args;
if (!client_read_args(cmd, 0, 0, &args))
return FALSE;
const char *reply = aps_reply_generate(cmd, args);
if (reply != NULL)
client_send_line(cmd->client,
t_strdup_printf("* XAPPLEPUSHSERVICE %s",
reply));
client_send_tagline(cmd, "OK XAPPLEPUSHSERVICE completed.");
return TRUE;
}