static int dav_move_collection(struct transaction_t *txn,
                               struct request_target_t *dest_tgt,
                               int overwrite)
{
    int r = 0, recursive = 1, rights;
    int omlen, nmlen;
    char *oldmailboxname = txn->req_tgt.mbentry->name;
    char *newmailboxname = dest_tgt->mbentry->name;
    struct mboxevent *mboxevent = NULL;

    /* Make sure we're moving within the same user */
    if (!mboxname_same_userid(newmailboxname, oldmailboxname)) {
        txn->error.desc = "Can only move within same user";
        return HTTP_FORBIDDEN;
    }

    /* Check ACL for current user on source mailbox */
    rights = httpd_myrights(httpd_authstate, txn->req_tgt.mbentry);
    if ((rights & DACL_UNBIND) != DACL_UNBIND) {
        /* DAV:need-privileges */
        txn->error.precond = DAV_NEED_PRIVS;
        txn->error.resource = txn->req_tgt.path;
        txn->error.rights = DACL_UNBIND;
        return HTTP_NO_PRIVS;
    }

    if (txn->req_tgt.mbentry->server) {
        /* Remote source mailbox */
        struct backend *be;

        be = proxy_findserver(txn->req_tgt.mbentry->server,
                              &http_protocol, httpd_userid,
                              &backend_cached, NULL, NULL, httpd_in);
        if (!be) return HTTP_UNAVAILABLE;

        return http_pipe_req_resp(be, txn);
    }

    /* Local source mailbox */

    /* If we're renaming something inside of something else,
       don't recursively rename */
    omlen = strlen(oldmailboxname);
    nmlen = strlen(newmailboxname);
    if (omlen < nmlen) {
        if (!strncmp(oldmailboxname, newmailboxname, omlen) &&
            newmailboxname[omlen] == '.') {
            recursive = 0;
        }
    } else {
        if (!strncmp(oldmailboxname, newmailboxname, nmlen) &&
            oldmailboxname[nmlen] == '.') {
            recursive = 0;
        }
    }

    r = mboxlist_createmailboxcheck(newmailboxname, 0, NULL, httpd_userisadmin,
                                    httpd_userid, httpd_authstate,
                                    NULL, NULL, 0 /* force */);

    if (r == IMAP_MAILBOX_EXISTS && overwrite) {
        /* Attempt to delete existing base mailbox */
        overwrite = -1;

        mboxevent = mboxevent_new(EVENT_MAILBOX_DELETE);

        if (mboxlist_delayed_delete_isenabled()) {
            r = mboxlist_delayed_deletemailbox(newmailboxname,
                                               httpd_userisadmin,
                                               httpd_userid, httpd_authstate,
                                               mboxevent, 1 /* checkacl */,
                                               0 /* localonly*/, 0 /* force */,
                                               0 /* keep_intermediaries */);

        }
        else {
            r = mboxlist_deletemailbox(newmailboxname,
                                       httpd_userisadmin,
                                       httpd_userid, httpd_authstate,
                                       mboxevent, 1 /* checkacl */,
                                       0 /* localonly*/, 0 /* force */,
                                       0 /* keep_intermediaries */);
        }

        if (!r) mboxevent_notify(&mboxevent);
        mboxevent_free(&mboxevent);

        /* Attempt to delete all existing submailboxes */
        if (!r && recursive) {
            char nmbn[MAX_MAILBOX_BUFFER];

            strcpy(nmbn, newmailboxname);
            strcat(nmbn, ".");

            r = mboxlist_allmbox(nmbn, remove_collection, NULL, 0);
        }
    }
    if (r) goto done;

    /* Attempt to rename the base mailbox */
    mboxevent = mboxevent_new(EVENT_MAILBOX_RENAME);

    r = mboxlist_renamemailbox(txn->req_tgt.mbentry, newmailboxname,
                               NULL /* partition */, 0 /* uidvalidity */,
                               httpd_userisadmin, httpd_userid, httpd_authstate,
                               mboxevent, 0, 0, 1 /* ignorequota */, 0, 0, 0);

    if (!r) mboxevent_notify(&mboxevent);
    mboxevent_free(&mboxevent);

    /* Attempt to rename all submailboxes */
    if (!r && recursive) {
        char ombn[MAX_MAILBOX_BUFFER];
        struct move_rock mrock = { ++omlen, ++nmlen, BUF_INITIALIZER,
                                   dest_tgt->namespace->prefix, NULL, {0} };

        strcpy(ombn, oldmailboxname);
        strcat(ombn, ".");

        /* Setup the rock */
        buf_setcstr(&mrock.newname, newmailboxname);
        buf_putc(&mrock.newname, '.');

        r = mboxlist_allmbox(ombn, move_collection, &mrock, 0);
        buf_free(&mrock.newname);

        if (mrock.root) {
            xml_response(HTTP_MULTI_STATUS, txn, mrock.root->doc);
            xmlFreeDoc(mrock.root->doc);
            return 0;
        }
    }

  done:
    switch (r) {
    case 0:
        return (overwrite < 0) ? HTTP_NO_CONTENT : HTTP_CREATED;

    case IMAP_MAILBOX_EXISTS:
        return HTTP_PRECOND_FAILED;

    case IMAP_PERMISSION_DENIED:
        /* DAV:need-privileges */
        txn->error.precond = DAV_NEED_PRIVS;
        txn->error.resource = dest_tgt->path;
        txn->error.rights = (overwrite < 0) ? DACL_UNBIND : DACL_BIND;
        return HTTP_NO_PRIVS;

    default:
        txn->error.desc = error_message(r);
        return HTTP_SERVER_ERROR;
    }
}
static int dav_move_collection(struct transaction_t *txn,
                               struct request_target_t *dest_tgt,
                               int overwrite)
{
    int r = 0, recursive = 1, rights;
    int omlen, nmlen;
    char *oldmailboxname = txn->req_tgt.mbentry->name;
    char *newmailboxname = dest_tgt->mbentry->name;
    struct mboxevent *mboxevent = NULL;

     
    if (!mboxname_same_userid(newmailboxname, oldmailboxname)) {
        txn->error.desc = "Can only move within same user";
        return HTTP_FORBIDDEN;
    }

     
    rights = httpd_myrights(httpd_authstate, txn->req_tgt.mbentry);
    if ((rights & DACL_UNBIND) != DACL_UNBIND) {
         
        txn->error.precond = DAV_NEED_PRIVS;
        txn->error.resource = txn->req_tgt.path;
        txn->error.rights = DACL_UNBIND;
        return HTTP_NO_PRIVS;
    }

    if (txn->req_tgt.mbentry->server) {
         
        struct backend *be;

        be = proxy_findserver(txn->req_tgt.mbentry->server,
                              &http_protocol, httpd_userid,
                              &backend_cached, NULL, NULL, httpd_in);
        if (!be) return HTTP_UNAVAILABLE;

        return http_pipe_req_resp(be, txn);
    }

     

     
    omlen = strlen(oldmailboxname);
    nmlen = strlen(newmailboxname);
    if (omlen < nmlen) {
        if (!strncmp(oldmailboxname, newmailboxname, omlen) &&
            newmailboxname[omlen] == '.') {
            recursive = 0;
        }
    } else {
        if (!strncmp(oldmailboxname, newmailboxname, nmlen) &&
            oldmailboxname[nmlen] == '.') {
            recursive = 0;
        }
    }

    r = mboxlist_createmailboxcheck(newmailboxname, 0, NULL, httpd_userisadmin,
                                    httpd_userid, httpd_authstate,
                                    NULL, NULL, 0  );

    if (r == IMAP_MAILBOX_EXISTS && overwrite) {
         
        overwrite = -1;

        mboxevent = mboxevent_new(EVENT_MAILBOX_DELETE);

        if (mboxlist_delayed_delete_isenabled()) {
            r = mboxlist_delayed_deletemailbox(newmailboxname,
                                               httpd_userisadmin,
                                               httpd_userid, httpd_authstate,
                                               mboxevent, 1  ,
                                               0  , 0  ,
                                               0  );

        }
        else {
            r = mboxlist_deletemailbox(newmailboxname,
                                       httpd_userisadmin,
                                       httpd_userid, httpd_authstate,
                                       mboxevent, 1  ,
                                       0  , 0  ,
                                       0  );
        }

        if (!r) mboxevent_notify(&mboxevent);
        mboxevent_free(&mboxevent);

         
        if (!r && recursive) {
            char nmbn[MAX_MAILBOX_BUFFER];

            strcpy(nmbn, newmailboxname);
            strcat(nmbn, ".");

            r = mboxlist_allmbox(nmbn, remove_collection, NULL, 0);
        }
    }
    if (r) goto done;

     
    mboxevent = mboxevent_new(EVENT_MAILBOX_RENAME);

    r = mboxlist_renamemailbox(txn->req_tgt.mbentry, newmailboxname,
                               NULL  , 0  ,
                               httpd_userisadmin, httpd_userid, httpd_authstate,
                               mboxevent, 0, 0, 1  , 0, 0, 0);

    if (!r) mboxevent_notify(&mboxevent);
    mboxevent_free(&mboxevent);

     
    if (!r && recursive) {
        char ombn[MAX_MAILBOX_BUFFER];
        struct move_rock mrock = { ++omlen, ++nmlen, BUF_INITIALIZER,
                                   dest_tgt->namespace->prefix, NULL, {0} };

        strcpy(ombn, oldmailboxname);
        strcat(ombn, ".");

         
        buf_setcstr(&mrock.newname, newmailboxname);
        buf_putc(&mrock.newname, '.');

        r = mboxlist_allmbox(ombn, move_collection, &mrock, 0);
        buf_free(&mrock.newname);

        if (mrock.root) {
            xml_response(HTTP_MULTI_STATUS, txn, mrock.root->doc);
            xmlFreeDoc(mrock.root->doc);
            return 0;
        }
    }

  done:
    switch (r) {
    case 0:
        return (overwrite < 0) ? HTTP_NO_CONTENT : HTTP_CREATED;

    case IMAP_MAILBOX_EXISTS:
        return HTTP_PRECOND_FAILED;

    case IMAP_PERMISSION_DENIED:
         
        txn->error.precond = DAV_NEED_PRIVS;
        txn->error.resource = dest_tgt->path;
        txn->error.rights = (overwrite < 0) ? DACL_UNBIND : DACL_BIND;
        return HTTP_NO_PRIVS;

    default:
        txn->error.desc = error_message(r);
        return HTTP_SERVER_ERROR;
    }
}