/* * Returns the index cache entry associated with this message. * If it doesn't already exist it is instantiated. */ ICE_S * fetch_ice(MAILSTREAM *stream, long unsigned int rawno) { PINELT_S **peltp; MESSAGECACHE *mc; if(!stream || rawno < 1L || rawno > stream->nmsgs) return NULL; if(!(mc = mail_elt(stream, rawno))) return NULL; /* * any private elt data yet? */ if((*(peltp = (PINELT_S **) &mc->sparep) == NULL)){ *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S)); memset(*peltp, 0, sizeof(PINELT_S)); } if((*peltp)->ice == NULL) (*peltp)->ice = new_ice(); if(need_format_setup(stream) && setup_header_widths) (*setup_header_widths)(stream); return((*peltp)->ice); }
Variant f_imap_mailboxmsginfo(const Resource& imap_stream) { ImapStream *obj = imap_stream.getTyped<ImapStream>(); Object ret(SystemLib::AllocStdClassObject()); int64_t unreadmsg = 0, deletedmsg = 0, msize = 0; for (unsigned long i = 1; i <= obj->m_stream->nmsgs; i++) { MESSAGECACHE * cache = mail_elt (obj->m_stream, i); mail_fetchstructure (obj->m_stream, i, NIL); if (!cache->seen || cache->recent) { unreadmsg++; } if (cache->deleted) { deletedmsg++; } msize = msize + cache->rfc822_size; } ret.o_set("Unread", (int64_t)unreadmsg); ret.o_set("Deleted", (int64_t)deletedmsg); ret.o_set("Nmsgs", (int64_t)obj->m_stream->nmsgs); ret.o_set("Size", (int64_t)msize); char date[100]; rfc822_date(date); ret.o_set("Date", String(date, CopyString)); ret.o_set("Driver", String(obj->m_stream->dtb->name, CopyString)); ret.o_set("Mailbox", String(obj->m_stream->mailbox, CopyString)); ret.o_set("Recent", (int64_t)msize); return ret; }
long get_msgno_by_msg_id(MAILSTREAM *stream, char *message_id, MSGNO_S *msgmap) { SEARCHPGM *pgm = NULL; long hint = mn_m2raw(msgmap, mn_get_cur(msgmap)); long newmsgno = -1L; int iter = 0; MESSAGECACHE *mc; extern MAILSTREAM *mm_search_stream; extern long mm_search_count; if(!(message_id && message_id[0]) || stream->nmsgs < 1L) return(newmsgno); mm_search_count = 0L; mm_search_stream = stream; while(mm_search_count == 0L && iter++ < 3 && (pgm = mail_newsearchpgm()) != NULL){ pgm->message_id = mail_newstringlist(); pgm->message_id->text.data = (unsigned char *) cpystr(message_id); pgm->message_id->text.size = strlen(message_id); if(iter > 1 || hint > stream->nmsgs) iter++; if(iter == 1){ /* restrict to hint message on first try */ pgm->msgno = mail_newsearchset(); pgm->msgno->first = pgm->msgno->last = hint; } else if(iter == 2){ /* restrict to last 50 messages on 2nd try */ pgm->msgno = mail_newsearchset(); if(stream->nmsgs > 100L) pgm->msgno->first = stream->nmsgs-50L; else{ pgm->msgno->first = 1L; iter++; } pgm->msgno->last = stream->nmsgs; } pine_mail_search_full(stream, NULL, pgm, SE_NOPREFETCH | SE_FREE); if(mm_search_count){ for(newmsgno=stream->nmsgs; newmsgno > 0L; newmsgno--) if((mc = mail_elt(stream, newmsgno)) && mc->searched) break; } } return(mn_raw2m(msgmap, newmsgno)); }
/*---------------------------------------------------------------------- Got thru the message mapping table, and remove messages with DELETED flag Accepts: stream -- mail stream to removed message references from msgs -- pointer to message manipulation struct f -- flags to use a purge criteria ----*/ void msgno_exclude_deleted(MAILSTREAM *stream, MSGNO_S *msgs, char *sequence) { long i, rawno; MESSAGECACHE *mc; int need_isort_reset = 0; if(!msgs || msgs->max_msgno < 1L) return; /* * With 3.91 we're using a new strategy for finding and operating * on all the messages with deleted status. The idea is to do a * mail_search for deleted messages so the elt's "searched" bit gets * set, and then to scan the elt's for them and set our local bit * to indicate they're excluded... */ (void) count_flagged(stream, F_DEL); if(sequence) mail_sequence (stream,sequence); /* * Start with the end of the folder and work backwards so that * msgno_exclude doesn't have to shift the entire array each time when * there are lots of deleteds. In fact, if everything is deleted (like * might be the case in a huge newsgroup) then it never has to shift * anything. It is always at the end of the array just eliminating the * last one instead. So instead of an n**2 operation, it is n. */ for(i = msgs->max_msgno; i >= 1L; i--) if((rawno = mn_m2raw(msgs, i)) > 0L && stream && rawno <= stream->nmsgs && (mc = mail_elt(stream, rawno)) && (sequence ? mc->sequence : 1) && ((mc->valid && mc->deleted) || (!mc->valid && mc->searched))){ msgno_exclude(stream, msgs, i, 0); need_isort_reset++; } if(need_isort_reset) msgno_reset_isort(msgs); /* * If we excluded away a zoomed display, unhide everything... */ if(msgs->max_msgno > 0L && any_lflagged(msgs, MN_HIDE) >= msgs->max_msgno) for(i = 1L; i <= msgs->max_msgno; i++) set_lflag(stream, msgs, i, MN_HIDE, 0); }
/* * Erase a particular entry in the cache. */ void clear_index_cache_ent(MAILSTREAM *stream, long int msgno, unsigned int flags) { long rawno = -1L; PINELT_S **peltp; MESSAGECACHE *mc; if(stream){ if(flags && IC_USE_RAW_MSGNO) rawno = msgno; else rawno = mn_m2raw(sp_msgmap(stream), msgno); if(rawno > 0L && rawno <= stream->nmsgs){ mc = mail_elt(stream, rawno); if(mc && mc->sparep){ peltp = (PINELT_S **) &mc->sparep; if((*peltp)->ice){ /* * This is intended to be a lightweight reset of * just the widths and print_format strings. For example, * the width of the screen changed and nothing else. * We simply unset the widths_done bit and it * is up to the drawer to free and recalculate the * print_format strings and to reset the widths. * * The else case is a clear of the entire cache entry * leaving behind only the empty structure. */ if(flags & IC_CLEAR_WIDTHS_DONE){ (*peltp)->ice->widths_done = 0; /* also zero out hash value */ (*peltp)->ice->id = 0; if((*peltp)->ice->tice){ (*peltp)->ice->tice->widths_done = 0; /* also zero out hash value */ (*peltp)->ice->tice->id = 0; } } else clear_ice(&(*peltp)->ice); } } } } }
void ImapClient::fetchFlags(const std::string& aHost, const std::string& aUserName, const std::string& aPassword, const std::string& aMailbox, unsigned long aMessageNumber, std::vector<int>& aFlagsVector, const bool aUid) { #include "linkage.c" MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); // convert aMessageNumber to message sequence number if necessary std::string lSequenceNumber; std::stringstream lConverter; lConverter << aMessageNumber; lConverter >> lSequenceNumber; char* lSequence = const_cast<char*>(lSequenceNumber.c_str()); // update cache for this message (could have changed because of a call to setFlags) mail_fetchflags_full(lSource, lSequence, (aUid ? FT_UID : NIL)); if (aUid) { aMessageNumber = mail_msgno(lSource, aMessageNumber); } MESSAGECACHE* lCache = mail_elt(lSource, aMessageNumber); if (lCache->seen == 1) { aFlagsVector[0] = 1; } if (lCache->deleted == 1) { aFlagsVector[1] = 1; } if (lCache->flagged == 1) { aFlagsVector[2] = 1; } if (lCache->answered == 1) { aFlagsVector[3] = 1; } if (lCache->draft == 1) { aFlagsVector[4] = 1; } }
ENVELOPE* ImapClient::fetchStructure(const std::string& aHost, const std::string& aUserName, const std::string& aPassword, const std::string& aMailbox, BODY** aBody, unsigned long aMessageNumber, bool aUid, std::vector<int>& aFlagsVector) { #include "linkage.c" *aBody = mail_newbody(); MAILSTREAM* lSource = getMailStream(aHost, aUserName, aPassword, aMailbox, true); ENVELOPE * lResult = mail_fetchstructure_full (lSource, aMessageNumber, aBody, (aUid ? FT_UID : NIL)); if (!lResult) { throw EmailException("WRONG_ID", "Could not get message - wrong message id."); } if (aUid) { aMessageNumber = mail_msgno(lSource, aMessageNumber); } MESSAGECACHE* lCache = mail_elt(lSource, aMessageNumber); if (lCache->seen == 1) { aFlagsVector[0] = 1; } if (lCache->deleted == 1) { aFlagsVector[1] = 1; } if (lCache->flagged == 1) { aFlagsVector[2] = 1; } if (lCache->answered == 1) { aFlagsVector[3] = 1; } if (lCache->draft == 1) { aFlagsVector[4] = 1; } return lResult; }
int user_flag_is_set(MAILSTREAM *stream, long unsigned int rawno, char *keyword) { int j, is_set = 0; MESSAGECACHE *mc; if(stream && keyword && keyword[0]){ if(rawno > 0L && stream && rawno <= stream->nmsgs && (mc = mail_elt(stream, rawno)) != NULL){ j = user_flag_index(stream, keyword); if(j >= 0 && j < NUSERFLAGS && ((1 << j) & mc->user_flags)) is_set++; } } return(is_set); }
ENVELOPE * ImapClient::fetchEnvelope(const std::string& aHost, const std::string& aUsername, const std::string& aPassword, const std::string& aMailbox, unsigned long aMessageNumber, std::vector<int>& aFlagsVector, const bool aUid) { #include "linkage.c" MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, true); if (aUid) { aMessageNumber = mail_msgno(lSource, aMessageNumber); } ENVELOPE* lResult = mail_fetchenvelope(lSource, aMessageNumber); if (!lResult) { throw EmailException("WRONG_ID", "Could not get message - wrong message id."); } MESSAGECACHE* lCache = mail_elt(lSource, aMessageNumber); if (lCache->seen == 1) { aFlagsVector[0] = 1; } if (lCache->deleted == 1) { aFlagsVector[1] = 1; } if (lCache->flagged == 1) { aFlagsVector[2] = 1; } if (lCache->answered == 1) { aFlagsVector[3] = 1; } if (lCache->draft == 1) { aFlagsVector[4] = 1; } return lResult; }
/* * Checks whether any parts of any of the messages in msgmap are marked * for deletion. */ int msgno_any_deletedparts(MAILSTREAM *stream, MSGNO_S *msgmap) { long n, rawno; PINELT_S *pelt; PARTEX_S **partp; MESSAGECACHE *mc; for(n = mn_first_cur(msgmap); n > 0L; n = mn_next_cur(msgmap)) if((rawno = mn_m2raw(msgmap, n)) > 0L && stream && rawno <= stream->nmsgs && (mc = mail_elt(stream, rawno)) && (pelt = (PINELT_S *) mc->sparep)) for(partp = &pelt->exceptions; *partp; partp = &(*partp)->next) if(((*partp)->handling & MSG_EX_DELETE) && (*partp)->partno && *(*partp)->partno != '0' && isdigit((unsigned char) *(*partp)->partno)) return(1); return(0); }
long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date, STRING **message) { char *t,*t1,tmp[MAILTMPLEN]; unsigned long u; MESSAGECACHE *elt; APPENDPACKAGE *ap = (APPENDPACKAGE *) data; *flags = *date = NIL; /* assume no flags or date */ if (ap->flags) fs_give ((void **) &ap->flags); if (ap->date) fs_give ((void **) &ap->date); mail_gc (ap->stream,GC_TEXTS); if (++ap->msgno <= ap->msgmax) { /* initialize flag string */ memset (t = tmp,0,MAILTMPLEN); /* output system flags */ if ((elt = mail_elt (ap->stream,ap->msgno))->seen) strcat (t," \\Seen"); if (elt->deleted) strcat (t," \\Deleted"); if (elt->flagged) strcat (t," \\Flagged"); if (elt->answered) strcat (t," \\Answered"); if (elt->draft) strcat (t," \\Draft"); /* any user flags? */ if (!ignorep && (u = elt->user_flags)) do if ((t1 = ap->stream->user_flags[find_rightmost_bit (&u)]) && (MAILTMPLEN - ((t += strlen (t)) - tmp)) > (long) (2 + strlen (t1))){ *t++ = ' '; /* space delimiter */ strcpy (t,t1); /* copy the user flag */ } while (u); /* until no more user flags */ *flags = ap->flags = cpystr (tmp + 1); *date = ap->date = cpystr (mail_date (tmp,elt)); *message = ap->message; /* message stringstruct */ INIT (ap->message,mstring,(void *) ap,elt->rfc822_size); } else *message = NIL; /* all done */ return LONGT; }
int main (int argc,char *argv[]) { MAILSTREAM *source = NIL; MAILSTREAM *dest = NIL; SEARCHPGM *criteria; char c,*s,*dp,*t,*t1,tmp[MAILTMPLEN],mbx[MAILTMPLEN]; unsigned long m,len,curlen,start,last; int i; int merge = NIL; int retcode = 1; int moreswitchp = T; char *cmd = NIL; char *src = NIL; char *dst = NIL; char *pgm = argc ? argv[0] : "mailutil"; #include "linkage.c" for (i = 1; i < argc; i++) { s = argv[i]; /* pick up argument */ /* parse switches */ if (moreswitchp && (*s == '-')) { if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T; else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T; else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T; else if (!strcmp (s,"-kwcopy") || !strcmp (s,"-kw")) kwcopyp = T; else if (!strcmp (s,"-ignore") || !strcmp (s,"-ig")) ignorep = T; else if ((!strcmp (s,"-merge") || !strcmp (s,"-m")) && (++i < argc)) { if (!strcmp (s = argv[i],"prompt")) merge = mPROMPT; else if (!strcmp (s,"append")) merge = mAPPEND; else if (!strncmp (s,"suffix=",7) && s[7]) { merge = mSUFFIX; suffix = cpystr (s+7); } else { printf ("unknown merge option: %s\n",s); exit (retcode); } } #ifdef SYSCONFIG else if ((!strcmp (s,"-user") || !strcmp (s,"-u")) && (++i < argc)) { struct passwd *pw = getpwnam (s = argv[i]); if (!pw) { printf ("unknown user id: %s\n",argv[i]); exit (retcode); } else if (setuid (pw->pw_uid)) { perror ("unable to change user id"); exit (retcode); } } #endif /* -- means no more switches, so mailbox name can start with "-" */ else if ((s[1] == '-') && !s[2]) moreswitchp = NIL; else { printf ("unknown switch: %s\n",s); exit (retcode); } } else if (!cmd) cmd = s; /* first non-switch is command */ else if (!src) src = s; /* second non-switch is source */ else if (!dst) dst = s; /* third non-switch is destination */ else { printf ("unknown argument: %s\n",s); exit (retcode); } } if (kwcopyp && ignorep) { puts ("-kwcopy and -ignore are mutually exclusive"); exit (retcode); } if (!cmd) cmd = ""; /* prevent SEGV */ if (!strcmp (cmd,"check")) { /* check for new messages */ if (!src) src = "INBOX"; if (dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgchk,stdsw); else if (mail_status (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL, src,SA_MESSAGES | SA_RECENT | SA_UNSEEN)) retcode = 0; } else if (!strcmp (cmd,"create")) { if (!src || dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgcre,stdsw); else if (mail_create (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL,src)) retcode = 0; } else if (!strcmp (cmd,"delete")) { if (!src || dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgdel,stdsw); else if (mail_delete (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL,src)) retcode = 0; } else if (!strcmp (cmd,"rename")) { if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep) printf (usage2,pgm,usgren,stdsw); else if (mail_rename (source = (*src == '{') ? mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)) : NIL,src,dst)) retcode = 0; } else if ((i = !strcmp (cmd,"move")) || !strcmp (cmd,"copy")) { if (!src || !dst || merge) printf (usage3,pgm,cmd,usgcpymov,stdsw); else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) | (debugp ? OP_DEBUG : NIL))) { dest = NIL; /* open destination stream if network */ if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))) { if (mbxcopy (source,dest,dst,T,i,merge)) retcode = 0; } } } else if ((i = !strcmp (cmd,"appenddelete")) || !strcmp (cmd,"append")) { if (!src || !dst || merge) printf (usage3,pgm,cmd,usgappdel,stdsw); else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) | (debugp ? OP_DEBUG : NIL))) { dest = NIL; /* open destination stream if network */ if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))) { if (mbxcopy (source,dest,dst,NIL,i,merge)) retcode = 0; } } } else if (!strcmp (cmd,"prune")) { if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep || !(criteria = prune_criteria (dst))) printf (usage2,pgm,usgprn,stdsw); else if ((source = mail_open (NIL,src,(debugp ? OP_DEBUG : NIL))) && mail_search_full (source,NIL,criteria,SE_FREE)) { for (m = 1, s = t = NIL, len = start = last = 0; m <= source->nmsgs; m++) if (mail_elt (source,m)->searched) { if (s) { /* continuing a range? */ if (m == last + 1) last = m; else { /* no, end of previous range? */ if (last != start) sprintf (t,":%lu,%lu",last,m); /* no, just this message */ else sprintf (t,",%lu",m); start = last = m; /* either way, start new range */ /* running out of space? */ if ((len - (curlen = (t += strlen (t)) - s)) < 20) { fs_resize ((void **) &s,len += MAILTMPLEN); t = s + curlen; /* relocate current pointer */ } } } else { /* first time, start new buffer */ s = (char *) fs_get (len = MAILTMPLEN); sprintf (s,"%lu",start = last = m); t = s + strlen (s); /* end of buffer */ } } /* finish last range if necessary */ if (last != start) sprintf (t,":%lu",last); if (s) { /* delete/expunge any matching messages */ mail_flag (source,s,"\\Deleted",ST_SET); m = source->nmsgs; /* get number of messages before purge */ mail_expunge (source); printf ("%lu message(s) purged\n",m - source->nmsgs); fs_give ((void **) &s); /* flush buffer */ } else puts ("No matching messages, so nothing purged"); source = mail_close (source); } } else if (!strcmp (cmd,"transfer")) { if (!src || !dst) printf (usage2,pgm,usgxfr,stdsw); else if ((*src == '{') && /* open source mailbox */ !(source = mail_open (NIL,src,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))); else if ((*dst == '{') && /* open destination server */ !(dest = mail_open (NIL,dst,OP_HALFOPEN | (debugp ? OP_DEBUG : NIL)))); else if (!(f = tmpfile ())) puts ("can't open temporary file"); else { if (verbosep) puts ("Listing mailboxes..."); if (dest) strcpy (strchr (strcpy (tmp,dest->mailbox),'}') + 1, dp = strchr (dst,'}') + 1); else { dp = dst; tmp[0] = '\0'; } mail_list (dest,tmp,""); rewind (f); /* list all mailboxes matching prefix */ if (ddelim < 0) { /* if server failed to give delimiter */ puts ("warning: unable to get destination hierarchy delimiter!"); ddelim = 0; /* default to none */ } if (source) strcpy (strchr (strcpy (tmp,source->mailbox),'}') + 1, strchr (src,'}') + 1); else strcpy (tmp,src); mail_list (source,tmp,"*"); rewind (f); /* read back mailbox names */ for (retcode = 0; !retcode && (fgets (tmp,MAILTMPLEN-1,f)); ) { if (t = strchr (tmp+1,'\n')) *t = '\0'; for (t = mbx,t1 = dest ? dest->mailbox : "",c = NIL; (c != '}') && *t1; *t++ = c= *t1++); for (t1 = dp; *t1; *t++ = *t1++); /* point to name without delim or netspec */ t1 = source ? (strchr (tmp+1,'}') + 1) : tmp + 1; /* src and mbx have different delimiters? */ if (ddelim && (ddelim != tmp[0])) while (c = *t1++) { /* swap delimiters then */ if (c == ddelim) c = tmp[0] ? tmp[0] : 'x'; else if (c == tmp[0]) c = ddelim; *t++ = c; } /* easy case */ else while (*t1) *t++ = *t1++; *t++ = '\0'; if (verbosep) { printf ("Copying %s\n => %s\n",tmp+1,mbx); fflush (stdout); } if (source = mail_open (source,tmp+1,(debugp ? OP_DEBUG : NIL) | (rwcopyp ? NIL : OP_READONLY))) { if (!mbxcopy (source,dest,mbx,T,NIL,merge)) retcode = 1; if (source->dtb->flags & DR_LOCAL) source = mail_close (source); } else printf ("can't open source mailbox %s\n",tmp+1); } } } else { printf ("%s version %s.%s\n\n",pgm,CCLIENTVERSION,version); printf (usage2,pgm,"command [switches] arguments",stdsw); printf ("\nCommands:\n %s\n",usgchk); puts (" ;; report number of messages and new messages"); printf (" %s\n",usgcre); puts (" ;; create new mailbox"); printf (" %s\n",usgdel); puts (" ;; delete existing mailbox"); printf (" %s\n",usgren); puts (" ;; rename mailbox to a new name"); printf (" copy %s\n",usgcpymov); printf (" move %s\n",usgcpymov); puts (" ;; create new mailbox and copy/move messages"); printf (" append %s\n",usgappdel); printf (" appenddelete %s\n",usgappdel); puts (" ;; copy/move messages to existing mailbox"); printf (" %s\n",usgprn); puts (" ;; prune mailbox of messages matching criteria"); printf (" %s\n",usgxfr); puts (" ;; copy source hierarchy to destination"); puts (" ;; -merge modes are prompt, append, or suffix=xxxx"); } /* close streams */ if (source) mail_close (source); if (dest) mail_close (dest); exit (retcode); return retcode; /* stupid compilers */ }
/* * Calculates all of the scores for the searchset and stores them in the * mail elts. Careful, this function uses patterns so if the caller is using * patterns then the caller will probably have to reset the pattern functions. * That is, will have to call first_pattern again with the correct type. * * Args: stream * searchset -- calculate scores for this set of messages * no_fetch -- we're in a callback from c-client, don't call c-client * * Returns 1 -- ok * 0 -- error, because of no_fetch */ int calculate_some_scores(MAILSTREAM *stream, SEARCHSET *searchset, int no_fetch) { PAT_S *pat = NULL; PAT_STATE pstate; char *savebits; long newscore, addtoscore, score; int error = 0; long rflags = ROLE_SCORE; long n, i; SEARCHSET *s; MESSAGECACHE *mc; HEADER_TOK_S *hdrtok; dprint((7, "calculate_some_scores\n")); if(nonempty_patterns(rflags, &pstate)){ /* calculate scores */ if(searchset){ /* this calls match_pattern which messes up searched bits */ savebits = (char *)fs_get((stream->nmsgs+1) * sizeof(char)); for(i = 1L; i <= stream->nmsgs; i++) savebits[i] = (mc = mail_elt(stream, i)) ? mc->searched : 0; /* * First set all the scores in the searchset to zero so that they * will no longer be undefined. */ score = 0L; for(s = searchset; s; s = s->next) for(n = s->first; n <= s->last; n++) set_msg_score(stream, n, score); for(pat = first_pattern(&pstate); !error && pat; pat = next_pattern(&pstate)){ newscore = pat->action->scoreval; hdrtok = pat->action->scorevalhdrtok; /* * This no_fetch probably isn't necessary since * we will actually have fetched this with * the envelope. Just making sure. */ if(hdrtok && no_fetch){ error++; break; } switch(match_pattern(pat->patgrp, stream, searchset, NULL, NULL, (no_fetch ? MP_IN_CCLIENT_CB : 0) | (SE_NOSERVER|SE_NOPREFETCH))){ case 1: if(!pat->action || pat->action->bogus) break; for(s = searchset; s; s = s->next) for(n = s->first; n <= s->last; n++) if(n > 0L && stream && n <= stream->nmsgs && (mc = mail_elt(stream, n)) && mc->searched){ if((score = get_msg_score(stream,n)) == SCORE_UNDEF) score = 0L; if(hdrtok) addtoscore = scorevalfrommsg(stream, n, hdrtok, no_fetch); else addtoscore = newscore; score += addtoscore; set_msg_score(stream, n, score); } break; case 0: break; case -1: error++; break; } } for(i = 1L; i <= stream->nmsgs; i++) if((mc = mail_elt(stream, i)) != NULL) mc->searched = savebits[i]; fs_give((void **)&savebits); if(error){ /* * Revert to undefined scores. */ score = SCORE_UNDEF; for(s = searchset; s; s = s->next) for(n = s->first; n <= s->last; n++) set_msg_score(stream, n, score); } } } return(error ? 0 : 1); }
/*---------------------------------------------------------------------- return our index number for the given raw message number Accepts: msgs - pointer to message manipulation struct msgno - number that's important part Returns: our index number of given raw message ----*/ int msgno_exceptions(MAILSTREAM *stream, long int rawno, char *part, int *bits, int set) { PINELT_S **peltp; PARTEX_S **partp; MESSAGECACHE *mc; if(!stream || rawno < 1L || rawno > stream->nmsgs) return FALSE; /* * Get pointer to exceptional part list, and scan down it * for the requested part... */ if((mc = mail_elt(stream, rawno)) && (*(peltp = (PINELT_S **) &mc->sparep))) for(partp = &(*peltp)->exceptions; *partp; partp = &(*partp)->next){ if(part){ if(!strcmp(part, (*partp)->partno)){ if(bits){ if(set) (*partp)->handling = *bits; else *bits = (*partp)->handling; } return(TRUE); /* bingo! */ } } else if(bits){ /* * The caller provided flags, but no part. * We are looking to see if the bits are set in any of the * parts. This doesn't count parts with non-digit partno's (like * scores) because those are used differently. * any of the flags... */ if((*partp)->partno && *(*partp)->partno && isdigit((unsigned char) *(*partp)->partno) && (*bits & (*partp)->handling) == *bits) return(TRUE); } else /* * The caller didn't specify a part, so * they must just be interested in whether * the msg had any exceptions at all... */ return(TRUE); } if(set && part){ if(!*peltp){ *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S)); memset(*peltp, 0, sizeof(PINELT_S)); partp = &(*peltp)->exceptions; } (*partp) = (PARTEX_S *) fs_get(sizeof(PARTEX_S)); (*partp)->partno = cpystr(part); (*partp)->next = NULL; (*partp)->handling = *bits; return(TRUE); } if(bits) /* init bits */ *bits = 0; return(FALSE); }
/*---------------------------------------------------------------------- Accepts: stream -- mail stream to removed message references from msgs -- pointer to message manipulation struct flags MI_REFILTERING -- do includes appropriate for refiltering MI_STATECHGONLY -- when refiltering, maybe only re-include messages which have had state changes since they were originally filtered Returns 1 if any new messages are included (indicating that we need to re-sort) 0 if no new messages are included ----*/ int msgno_include(MAILSTREAM *stream, MSGNO_S *msgs, int flags) { long i, slop, old_total, old_size; int exbits, ret = 0; size_t len; MESSAGECACHE *mc; if(!msgs) return(ret); for(i = 1L; i <= stream->nmsgs; i++){ if(!msgno_exceptions(stream, i, "0", &exbits, FALSE)) exbits = 0; if((((flags & MI_REFILTERING) && (exbits & MSG_EX_FILTERED) && !(exbits & MSG_EX_FILED) && (!(flags & MI_STATECHGONLY) || (exbits & MSG_EX_STATECHG))) || (!(flags & MI_REFILTERING) && !(exbits & MSG_EX_FILTERED))) && get_lflag(stream, NULL, i, MN_EXLD)){ old_total = msgs->max_msgno; old_size = msgs->sort_size; slop = (msgs->max_msgno + 1L) % 64; msgs->sort_size = (msgs->max_msgno + 1L) + (64 - slop); len = (size_t) msgs->sort_size * sizeof(long); if(msgs->sort){ if(old_size != msgs->sort_size) fs_resize((void **)&(msgs->sort), len); } else msgs->sort = (long *)fs_get(len); ret = 1; msgs->sort[++msgs->max_msgno] = i; msgs->isort[i] = msgs->max_msgno; set_lflag(stream, msgs, msgs->max_msgno, MN_EXLD, 0); if(flags & MI_REFILTERING){ exbits &= ~(MSG_EX_FILTERED | MSG_EX_TESTED); msgno_exceptions(stream, i, "0", &exbits, TRUE); } if(old_total <= 0L){ /* if no previous messages, */ if(!msgs->select){ /* select the new message */ msgs->sel_size = 8L; len = (size_t)msgs->sel_size * sizeof(long); msgs->select = (long *)fs_get(len); } msgs->sel_cnt = 1L; msgs->sel_cur = 0L; msgs->select[0] = 1L; } } else if((flags & MI_REFILTERING) && (exbits & (MSG_EX_FILTERED | MSG_EX_TESTED)) && !(exbits & MSG_EX_FILED) && (!(exbits & MSG_EX_MANUNDEL) || ((mc = mail_elt(stream, i)) && mc->deleted)) && (!(flags & MI_STATECHGONLY) || (exbits & MSG_EX_STATECHG))){ /* * We get here if the message was filtered by a filter that * just changes status bits (it wasn't excluded), and now also * if the message was merely tested for filtering. It has also * not been manually undeleted. If it was manually undeleted, we * don't want to reprocess the filter, undoing the user's * manual undeleting. Of course, a new pine will re check this * message anyway, so the user had better be using this * manual undeleting only to temporarily save him or herself * from an expunge before Saving or printing or something. * Also, we want to still try filtering if the message has at * all been marked deleted, even if the there was any manual * undeleting, since this directly precedes an expunge, we want * to make sure the filter does the right thing before getting * rid of the message forever. */ exbits &= ~(MSG_EX_FILTERED | MSG_EX_TESTED); msgno_exceptions(stream, i, "0", &exbits, TRUE); } } return(ret); }
/*---------------------------------------------------------------------- Build flags string based on requested flags and what's set in messagecache Args: flags -- flags to test Result: allocated, space-delimited flags string is returned ----*/ char * flag_string(MAILSTREAM *stream, long rawno, long int flags) { MESSAGECACHE *mc; char *p, *q, *returned_flags = NULL; size_t len = 0; int k; mc = (rawno > 0L && stream && rawno <= stream->nmsgs) ? mail_elt(stream, rawno) : NULL; if(!mc) return returned_flags; if((flags & F_DEL) && mc->deleted) len += strlen("\\DELETED") + 1; if((flags & F_ANS) && mc->answered) len += strlen("\\ANSWERED") + 1; if((flags & F_FWD) && user_flag_is_set(stream, rawno, FORWARDED_FLAG)) len += strlen(FORWARDED_FLAG) + 1; if((flags & F_FLAG) && mc->flagged) len += strlen("\\FLAGGED") + 1; if((flags & F_SEEN) && mc->seen) len += strlen("\\SEEN") + 1; if((flags & F_KEYWORD) && stream->user_flags){ for(k = 0; k < NUSERFLAGS; k++){ if((q=stream_to_user_flag_name(stream, k)) && user_flag_is_set(stream, rawno, q)){ len += strlen(q) + 1; } } } returned_flags = (char *) fs_get((len+1) * sizeof(char)); p = returned_flags; *p = '\0'; if((flags & F_DEL) && mc->deleted) sstrncpy(&p, "\\DELETED ", len+1-(p-returned_flags)); if((flags & F_ANS) && mc->answered) sstrncpy(&p, "\\ANSWERED ", len+1-(p-returned_flags)); if((flags & F_FWD) && user_flag_is_set(stream, rawno, FORWARDED_FLAG)){ sstrncpy(&p, FORWARDED_FLAG, len+1-(p-returned_flags)); sstrncpy(&p, " ", len+1-(p-returned_flags)); } if((flags & F_FLAG) && mc->flagged) sstrncpy(&p, "\\FLAGGED ", len+1-(p-returned_flags)); if((flags & F_SEEN) && mc->seen) sstrncpy(&p, "\\SEEN ", len+1-(p-returned_flags)); if((flags & F_KEYWORD) && stream->user_flags){ for(k = 0; k < NUSERFLAGS; k++){ if((q=stream_to_user_flag_name(stream, k)) && user_flag_is_set(stream, rawno, q)){ sstrncpy(&p, q, len+1-(p-returned_flags)); sstrncpy(&p, " ", len+1-(p-returned_flags)); len += strlen(p) + 1; } } } if(p != returned_flags && (len+1-(p-returned_flags)>0)) *--p = '\0'; return returned_flags; }
Variant f_imap_fetch_overview(const Resource& imap_stream, const String& sequence, int64_t options /* = 0 */) { if (options && options != FT_UID) { Logger::Warning("invalid value for the options parameter"); return false; } ImapStream *obj = imap_stream.getTyped<ImapStream>(); Array ret(Array::Create()); long status = (options & FT_UID) ? mail_uid_sequence(obj->m_stream, (unsigned char *)sequence.data()) : mail_sequence(obj->m_stream, (unsigned char *)sequence.data()); if (status) { MESSAGECACHE *elt; ENVELOPE *env; for (unsigned long i = 1; i <= obj->m_stream->nmsgs; i++) { if (((elt = mail_elt(obj->m_stream, i))->sequence) && (env = mail_fetch_structure(obj->m_stream, i, NIL, NIL))) { Object myoverview(SystemLib::AllocStdClassObject()); OBJ_SET_ENTRY(myoverview, env, "subject", subject); if (env->from) { env->from->next = NULL; char *address = _php_rfc822_write_address(env->from); if (address) { myoverview.o_set("from", String(address, AttachString)); } } if (env->to) { env->to->next = NULL; char *address = _php_rfc822_write_address(env->to); if (address) { myoverview.o_set("to", String(address, AttachString)); } } OBJ_SET_ENTRY(myoverview, env, "date", date); OBJ_SET_ENTRY(myoverview, env, "message_id", message_id); OBJ_SET_ENTRY(myoverview, env, "references", references); OBJ_SET_ENTRY(myoverview, env, "in_reply_to", in_reply_to); myoverview.o_set("size", (int64_t)elt->rfc822_size); myoverview.o_set("uid", (int64_t)mail_uid(obj->m_stream, i)); myoverview.o_set("msgno", (int64_t)i); myoverview.o_set("recent", (int64_t)elt->recent); myoverview.o_set("flagged", (int64_t)elt->flagged); myoverview.o_set("answered", (int64_t)elt->answered); myoverview.o_set("deleted", (int64_t)elt->deleted); myoverview.o_set("seen", (int64_t)elt->seen); myoverview.o_set("draft", (int64_t)elt->draft); ret.append(myoverview); } } } return ret; }
Variant f_imap_headerinfo(const Resource& imap_stream, int64_t msg_number, int64_t fromlength /* = 0 */, int64_t subjectlength /* = 0 */, const String& defaulthost /* = "" */) { ImapStream *obj = imap_stream.getTyped<ImapStream>(); if (fromlength < 0 || fromlength > MAILTMPLEN) { Logger::Warning("From length has to be between 0 and %d", MAILTMPLEN); return false; } if (subjectlength < 0 || subjectlength > MAILTMPLEN) { Logger::Warning("Subject length has to be between 0 and %d", MAILTMPLEN); return false; } if (!obj->checkMsgNumber(msg_number)) { return false; } if (!mail_fetchstructure(obj->m_stream, msg_number, NIL)) { return false; } MESSAGECACHE *cache = mail_elt(obj->m_stream, msg_number); ENVELOPE *en = mail_fetchenvelope(obj->m_stream, msg_number); /* call a function to parse all the text, so that we can use the same function to parse text from other sources */ Object ret = _php_make_header_object(en); /* now run through properties that are only going to be returned from a server, not text headers */ ret.o_set("Recent", cache->recent ? (cache->seen ? "R": "N") : " "); ret.o_set("Unseen", (cache->recent | cache->seen) ? " " : "U"); ret.o_set("Flagged", cache->flagged ? "F" : " "); ret.o_set("Answered", cache->answered ? "A" : " "); ret.o_set("Deleted", cache->deleted ? "D" : " "); ret.o_set("Draft", cache->draft ? "X" : " "); char dummy[2000], fulladdress[MAILTMPLEN + 1]; snprintf(dummy, sizeof(dummy), "%4ld", cache->msgno); ret.o_set("Msgno", String(dummy, CopyString)); mail_date(dummy, cache); ret.o_set("MailDate", String(dummy, CopyString)); snprintf(dummy, sizeof(dummy), "%ld", cache->rfc822_size); ret.o_set("Size", String(dummy, CopyString)); ret.o_set("udate", (int64_t)mail_longdate(cache)); if (en->from && fromlength) { fulladdress[0] = 0x00; mail_fetchfrom(fulladdress, obj->m_stream, msg_number, fromlength); ret.o_set("fetchfrom", String(fulladdress, CopyString)); } if (en->subject && subjectlength) { fulladdress[0] = 0x00; mail_fetchsubject(fulladdress, obj->m_stream, msg_number, subjectlength); ret.o_set("fetchsubject", String(fulladdress, CopyString)); } return ret; }