Example #1
0
static int do_sync_mailboxes(struct sync_name_list *mboxname_list,
                             struct sync_action_list *user_list,
                             const char **channelp,
                             unsigned flags)
{
    struct sync_name *mbox;
    int r = 0;

    if (mboxname_list->count) {
        r = sync_do_mailboxes(mboxname_list, NULL, sync_backend, flags);
        if (channelp && r == IMAP_MAILBOX_LOCKED) {
            for (mbox = mboxname_list->head; mbox; mbox = mbox->next) {
                if (mbox->mark) continue;
                sync_log_channel_mailbox(*channelp, mbox->name);
                report_verbose("  Deferred: MAILBOX %s\n", mbox->name);
            }
            r = 0;
        }
        else if (r) {
            /* promote failed personal mailboxes to USER */
            int nonuser = 0;

            for (mbox = mboxname_list->head; mbox; mbox = mbox->next) {
                /* done OK?  Good :) */
                if (mbox->mark)
                    continue;

                char *userid = mboxname_to_userid(mbox->name);
                if (userid) {
                    mbox->mark = 1;

                    sync_action_list_add(user_list, NULL, userid);
                    report_verbose("  Promoting: MAILBOX %s -> USER %s\n",
                                   mbox->name, userid);
                    free(userid);
                }
                else
                    nonuser = 1; /* there was a non-user mailbox */
            }
            if (!nonuser) r = 0;
        }
    }

    return r;
}
Example #2
0
static int do_sync_mailboxes(struct sync_name_list *mboxname_list,
                             struct sync_action_list *user_list,
                             unsigned flags)
{
    int r = 0;

    if (mboxname_list->count) {
        r = sync_do_mailboxes(mboxname_list, sync_backend, flags);
        if (r) {
            /* promote failed personal mailboxes to USER */
            int nonuser = 0;
            struct sync_name *mbox;

            for (mbox = mboxname_list->head; mbox; mbox = mbox->next) {
                /* done OK?  Good :) */
                if (mbox->mark)
                    continue;

                char *userid = mboxname_to_userid(mbox->name);
                if (userid) {
                    mbox->mark = 1;

                    sync_action_list_add(user_list, NULL, userid);
                    if (verbose) {
                        printf("  Promoting: MAILBOX %s -> USER %s\n",
                               mbox->name, userid);
                    }
                    if (verbose_logging) {
                        syslog(LOG_INFO, "  Promoting: MAILBOX %s -> USER %s",
                               mbox->name, userid);
                    }
                    free(userid);
                }
                else
                    nonuser = 1; /* there was a non-user mailbox */
            }
            if (!nonuser) r = 0;
        }
    }

    return r;
}
Example #3
0
static int do_sync(sync_log_reader_t *slr)
{
    struct sync_action_list *user_list = sync_action_list_create();
    struct sync_action_list *unuser_list = sync_action_list_create();
    struct sync_action_list *meta_list = sync_action_list_create();
    struct sync_action_list *mailbox_list = sync_action_list_create();
    struct sync_action_list *unmailbox_list = sync_action_list_create();
    struct sync_action_list *quota_list = sync_action_list_create();
    struct sync_action_list *annot_list = sync_action_list_create();
    struct sync_action_list *seen_list = sync_action_list_create();
    struct sync_action_list *sub_list = sync_action_list_create();
    struct sync_name_list *mboxname_list = sync_name_list_create();
    const char *args[3];
    struct sync_action *action;
    int r = 0;

    while (1) {
        r = sync_log_reader_getitem(slr, args);
        if (r == EOF) break;

        if (!strcmp(args[0], "USER"))
            sync_action_list_add(user_list, NULL, args[1]);
        else if (!strcmp(args[0], "UNUSER"))
            sync_action_list_add(unuser_list, NULL, args[1]);
        else if (!strcmp(args[0], "META"))
            sync_action_list_add(meta_list, NULL, args[1]);
        else if (!strcmp(args[0], "SIEVE"))
            sync_action_list_add(meta_list, NULL, args[1]);
        else if (!strcmp(args[0], "APPEND")) /* just a mailbox event */
            sync_action_list_add(mailbox_list, args[1], NULL);
        else if (!strcmp(args[0], "MAILBOX"))
            sync_action_list_add(mailbox_list, args[1], NULL);
        else if (!strcmp(args[0], "UNMAILBOX"))
            sync_action_list_add(unmailbox_list, args[1], NULL);
        else if (!strcmp(args[0], "QUOTA"))
            sync_action_list_add(quota_list, args[1], NULL);
        else if (!strcmp(args[0], "ANNOTATION"))
            sync_action_list_add(annot_list, args[1], NULL);
        else if (!strcmp(args[0], "SEEN"))
            sync_action_list_add(seen_list, args[2], args[1]);
        else if (!strcmp(args[0], "SUB"))
            sync_action_list_add(sub_list, args[2], args[1]);
        else if (!strcmp(args[0], "UNSUB"))
            sync_action_list_add(sub_list, args[2], args[1]);
        else
            syslog(LOG_ERR, "Unknown action type: %s", args[0]);
    }

    /* Optimise out redundant clauses */

    for (action = user_list->head; action; action = action->next) {
        /* remove per-user items */
        remove_meta(action->user, meta_list);
        remove_meta(action->user, seen_list);
        remove_meta(action->user, sub_list);
    }

    /* duplicate removal for unuser - we also strip all the user events */
    for (action = unuser_list->head; action; action = action->next) {
        /* remove per-user items */
        remove_meta(action->user, meta_list);
        remove_meta(action->user, seen_list);
        remove_meta(action->user, sub_list);

        /* unuser trumps user */
        remove_meta(action->user, user_list);
    }

    for (action = meta_list->head; action; action = action->next) {
        /* META action overrides any user SEEN or SUB/UNSUB action
           for same user */
        remove_meta(action->user, seen_list);
        remove_meta(action->user, sub_list);
    }

    /* And then run tasks. */
    for (action = quota_list->head; action; action = action->next) {
        if (!action->active)
            continue;

        if (sync_do_quota(action->name, sync_backend, flags)) {
            /* XXX - bogus handling, should be user */
            sync_action_list_add(mailbox_list, action->name, NULL);
            if (verbose) {
                printf("  Promoting: QUOTA %s -> MAILBOX %s\n",
                       action->name, action->name);
            }
            if (verbose_logging) {
                syslog(LOG_INFO, "  Promoting: QUOTA %s -> MAILBOX %s",
                       action->name, action->name);
            }
        }
    }

    for (action = annot_list->head; action; action = action->next) {
        if (!action->active)
            continue;

        /* NOTE: ANNOTATION "" is a special case - it's a server
         * annotation, hence the check for a character at the
         * start of the name */
        if (sync_do_annotation(action->name, sync_backend,
                               flags) && *action->name) {
            /* XXX - bogus handling, should be ... er, something */
            sync_action_list_add(mailbox_list, action->name, NULL);
            if (verbose) {
                printf("  Promoting: ANNOTATION %s -> MAILBOX %s\n",
                       action->name, action->name);
            }
            if (verbose_logging) {
                syslog(LOG_INFO, "  Promoting: ANNOTATION %s -> MAILBOX %s",
                       action->name, action->name);
            }
        }
    }

    for (action = seen_list->head; action; action = action->next) {
        if (!action->active)
            continue;

        if (sync_do_seen(action->user, action->name, sync_backend, flags)) {
            char *userid = mboxname_to_userid(action->name);
            if (userid && mboxname_isusermailbox(action->name, 1) && !strcmp(userid, action->user)) {
                sync_action_list_add(user_list, NULL, action->user);
                if (verbose) {
                    printf("  Promoting: SEEN %s %s -> USER %s\n",
                           action->user, action->name, action->user);
                }
                if (verbose_logging) {
                    syslog(LOG_INFO, "  Promoting: SEEN %s %s -> USER %s",
                           action->user, action->name, action->user);
                }
            } else {
                sync_action_list_add(meta_list, NULL, action->user);
                if (verbose) {
                    printf("  Promoting: SEEN %s %s -> META %s\n",
                           action->user, action->name, action->user);
                }
                if (verbose_logging) {
                    syslog(LOG_INFO, "  Promoting: SEEN %s %s -> META %s",
                           action->user, action->name, action->user);
                }
            }
            free(userid);
        }
    }

    for (action = sub_list->head; action; action = action->next) {
        if (!action->active)
            continue;

        if (user_sub(action->user, action->name)) {
            sync_action_list_add(meta_list, NULL, action->user);
            if (verbose) {
                printf("  Promoting: SUB %s %s -> META %s\n",
                       action->user, action->name, action->user);
            }
            if (verbose_logging) {
                syslog(LOG_INFO, "  Promoting: SUB %s %s -> META %s",
                       action->user, action->name, action->name);
            }
        }
    }

    for (action = mailbox_list->head; action; action = action->next) {
        if (!action->active)
            continue;

        sync_name_list_add(mboxname_list, action->name);
        /* only do up to 1000 mailboxes at a time */
        if (mboxname_list->count > 1000) {
            syslog(LOG_NOTICE, "sync_mailboxes: doing 1000");
            r = do_sync_mailboxes(mboxname_list, user_list, flags);
            if (r) goto cleanup;
            r = do_restart();
            if (r) goto cleanup;
            sync_name_list_free(&mboxname_list);
            mboxname_list = sync_name_list_create();
        }
    }

    r = do_sync_mailboxes(mboxname_list, user_list, flags);
    if (r) goto cleanup;
    r = do_restart();
    if (r) goto cleanup;

    for (action = unmailbox_list->head; action; action = action->next) {
        if (!action->active)
            continue;
        r = do_unmailbox(action->name, sync_backend, flags);
        if (r) goto cleanup;
    }

    for (action = meta_list->head; action; action = action->next) {
        if (!action->active)
            continue;

        r = sync_do_meta(action->user, sync_backend, flags);
        if (r) {
            if (r == IMAP_INVALID_USER) goto cleanup;

            sync_action_list_add(user_list, NULL, action->user);
            if (verbose) {
                printf("  Promoting: META %s -> USER %s\n",
                       action->user, action->user);
            }
            if (verbose_logging) {
                syslog(LOG_INFO, "  Promoting: META %s -> USER %s",
                       action->user, action->user);
            }
        }
    }

    for (action = user_list->head; action; action = action->next) {
        if (!action->active)
            continue;
        r = sync_do_user(action->user, sync_backend, flags);
        if (r) goto cleanup;
        r = do_restart();
        if (r) goto cleanup;
    }

    for (action = unuser_list->head; action; action = action->next) {
        if (!action->active)
            continue;
        r = do_unuser(action->user);
        if (r) goto cleanup;
    }

  cleanup:
    if (r) {
        if (verbose)
            fprintf(stderr, "Error in do_sync(): bailing out! %s\n", error_message(r));

        syslog(LOG_ERR, "Error in do_sync(): bailing out! %s", error_message(r));
    }

    sync_action_list_free(&user_list);
    sync_action_list_free(&unuser_list);
    sync_action_list_free(&meta_list);
    sync_action_list_free(&mailbox_list);
    sync_action_list_free(&unmailbox_list);
    sync_action_list_free(&quota_list);
    sync_action_list_free(&annot_list);
    sync_action_list_free(&seen_list);
    sync_action_list_free(&sub_list);
    sync_name_list_free(&mboxname_list);

    return r;
}