1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: keyword.c 807 2007-11-09 01:21:33Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2016 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 #include "../pith/headers.h"
20 #include "../pith/keyword.h"
21 #include "../pith/state.h"
22 #include "../pith/flag.h"
23 #include "../pith/string.h"
24 #include "../pith/status.h"
25 #include "../pith/util.h"
34 * Read the keywords array into a KEYWORD_S structure.
35 * Make sure that all of the strings are UTF-8.
38 init_keyword_list(char **keywordarray
)
40 char **t
, *nickname
, *keyword
;
41 KEYWORD_S
*head
= NULL
, **tail
;
44 for(t
= keywordarray
; t
&& *t
&& **t
; t
++){
45 nickname
= keyword
= NULL
;
46 get_pair(*t
, &nickname
, &keyword
, 0, 0);
47 *tail
= new_keyword_s(keyword
, nickname
);
48 tail
= &(*tail
)->next
;
51 fs_give((void **) &keyword
);
54 fs_give((void **) &nickname
);
62 new_keyword_s(char *keyword
, char *nickname
)
66 kw
= (KEYWORD_S
*) fs_get(sizeof(*kw
));
67 memset(kw
, 0, sizeof(*kw
));
69 if(keyword
&& *keyword
)
70 kw
->kw
= cpystr(keyword
);
72 if(nickname
&& *nickname
)
73 kw
->nick
= cpystr(nickname
);
80 free_keyword_list(KEYWORD_S
**kl
)
84 free_keyword_list(&(*kl
)->next
);
87 fs_give((void **) &(*kl
)->kw
);
90 fs_give((void **) &(*kl
)->nick
);
92 fs_give((void **) kl
);
98 * Return a pointer to the keyword associated with a nickname, or the
99 * input itself if no match.
102 nick_to_keyword(char *nick
)
108 for(kw
= ps_global
->keywords
; kw
; kw
= kw
->next
)
109 if(!strcmp(nick
, kw
->nick
? kw
->nick
: kw
->kw
? kw
->kw
: "")){
121 * Return a pointer to the nickname associated with a keyword, or the
122 * input itself if no match.
125 keyword_to_nick(char *keyword
)
131 for(kw
= ps_global
->keywords
; kw
; kw
= kw
->next
)
132 if(!strcmp(keyword
, kw
->kw
? kw
->kw
: "")){
144 * Return a pointer to the keyword associated with an initial, or the
145 * input itself if no match.
146 * Only works for ascii initials.
149 initial_to_keyword(char *initial
)
157 if(initial
[0] && initial
[1] == '\0'){
159 if(isascii(init
) && isupper(init
))
160 init
= tolower((unsigned char) init
);
162 for(kw
= ps_global
->keywords
; kw
; kw
= kw
->next
){
164 kwinit
= kw
->nick
[0];
168 if(isascii(kwinit
) && isupper(kwinit
))
169 kwinit
= tolower((unsigned char) kwinit
);
183 user_flag_is_set(MAILSTREAM
*stream
, long unsigned int rawno
, char *keyword
)
188 if(stream
&& keyword
&& keyword
[0]){
189 if(rawno
> 0L && stream
190 && rawno
<= stream
->nmsgs
191 && (mc
= mail_elt(stream
, rawno
)) != NULL
){
192 j
= user_flag_index(stream
, keyword
);
193 if(j
>= 0 && j
< NUSERFLAGS
&& ((1 << j
) & mc
->user_flags
))
203 * Returns the bit position of the keyword in stream, else -1.
206 user_flag_index(MAILSTREAM
*stream
, char *keyword
)
211 if(stream
&& keyword
&& keyword
[0]){
212 for(i
= 0; i
< NUSERFLAGS
; i
++)
213 if((p
=stream_to_user_flag_name(stream
, i
)) && !strucmp(keyword
, p
)){
224 stream_to_user_flag_name(MAILSTREAM
*stream
, int k
)
226 if(stream
&& stream
->user_flags
&& k
>= 0 && k
< NUSERFLAGS
)
227 return(stream
->user_flags
[k
]);
234 some_user_flags_defined(MAILSTREAM
*stream
)
239 for(k
= 0; k
< NUSERFLAGS
; k
++)
240 if(stream_to_user_flag_name(stream
, k
))
247 /*----------------------------------------------------------------------
248 Build flags string based on requested flags and what's set in messagecache
250 Args: flags -- flags to test
252 Result: allocated, space-delimited flags string is returned
255 flag_string(MAILSTREAM
*stream
, long rawno
, long int flags
)
258 char *p
, *q
, *returned_flags
= NULL
;
262 mc
= (rawno
> 0L && stream
&& rawno
<= stream
->nmsgs
)
263 ? mail_elt(stream
, rawno
) : NULL
;
265 return returned_flags
;
267 if((flags
& F_DEL
) && mc
->deleted
)
268 len
+= strlen("\\DELETED") + 1;
270 if((flags
& F_ANS
) && mc
->answered
)
271 len
+= strlen("\\ANSWERED") + 1;
273 if((flags
& F_FWD
) && user_flag_is_set(stream
, rawno
, FORWARDED_FLAG
))
274 len
+= strlen(FORWARDED_FLAG
) + 1;
276 if((flags
& F_FLAG
) && mc
->flagged
)
277 len
+= strlen("\\FLAGGED") + 1;
279 if((flags
& F_SEEN
) && mc
->seen
)
280 len
+= strlen("\\SEEN") + 1;
282 if((flags
& F_KEYWORD
) && stream
->user_flags
){
283 for(k
= 0; k
< NUSERFLAGS
; k
++){
284 if((q
=stream_to_user_flag_name(stream
, k
))
285 && user_flag_is_set(stream
, rawno
, q
)){
286 len
+= strlen(q
) + 1;
291 returned_flags
= (char *) fs_get((len
+1) * sizeof(char));
295 if((flags
& F_DEL
) && mc
->deleted
)
296 sstrncpy(&p
, "\\DELETED ", len
+1-(p
-returned_flags
));
298 if((flags
& F_ANS
) && mc
->answered
)
299 sstrncpy(&p
, "\\ANSWERED ", len
+1-(p
-returned_flags
));
301 if((flags
& F_FWD
) && user_flag_is_set(stream
, rawno
, FORWARDED_FLAG
)){
302 sstrncpy(&p
, FORWARDED_FLAG
, len
+1-(p
-returned_flags
));
303 sstrncpy(&p
, " ", len
+1-(p
-returned_flags
));
306 if((flags
& F_FLAG
) && mc
->flagged
)
307 sstrncpy(&p
, "\\FLAGGED ", len
+1-(p
-returned_flags
));
309 if((flags
& F_SEEN
) && mc
->seen
)
310 sstrncpy(&p
, "\\SEEN ", len
+1-(p
-returned_flags
));
312 if((flags
& F_KEYWORD
) && stream
->user_flags
){
313 for(k
= 0; k
< NUSERFLAGS
; k
++){
314 if((q
=stream_to_user_flag_name(stream
, k
))
315 && user_flag_is_set(stream
, rawno
, q
)){
316 sstrncpy(&p
, q
, len
+1-(p
-returned_flags
));
317 sstrncpy(&p
, " ", len
+1-(p
-returned_flags
));
318 len
+= strlen(p
) + 1;
323 if(p
!= returned_flags
&& (len
+1-(p
-returned_flags
)>0))
326 return returned_flags
;
331 get_msgno_by_msg_id(MAILSTREAM
*stream
, char *message_id
, MSGNO_S
*msgmap
)
333 SEARCHPGM
*pgm
= NULL
;
334 long hint
= mn_m2raw(msgmap
, mn_get_cur(msgmap
));
338 extern MAILSTREAM
*mm_search_stream
;
339 extern long mm_search_count
;
341 if(!(message_id
&& message_id
[0]) || stream
->nmsgs
< 1L)
344 mm_search_count
= 0L;
345 mm_search_stream
= stream
;
346 while(mm_search_count
== 0L && iter
++ < 3
347 && (pgm
= mail_newsearchpgm()) != NULL
){
348 pgm
->message_id
= mail_newstringlist();
349 pgm
->message_id
->text
.data
= (unsigned char *) cpystr(message_id
);
350 pgm
->message_id
->text
.size
= strlen(message_id
);
352 if(iter
> 1 || hint
> stream
->nmsgs
)
356 /* restrict to hint message on first try */
357 pgm
->msgno
= mail_newsearchset();
358 pgm
->msgno
->first
= pgm
->msgno
->last
= hint
;
361 /* restrict to last 50 messages on 2nd try */
362 pgm
->msgno
= mail_newsearchset();
363 if(stream
->nmsgs
> 100L)
364 pgm
->msgno
->first
= stream
->nmsgs
-50L;
366 pgm
->msgno
->first
= 1L;
370 pgm
->msgno
->last
= stream
->nmsgs
;
373 pine_mail_search_full(stream
, NULL
, pgm
, SE_NOPREFETCH
| SE_FREE
);
376 for(newmsgno
=stream
->nmsgs
; newmsgno
> 0L; newmsgno
--)
377 if((mc
= mail_elt(stream
, newmsgno
)) && mc
->searched
)
382 return(mn_raw2m(msgmap
, newmsgno
));
387 * These chars are not allowed in keywords.
389 * Returns 0 if ok, 1 if not.
390 * Returns an allocated error message on error.
393 keyword_check(char *kw
, char **error
)
401 kw
= nick_to_keyword(kw
);
403 for(p
= kw
; p
&& *p
; p
++)
406 *error
= cpystr("Keywords must be all ASCII characters");
411 if((t
= strindex(kw
, SPACE
)) ||
412 (t
= strindex(kw
, '{')) ||
413 (t
= strindex(kw
, '(')) ||
414 (t
= strindex(kw
, ')')) ||
415 (t
= strindex(kw
, ']')) ||
416 (t
= strindex(kw
, '%')) ||
417 (t
= strindex(kw
, '"')) ||
418 (t
= strindex(kw
, '\\')) ||
419 (t
= strindex(kw
, '*'))){
426 snprintf(buf
, sizeof(buf
), "%s not allowed in keywords",
434 *error
= cpystr(buf
);