struct backend *proxy_findinboxserver(const char *userid) { mbentry_t *mbentry = NULL; struct backend *s = NULL; char *inbox = mboxname_user_mbox(userid, NULL); int r = mboxlist_lookup(inbox, &mbentry, NULL); free(inbox); if (r) return NULL; if (mbentry->mbtype & MBTYPE_REMOTE) { s = proxy_findserver(mbentry->server, &imap_protocol, proxy_userid, &backend_cached, &backend_current, &backend_inbox, imapd_in); } mboxlist_entry_free(&mbentry); return s; }
struct backend *proxy_findinboxserver(const char *userid) { char inbox[MAX_MAILBOX_BUFFER]; struct mboxlist_entry *mbentry = NULL; struct backend *s = NULL; int r; r = (*imapd_namespace.mboxname_tointernal)(&imapd_namespace, "INBOX", userid, inbox); if (r) return NULL; r = mboxlist_lookup(inbox, &mbentry, NULL); if (r) return NULL; if (mbentry->mbtype & MBTYPE_REMOTE) { s = proxy_findserver(mbentry->server, &imap_protocol, proxy_userid, &backend_cached, &backend_current, &backend_inbox, imapd_in); } mboxlist_entry_free(&mbentry); return s; }
/* This is called once for each mailbox we're told to index. */ static int index_one(const char *name, int blocking) { mbentry_t *mbentry = NULL; struct mailbox *mailbox = NULL; int r; int flags = 0; if (incremental_mode) flags |= SEARCH_UPDATE_INCREMENTAL; /* Convert internal name to external */ char *extname = mboxname_to_external(name, &squat_namespace, NULL); /* Skip remote mailboxes */ r = mboxlist_lookup(name, &mbentry, NULL); if (r) { if (verbose) { printf("error looking up %s: %s\n", extname, error_message(r)); } syslog(LOG_INFO, "error looking up %s: %s\n", extname, error_message(r)); free(extname); return r; } if (mbentry->mbtype & MBTYPE_REMOTE) { mboxlist_entry_free(&mbentry); free(extname); return 0; } mboxlist_entry_free(&mbentry); /* make sure the mailbox (or an ancestor) has /vendor/cmu/cyrus-imapd/squat set to "true" */ if (annotation_flag) { char buf[MAX_MAILBOX_BUFFER] = "", *p; struct buf attrib = BUF_INITIALIZER; int domainlen = 0; if (config_virtdomains && (p = strchr(name, '!'))) domainlen = p - name + 1; strlcpy(buf, name, sizeof(buf)); /* since mailboxes inherit /vendor/cmu/cyrus-imapd/squat, we need to iterate all the way up to "" (server entry) */ while (1) { r = annotatemore_lookup(buf, IMAP_ANNOT_NS "squat", "", &attrib); if (r || /* error */ attrib.s || /* found an entry */ !buf[0]) { /* done recursing */ break; } p = strrchr(buf, '.'); /* find parent mailbox */ if (p && (p - buf > domainlen)) /* don't split subdomain */ *p = '\0'; else if (!buf[domainlen]) /* server entry */ buf[0] = '\0'; else /* domain entry */ buf[domainlen] = '\0'; } if (r || !attrib.s || strcasecmp(attrib.s, "true")) { buf_free(&attrib); free(extname); return 0; } buf_free(&attrib); } again: if (blocking) r = mailbox_open_irl(name, &mailbox); else r = mailbox_open_irlnb(name, &mailbox); if (r == IMAP_MAILBOX_LOCKED) { if (verbose) syslog(LOG_INFO, "mailbox %s locked, retrying", extname); free(extname); return r; } if (r) { if (verbose) { printf("error opening %s: %s\n", extname, error_message(r)); } syslog(LOG_INFO, "error opening %s: %s\n", extname, error_message(r)); free(extname); return r; } syslog(LOG_INFO, "indexing mailbox %s... ", extname); if (verbose > 0) { printf("Indexing mailbox %s... ", extname); } r = search_update_mailbox(rx, mailbox, flags); mailbox_close(&mailbox); /* in non-blocking (rolling) mode, only do one batch per mailbox at * a time for fairness [IRIS-2471]. The squatter will re-insert the * mailbox in the queue */ if (blocking && r == IMAP_AGAIN) goto again; free(extname); return r; }
/* This handles piping of the LSUB command, because we have to figure out * what mailboxes actually exist before passing them to the end user. * * It is also needed if we are doing a FIND MAILBOXES, for that we do an * LSUB on the backend anyway, because the semantics of FIND do not allow * it to return nonexistant mailboxes (RFC1176), but we need to really dumb * down the response when this is the case. */ int pipe_lsub(struct backend *s, const char *userid, const char *tag, int force_notfatal, const char *resp) { int taglen = strlen(tag); int c; int r = PROXY_OK; int exist_r; static struct buf tagb, cmd, sep, name; struct buf flags = BUF_INITIALIZER; const char *end_strip_flags[] = { " \\NonExistent)", "\\NonExistent)", " \\Noselect)", "\\Noselect)", NULL }; const char *mid_strip_flags[] = { "\\NonExistent ", "\\Noselect ", NULL }; assert(s); assert(s->timeout); s->timeout->mark = time(NULL) + IDLE_TIMEOUT; while(1) { c = getword(s->in, &tagb); if(c == EOF) { if(s == backend_current && !force_notfatal) fatal("Lost connection to selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; goto out; } if(!strncmp(tag, tagb.s, taglen)) { char buf[2048]; if(!prot_fgets(buf, sizeof(buf), s->in)) { if(s == backend_current && !force_notfatal) fatal("Lost connection to selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; goto out; } /* Got the end of the response */ buf_appendcstr(&s->last_result, buf); buf_cstring(&s->last_result); switch (buf[0]) { case 'O': case 'o': r = PROXY_OK; break; case 'N': case 'n': r = PROXY_NO; break; case 'B': case 'b': r = PROXY_BAD; break; default: /* huh? no result? */ if(s == backend_current && !force_notfatal) fatal("Lost connection to selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; break; } break; /* we're done */ } c = getword(s->in, &cmd); if(c == EOF) { if(s == backend_current && !force_notfatal) fatal("Lost connection to selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; goto out; } if(strncasecmp("LSUB", cmd.s, 4) && strncasecmp("LIST", cmd.s, 4)) { prot_printf(imapd_out, "%s %s ", tagb.s, cmd.s); r = pipe_to_end_of_response(s, force_notfatal); if (r != PROXY_OK) goto out; } else { /* build up the response bit by bit */ int i; buf_reset(&flags); c = prot_getc(s->in); while(c != ')' && c != EOF) { buf_putc(&flags, c); c = prot_getc(s->in); } if(c != EOF) { /* terminate string */ buf_putc(&flags, ')'); buf_cstring(&flags); /* get the next character */ c = prot_getc(s->in); } if(c != ' ') { if(s == backend_current && !force_notfatal) fatal("Bad LSUB response from selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; goto out; } /* Check for flags that we should remove * (e.g. Noselect, NonExistent) */ for(i=0; end_strip_flags[i]; i++) buf_replace_all(&flags, end_strip_flags[i], ")"); for (i=0; mid_strip_flags[i]; i++) buf_replace_all(&flags, mid_strip_flags[i], NULL); /* Get separator */ c = getastring(s->in, s->out, &sep); if(c != ' ') { if(s == backend_current && !force_notfatal) fatal("Bad LSUB response from selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; goto out; } /* Get name */ c = getastring(s->in, s->out, &name); if(c == '\r') c = prot_getc(s->in); if(c != '\n') { if(s == backend_current && !force_notfatal) fatal("Bad LSUB response from selected backend", EC_UNAVAILABLE); proxy_downserver(s); r = PROXY_NOCONNECTION; goto out; } /* lookup name */ exist_r = 1; char *intname = mboxname_from_external(name.s, &imapd_namespace, userid); mbentry_t *mbentry = NULL; exist_r = mboxlist_lookup(intname, &mbentry, NULL); free(intname); if(!exist_r && (mbentry->mbtype & MBTYPE_RESERVE)) exist_r = IMAP_MAILBOX_RESERVED; mboxlist_entry_free(&mbentry); /* send our response */ /* we need to set \Noselect if it's not in our mailboxes.db */ if (resp[0] == 'L') { if(!exist_r) { prot_printf(imapd_out, "* %s %s \"%s\" ", resp, flags.s, sep.s); } else { prot_printf(imapd_out, "* %s (\\Noselect) \"%s\" ", resp, sep.s); } prot_printstring(imapd_out, name.s); prot_printf(imapd_out, "\r\n"); } else if(resp[0] == 'M' && !exist_r) { /* Note that it has to exist for a find response */ prot_printf(imapd_out, "* %s ", resp); prot_printastring(imapd_out, name.s); prot_printf(imapd_out, "\r\n"); } } } /* while(1) */ out: buf_free(&flags); return r; }
int main(int argc, char **argv) { struct mboxlist_entry *mbentry = NULL; int rc, i, quiet = 0, stop_on_error=0, metadata=0; int opt; /* getopt() returns an int */ char *alt_config = NULL; char buf[MAX_MAILBOX_PATH+1]; if ((geteuid()) == 0 && (become_cyrus() != 0)) { fatal("must run as the Cyrus user", EC_USAGE); } while ((opt = getopt(argc, argv, "C:qsm")) != EOF) { switch(opt) { case 'C': /* alt config file */ alt_config = optarg; break; case 'q': quiet = 1; break; case 's': stop_on_error = 1; break; case 'm': metadata = 1; break; default: usage(); } } cyrus_init(alt_config, "mbpath", 0); if ((rc = mboxname_init_namespace(&mbpath_namespace, 1)) != 0) { fatal(error_message(rc), -1); } mboxlist_init(0); mboxlist_open(NULL); for (i = optind; i < argc; i++) { /* Translate mailboxname */ (*mbpath_namespace.mboxname_tointernal)(&mbpath_namespace, argv[i], NULL, buf); if ((rc = mboxlist_lookup(buf, &mbentry, NULL)) == 0) { if (mbentry->mbtype & MBTYPE_REMOTE) { printf("%s!%s\n", mbentry->server, mbentry->partition); } else if (metadata) { const char *path = mboxname_metapath(mbentry->partition, mbentry->name, 0, 0); printf("%s\n", path); } else { const char *path = mboxname_datapath(mbentry->partition, mbentry->name, 0); printf("%s\n", path); } mboxlist_entry_free(&mbentry); } else { if (!quiet && (rc == IMAP_MAILBOX_NONEXISTENT)) { fprintf(stderr, "Invalid mailbox name: %s\n", argv[i]); } if (stop_on_error) { if (quiet) { fatal("", -1); } else { fatal("Error in processing mailbox. Stopping\n", -1); } } } } mboxlist_close(); mboxlist_done(); cyrus_done(); return 0; }