* mu-maildir.[ch]: re-implement message flag parsing, message moving

This commit is contained in:
Dirk-Jan C. Binnema
2011-08-13 02:00:04 +03:00
parent 2bdfb1159d
commit bad4973408
5 changed files with 233 additions and 421 deletions

View File

@ -680,199 +680,6 @@ mu_msg_is_readable (MuMsg *self)
== 0) ? TRUE : FALSE;
}
enum _MaildirType {
MAILDIR_TYPE_CUR,
MAILDIR_TYPE_NEW,
MAILDIR_TYPE_OTHER
};
typedef enum _MaildirType MaildirType;
static MaildirType
get_maildir_type (const char *path)
{
MaildirType mtype;
gchar *dirname;
dirname = g_path_get_dirname (path);
/* g_path_get_dirname does not specify if the name includes
* the closing '/'... if it does, remove it */
if (dirname[strlen(dirname) - 1 ] == G_DIR_SEPARATOR)
dirname[strlen(dirname) - 1] = '\0';
if (g_str_has_suffix (dirname, "cur"))
mtype = MAILDIR_TYPE_CUR;
else if (g_str_has_suffix (dirname, "new"))
mtype = MAILDIR_TYPE_NEW;
else
mtype = MAILDIR_TYPE_OTHER;
g_free (dirname);
return mtype;
}
char*
get_new_fullpath (const char *oldpath, const char *targetmdir,
MaildirType mtype, MuFlags flags)
{
char *filename, *newfullpath;
const char* mdirsub;
filename = g_path_get_basename (oldpath);
if (mtype == MAILDIR_TYPE_CUR)
mdirsub = "cur";
else if (mtype == MAILDIR_TYPE_NEW)
mdirsub = "new";
else {
g_free (filename);
g_return_val_if_reached (NULL);
return NULL;
}
newfullpath = g_strdup_printf ("%s%c%s%c%s",
targetmdir,
G_DIR_SEPARATOR,
mdirsub,
G_DIR_SEPARATOR,
filename);
g_free (filename);
/* we update the filename for the new flags; in case the NEW
* flag is set/unset, this can also influence the dir */
if (flags != MU_FLAG_NONE) {
gchar *tmp;
tmp = mu_maildir_get_path_from_flags (newfullpath, flags);
g_free (newfullpath);
newfullpath = tmp;
}
return newfullpath;
}
static gboolean
msg_move (const char* oldpath, const char *newfullpath, GError **err)
{
if (access (oldpath, R_OK) != 0) {
g_set_error (err, 0, MU_ERROR_FILE, "cannot read %s",
oldpath);
return FALSE;
}
if (access (newfullpath, F_OK) == 0) {
g_set_error (err, 0, MU_ERROR_FILE, "%s already exists",
newfullpath);
return FALSE;
}
if (rename (oldpath, newfullpath) != 0) {
g_set_error (err, 0, MU_ERROR_FILE, "error moving %s to %s",
oldpath, newfullpath);
return FALSE;
}
/* double check -- is the target really there? */
if (access (newfullpath, F_OK) != 0) {
g_set_error (err, 0, MU_ERROR_FILE, "can't find target (%s)",
newfullpath);
return FALSE;
}
if (access (oldpath, F_OK) == 0) {
g_set_error (err, 0, MU_ERROR_FILE, "source is still there (%s)",
oldpath);
return FALSE;
}
return TRUE;
}
static gboolean
check_source_file (const char *src, MaildirType *mtype, GError **err)
{
if (!g_path_is_absolute(src)) {
g_set_error (err, 0, MU_ERROR_FILE,
"source is not an absolute path: '%s'", src);
return FALSE;
}
*mtype = get_maildir_type (src);
if (*mtype != MAILDIR_TYPE_CUR && *mtype != MAILDIR_TYPE_NEW) {
g_set_error (err, 0, MU_ERROR_FILE,
"source is not in a maildir: '%s'", src);
return FALSE;
}
return TRUE;
}
static gboolean
check_target_dir (const char* targetmdir, GError **err)
{
if (!g_path_is_absolute(targetmdir)) {
g_set_error (err, 0, MU_ERROR_FILE,
"target is not an absolute path: '%s'", targetmdir);
return FALSE;
}
if (!mu_util_check_dir (targetmdir, TRUE, TRUE)) {
g_set_error (err, 0, MU_ERROR_FILE,
"target is not a read-writable dir: '%s'", targetmdir);
return FALSE;
}
return TRUE;
}
/*
* move a msg to another maildir, trying to maintain 'integrity',
* ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be
* super-paranoid here...
*/
gchar*
mu_msg_file_move_to_maildir (const char* oldpath, const char* targetmdir,
MuFlags flags, GError **err)
{
MaildirType mtype;
char *newfullpath;
gboolean rv;
g_return_val_if_fail (oldpath, FALSE);
g_return_val_if_fail (targetmdir, FALSE);
if (!check_source_file (oldpath, &mtype, err))
return FALSE;
if (!check_target_dir (targetmdir, err))
return FALSE;
newfullpath = get_new_fullpath (oldpath, targetmdir, mtype, flags);
if (!newfullpath) {
g_set_error (err, 0, MU_ERROR_FILE,
"failed to determine target full path");
return FALSE;
}
if (g_strcmp0 (oldpath, newfullpath) == 0) {
g_set_error (err, 0, MU_ERROR_FILE,
"target equals source");
return FALSE;
}
rv = msg_move (oldpath, newfullpath, err);
if (!rv) {
g_free (newfullpath);
return NULL;
}
return newfullpath;
}
/*
* move a msg to another maildir, trying to maintain 'integrity',
* ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be
@ -885,10 +692,9 @@ mu_msg_move_to_maildir (MuMsg *self, const char* targetmdir,
char *newfullpath;
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (targetmdir, FALSE);
newfullpath = mu_msg_file_move_to_maildir (mu_msg_get_path (self),
targetmdir, flags, err);
newfullpath = mu_maildir_move_message (mu_msg_get_path (self),
targetmdir, flags, err);
if (newfullpath) /* update our path to new one... */
mu_msg_cache_set_str (self->_cache, MU_MSG_FIELD_ID_PATH, newfullpath,
TRUE); /* the cache will free the string */