diff options
| author | Sam Varshavchik | 2018-07-14 15:51:42 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2018-07-16 21:20:25 -0400 | 
| commit | 9643d3d5adcbc6357833a818e2928eb8e76717ed (patch) | |
| tree | 367ec86c8ccfb3aa2ab40b2440ebabfea382e0ce /maildir/maildirmake.c | |
| parent | 3359e8155147662382d2fd982bcf75a1644901a0 (diff) | |
| download | courier-libs-9643d3d5adcbc6357833a818e2928eb8e76717ed.tar.bz2 | |
Add maidirmake options to convert pre-unicode mailboxes to unicode mailboxes.
Diffstat (limited to 'maildir/maildirmake.c')
| -rw-r--r-- | maildir/maildirmake.c | 434 | 
1 files changed, 433 insertions, 1 deletions
| diff --git a/maildir/maildirmake.c b/maildir/maildirmake.c index 9e14eb4..6d35899 100644 --- a/maildir/maildirmake.c +++ b/maildir/maildirmake.c @@ -1,5 +1,5 @@  /* -** Copyright 1998 - 2006Double Precision, Inc. +** Copyright 1998 - 2018 Double Precision, Inc.  ** See COPYING for distribution information.  */ @@ -25,8 +25,10 @@  #include	"maildircreate.h"  #include	"maildirmisc.h" +#include	"maildirinfo.h"  #include	"maildirsharedrc.h"  #include	"maildirquota.h" +#include	"maildirfilter.h"  #include	<courier-unicode.h>  static void usage() @@ -194,6 +196,421 @@ int	found;  	exit(0);  } +/***************************************************************************** + +Convert modified-UTF7 folder names to UTF-8 (sort-of). + +*****************************************************************************/ + +struct convertutf8_list { +	struct convertutf8_list *next; +	char *rename_from; +	char *rename_to; +}; + +struct convertutf8_status { +	struct convertutf8_list *list; +	int status; +}; + +/* Find folders that need to change */ + +static void convertutf8_build_list(const char *inbox_name, +				   void *arg) +{ +	struct convertutf8_status *status= +		(struct convertutf8_status *)arg; +	struct convertutf8_list *list; + +	char *converted=imap_foldername_to_filename(0, inbox_name); + +	if (!converted) +	{ +		fprintf(stderr, +			"Error: %s: does not appear to be valid" +			" modified-UTF7\n", +			inbox_name); +		status->status=1; +		return; +	} + +	if (strcmp(converted, inbox_name) == 0) +	{ +		free(converted); +		return; +	} +	list=(struct convertutf8_list *)malloc(sizeof(struct convertutf8_list)); + +	if (!list || !(list->rename_from=strdup(inbox_name))) +	{ +		perror("malloc"); +		exit(1); +	} + +	list->rename_to=converted; +	list->next=status->list; +	status->list=list; +} + +void convertutf8(const char *maildir, const char *mailfilter, int doit) +{ +	struct convertutf8_status status; +	struct convertutf8_list *list; +	char *courierimapsubscribed; +	char *courierimapsubscribed_new; +	FILE *courierimapsubscribed_fp; +	struct maildirfilter mf; +	int mf_status; +	char *mailfilter_newname=0; + +	memset(&status, 0, sizeof(status)); +	memset(&mf, 0, sizeof(mf)); + +	printf("Checking %s:\n", maildir); + +	maildir_list(maildir, convertutf8_build_list, &status); + +	if (status.status) +		exit(status.status); + +	if (mailfilter) +	{ +		struct maildirfilterrule *r; + +		/* +		** Try to convert folder references from mailfilter +		*/ + +		mailfilter_newname=malloc(strlen(mailfilter)+10); + +		strcat(strcpy(mailfilter_newname, mailfilter), ".new"); +		mf_status=maildir_filter_loadrules(&mf, mailfilter); + +		if (mf_status != MF_LOADOK && mf_status != MF_LOADNOTFOUND) +		{ +			fprintf(stderr, "Error: cannot load %s\n", +				mailfilter); +		} + +		for (r=mf.first; r; r=r->next) +		{ +			char *converted; + +			/* Look for deliveries to a folder */ + +			if (strncmp(r->tofolder, "INBOX.", 6)) +				continue; + +			converted=imap_foldername_to_filename(0, r->tofolder); + +			if (!converted) +			{ +				fprintf(stderr, "Error: %s: " +					"%s: does not appear to be valid " +					"modified-UTF7\n", +					mailfilter, +					r->tofolder); +				status.status=1; +			} + +			if (strcmp(converted, r->tofolder) == 0) +			{ +				free(converted); +				continue; +			} + +			printf("Mail filter to %s updated to %s\n", +			       r->tofolder, converted); + +			free(r->tofolder); +			r->tofolder=converted; +		} + +		if (mf_status == MF_LOADOK) +		{ +			FILE *fp=fopen(mailfilter, "r"); +			char detected_from[1024]; +			char detected_tomaildir[1024]; +			char buffer[1024]; +			struct stat st_buf; + +			/* +			** We need to know the FROM address and the MAILDIR +			** reference. Attempt to ham-fistedly parse the +			** current filter file. +			*/ + +			detected_from[0]=0; +			detected_tomaildir[0]=0; + +			if (!fp) +			{ +				perror(mailfilter); +				exit(1); +			} + +			while (fgets(buffer, sizeof(buffer), fp)) +			{ +				char *p, *q; + +				if (strncmp(buffer, "FROM='", 6) == 0) +				{ +					char *p=strchr(buffer+6, '\''); + +					if (!p) +					{ +						fprintf(stderr, +							"Cannot parse %s\n", +							mailfilter); +						status.status=1; +					} +					else +					{ +						*p=0; +						strcpy(detected_from, buffer+6); + +						/* +						  Unescape, because saverules() +						  escapes it. +						*/ + +						for (q=p=detected_from; *p; p++) +						{ +							if (*p == '\\' && p[1]) +								++p; +							*q=*p; +							++q; +						} +						*q=0; +					} +				} + +				if (strncmp(buffer, "to \"", 4) == 0) +				{ +					p=strstr(buffer+4, "/.\""); + +					if (!p) +					{ +						fprintf(stderr, +							"Cannot parse %s\n", +							mailfilter); +						status.status=1; +					} +					else +					{ +						*p=0; +					} +					strcpy(detected_tomaildir, buffer+4); +				} +			} +			fclose(fp); +			if (detected_from[0] == 0 || +			    detected_tomaildir[0] == 0) +			{ +				fprintf(stderr, +					"Failed to parse %s\n", +					mailfilter); +				status.status=1; +			} +			maildir_filter_saverules(&mf, mailfilter_newname, +						 detected_tomaildir, +						 detected_from); + +			if (stat(mailfilter, &st_buf) || +			    chmod(mailfilter_newname, st_buf.st_mode)) +			{ +				perror(mailfilter); +				exit(1); +			} +			/* +			** If we're root, preserve the ownership and permission +			*/ +			if (geteuid() == 0) +			{ +				if (chown(mailfilter_newname, st_buf.st_uid, +					  st_buf.st_gid)) +				{ +					perror(mailfilter_newname); +					exit(1); +				} +			} +		} +	} +	else +	{ +		mf_status=MF_LOADNOTFOUND; +	} + +	courierimapsubscribed=malloc(strlen(maildir)+100); +	courierimapsubscribed_new=malloc(strlen(maildir)+100); + +	strcat(strcpy(courierimapsubscribed, maildir), +	       "/courierimapsubscribed"); +	strcat(strcpy(courierimapsubscribed_new, maildir), +	       "/courierimapsubscribed.new"); + +	/* +	** Update folder references in the IMAP subscription file. +	*/ + +	if ((courierimapsubscribed_fp=fopen(courierimapsubscribed, "r")) +	    != NULL) +	{ +		char buffer[2048]; +		FILE *new_fp=fopen(courierimapsubscribed_new, "w"); +		char *converted; +		struct stat st_buf; + +		while (fgets(buffer, sizeof(buffer), courierimapsubscribed_fp)) +		{ +			char *p=strchr(buffer, '\n'); + +			if (!p) +			{ +				fprintf(stderr, "Error: courierimapsubscribed: " +					"folder name too long\n"); +				status.status=1; +				continue; +			} + +			*p=0; + +			converted=imap_foldername_to_filename(0, buffer); + +			if (!converted) +			{ +				fprintf(stderr, "Error: courierimapsubscribed: " +					"%s: does not appear to be valid " +					"modified-UTF7\n", +					buffer); +				status.status=1; +				continue; +			} +			fprintf(new_fp, "%s\n", converted); + +			if (strcmp(buffer, converted)) +			{ +				printf("Subscription to %s changed to %s\n", +				       buffer, converted); +			} +			free(converted); +		} +		if (fflush(new_fp) || fclose(new_fp)) +		{ +			exit(1); +		} +		fclose(courierimapsubscribed_fp); + +		/* +		** If we're root, preserve the ownership and permission +		*/ +		if (stat(courierimapsubscribed, &st_buf) || +		    chmod(courierimapsubscribed_new, st_buf.st_mode)) +		{ +			perror(courierimapsubscribed); +			exit(1); +		} + +		if (geteuid() == 0) +		{ +			if (chown(courierimapsubscribed_new, st_buf.st_uid, +				  st_buf.st_gid)) +			{ +				perror(courierimapsubscribed_new); +				exit(1); +			} +		} +	} + +	if (status.status) +	{ +		unlink(courierimapsubscribed_new); +		if (mf_status == MF_LOADOK) +			unlink(mailfilter_newname); +		exit(status.status); +	} +	for (list=status.list; list; list=list->next) +	{ +		char *frompath, *topath; + +		printf("Rename %s to %s\n", list->rename_from, list->rename_to); + +		frompath=malloc(strlen(maildir)+strlen(list->rename_from)); +		topath=malloc(strlen(maildir)+strlen(list->rename_to)); + +		if (!frompath || !topath) +		{ +			perror("malloc"); +			exit(1); +		} + +		strcat(strcpy(frompath, maildir), "/"); +		strcat(strcpy(topath, maildir), "/"); + +		/* They all have the INBOX. prefix, strip it off */ +		strcat(frompath, strchr(list->rename_from, '.')); +		strcat(topath, strchr(list->rename_to, '.')); + +		if (doit) +		{ +			if (rename(frompath, topath)) +			{ +				fprintf(stderr, +					"FATAL ERROR RENAMING %s to %s: %s\n", +					frompath, topath, strerror(errno)); +				status.status=1; +			} +		} +		free(frompath); +		free(topath); +	} + +	if (doit) +	{ +		if (courierimapsubscribed_fp) +		{ +			printf("Updating %s\n", courierimapsubscribed); + +			if (rename(courierimapsubscribed_new, +				   courierimapsubscribed)) +			{ +				fprintf(stderr, +					"FATAL ERROR RENAMING %s to %s: %s\n", +					courierimapsubscribed_new, +					courierimapsubscribed, strerror(errno)); +				status.status=1; +			} +		} + +		if (mf_status == MF_LOADOK) +		{ +			printf("Updating %s\n", mailfilter); + +			if (rename(mailfilter_newname, mailfilter)) +			{ +				fprintf(stderr, +					"FATAL ERROR RENAMING %s to %s: %s\n", +					mailfilter_newname, mailfilter, +					strerror(errno)); +				status.status=1; +			} +		} +	} +	else +	{ +		if (courierimapsubscribed_fp) +		{ +			printf("Verified %s\n", courierimapsubscribed); +		} + +		if (mf_status == MF_LOADOK) +		{ +			printf("Verified %s\n", mailfilter); +		} +	} +	exit(status.status); +} +  int main(int argc, char *argv[])  {  const char *maildir, *folder=0; @@ -297,6 +714,21 @@ char	*tmp=0;  			continue;  		} +		if (strcmp(argv[argn], "--convutf8") == 0 && argc-argn > 1) +		{ +			char *maildir=argv[++argn]; +			char *mailfilter=argn < argc ? argv[++argn]:0; +			convertutf8(maildir, mailfilter, 1); +			exit(0); +		} + +		if (strcmp(argv[argn], "--checkutf8") == 0 && argc-argn > 1) +		{ +			char *maildir=argv[++argn]; +			char *mailfilter=argn < argc ? argv[++argn]:0; +			convertutf8(maildir, mailfilter, 0); +			exit(0); +		}  		usage();  	} | 
