1 /* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "array.h"
5 #include "mail-storage.h"
6 #include "mail-types.h"
7 
8 #include "push-notification-drivers.h"
9 #include "push-notification-events.h"
10 #include "push-notification-event-flagsset.h"
11 #include "push-notification-txn-msg.h"
12 
13 
14 #define EVENT_NAME "FlagsSet"
15 
16 static struct push_notification_event_flagsset_config default_config;
17 
18 
push_notification_event_flagsset_default_config(void)19 static void *push_notification_event_flagsset_default_config(void)
20 {
21 	i_zero(&default_config);
22 
23 	return &default_config;
24 }
25 
26 static void
push_notification_event_flagsset_debug_msg(struct push_notification_txn_event * event)27 push_notification_event_flagsset_debug_msg(
28 	struct push_notification_txn_event *event)
29 {
30 	struct push_notification_event_flagsset_data *data = event->data;
31 	const char *keyword;
32 
33 	if ((data->flags_set & MAIL_ANSWERED) != 0)
34 		i_debug("%s: Answered flag set", EVENT_NAME);
35 	if ((data->flags_set & MAIL_FLAGGED) != 0)
36 		i_debug("%s: Flagged flag set", EVENT_NAME);
37 	if ((data->flags_set & MAIL_DELETED) != 0)
38 		i_debug("%s: Deleted flag set", EVENT_NAME);
39 	if ((data->flags_set & MAIL_SEEN) != 0)
40 		i_debug("%s: Seen flag set", EVENT_NAME);
41 	if ((data->flags_set & MAIL_DRAFT) != 0)
42 		i_debug("%s: Draft flag set", EVENT_NAME);
43 
44 	array_foreach_elem(&data->keywords_set, keyword)
45 		i_debug("%s: Keyword set [%s]", EVENT_NAME, keyword);
46 }
47 
48 static struct push_notification_event_flagsset_data *
push_notification_event_flagsset_get_data(struct push_notification_txn * ptxn,struct push_notification_txn_msg * msg,struct push_notification_event_config * ec)49 push_notification_event_flagsset_get_data(
50 	struct push_notification_txn *ptxn,
51 	struct push_notification_txn_msg *msg,
52 	struct push_notification_event_config *ec)
53 {
54 	struct push_notification_event_flagsset_data *data;
55 
56 	data = push_notification_txn_msg_get_eventdata(msg, EVENT_NAME);
57 	if (data == NULL) {
58 		data = p_new(ptxn->pool,
59 			     struct push_notification_event_flagsset_data, 1);
60 		data->flags_set = 0;
61 		p_array_init(&data->keywords_set, ptxn->pool, 4);
62 
63 		push_notification_txn_msg_set_eventdata(ptxn, msg, ec, data);
64 	}
65 
66 	return data;
67 }
68 
69 static void
push_notification_event_flagsset_flags_event(struct push_notification_txn * ptxn,struct push_notification_event_config * ec,struct push_notification_txn_msg * msg,struct mail * mail,enum mail_flags old_flags)70 push_notification_event_flagsset_flags_event(
71 	struct push_notification_txn *ptxn,
72 	struct push_notification_event_config *ec,
73 	struct push_notification_txn_msg *msg, struct mail *mail,
74 	enum mail_flags old_flags)
75 {
76 	struct push_notification_event_flagsset_config *config =
77 		(struct push_notification_event_flagsset_config *)ec->config;
78 	struct push_notification_event_flagsset_data *data;
79 	enum mail_flags flag_check_always[] = {
80 		MAIL_ANSWERED,
81 		MAIL_DRAFT,
82 		MAIL_FLAGGED
83 	};
84 	enum mail_flags flags, flags_set = 0;
85 	unsigned int i;
86 
87 	flags = mail_get_flags(mail);
88 
89 	for (i = 0; i < N_ELEMENTS(flag_check_always); i++) {
90 		if ((flags & flag_check_always[i]) != 0 &&
91 		    (old_flags & flag_check_always[i]) == 0)
92 			flags_set |= flag_check_always[i];
93 	}
94 
95 	if (!config->hide_deleted && (flags & MAIL_DELETED) != 0 &&
96 	    (old_flags & MAIL_DELETED) == 0) {
97 		flags_set |= MAIL_DELETED;
98 	}
99 
100 	if (!config->hide_seen && (flags & MAIL_SEEN) != 0 &&
101 	    (old_flags & MAIL_SEEN) == 0) {
102 		flags_set |= MAIL_SEEN;
103 	}
104 
105 	/* Only create data element if at least one flag was set. */
106 	if (flags_set != 0) {
107 		data = push_notification_event_flagsset_get_data(ptxn, msg, ec);
108 		data->flags_set |= flags_set;
109 	}
110 }
111 
112 static void
push_notification_event_flagsset_keywords_event(struct push_notification_txn * ptxn,struct push_notification_event_config * ec,struct push_notification_txn_msg * msg,struct mail * mail,const char * const * old_keywords)113 push_notification_event_flagsset_keywords_event(
114 	struct push_notification_txn *ptxn,
115 	struct push_notification_event_config *ec,
116 	struct push_notification_txn_msg *msg, struct mail *mail,
117 	const char *const *old_keywords)
118 {
119 	struct push_notification_event_flagsset_data *data;
120 	const char *k, *const *keywords, *const *op;
121 
122 	data = push_notification_event_flagsset_get_data(ptxn, msg, ec);
123 	keywords = mail_get_keywords(mail);
124 
125 	for (; *keywords != NULL; keywords++) {
126 		for (op = old_keywords; *op != NULL; op++) {
127 			if (strcmp(*keywords, *op) == 0)
128 				break;
129 		}
130 
131 		if (*op == NULL) {
132 			k = p_strdup(ptxn->pool, *keywords);
133 			array_push_back(&data->keywords_set, &k);
134 		}
135 	}
136 }
137 
138 static void
push_notification_event_flagsset_free_msg(struct push_notification_txn_event * event)139 push_notification_event_flagsset_free_msg(
140 	struct push_notification_txn_event *event)
141 {
142 	struct push_notification_event_flagsset_data *data = event->data;
143 
144 	if (array_is_created(&data->keywords_set))
145 	   array_free(&data->keywords_set);
146 }
147 
148 /* Event definition */
149 
150 extern struct push_notification_event push_notification_event_flagsset;
151 
152 struct push_notification_event push_notification_event_flagsset = {
153 	.name = EVENT_NAME,
154 	.init = {
155 		.default_config =
156 			push_notification_event_flagsset_default_config,
157 	},
158 	.msg = {
159 		.debug_msg = push_notification_event_flagsset_debug_msg,
160 		.free_msg = push_notification_event_flagsset_free_msg,
161 	},
162 	.msg_triggers = {
163 		.flagchange = push_notification_event_flagsset_flags_event,
164 		.keywordchange =
165 			push_notification_event_flagsset_keywords_event,
166 	},
167 };
168