diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /libmail/imapacl.C | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'libmail/imapacl.C')
| -rw-r--r-- | libmail/imapacl.C | 925 | 
1 files changed, 925 insertions, 0 deletions
| diff --git a/libmail/imapacl.C b/libmail/imapacl.C new file mode 100644 index 0000000..c257bab --- /dev/null +++ b/libmail/imapacl.C @@ -0,0 +1,925 @@ +/* +** Copyright 2004, Double Precision Inc. +** +** See COPYING for distribution information. +*/ +#include "libmail_config.h" +#include "addmessage.H" +#include "imap.H" +#include "misc.H" +#include "imapacl.H" +#include "imapfolder.H" +#include "imapfolders.H" +#include "imaphandler.H" +#include "imaplisthandler.H" +#include "maildir/maildiraclt.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <sstream> +#include <algorithm> + +using namespace std; + + +LIBMAIL_START + +/* +** ACL1 MYRIGHTS response. +*/ + +class imapGetMyRights::parseMyRights : public imapHandlerStructured { + +	string folder; +	string &rights; + +	string curfolder; +	void (parseMyRights::*next_func)(imap &, Token); + +public: +	parseMyRights(string folderArg, string &rightsArg); +	~parseMyRights(); +	void installed(imap &imapAccount); + +private: +	const char *getName(); +	void timedOut(const char *); +	void process(imap &imapAccount, Token t); + +	void getFolder(imap &imapAccount, Token t); +	void getRights(imap &imapAccount, Token t); + +}; + + +/* +** ACL2 LIST(MYRIGHTS) handler. +*/ + +class imapGetMyRights::listMyRights : private vector<imapFolder>, +		       public imapLIST { + +	string folderName; +	string &rights; + +public: +	listMyRights(string folderNameArg, +		     string &rightsArg); +	~listMyRights(); + +	void processExtendedAttributes(imapFolder &); +}; + +LIBMAIL_END + +mail::imapGetMyRights::imapGetMyRights(string folderNameArg, string &rightsArg, +				       mail::callback &callbackArg) +	: folderName(folderNameArg), +	  rights(rightsArg), +	  callback(callbackArg) +{ +} + +mail::imapGetMyRights::~imapGetMyRights() +{ +} + +void mail::imapGetMyRights::installed(imap &imapAccount) +{ +	if (imapAccount.getCapability("ACL") == "ACL") +	{ +		/* ACL 1 */ +	 +		imapAccount.imapcmd("MYRIGHTS", +				    "MYRIGHTS " +				    + imapAccount.quoteSimple(folderName) +				    + "\r\n"); +	} +	else +	{ +		imapAccount.imapcmd("MYRIGHTS", +				    "LIST (MYRIGHTS) \"\" " +				    + imapAccount.quoteSimple(folderName) +				    + "\r\n"); +	} +} + +const char *mail::imapGetMyRights::getName() +{ +	return "MYRIGHTS"; +} + +void mail::imapGetMyRights::timedOut(const char *errmsg) +{ +	callbackTimedOut(callback, errmsg); +} + +bool mail::imapGetMyRights::untaggedMessage(imap &imapAccount, +					    string msgname) +{ +	if (msgname == "MYRIGHTS") +	{ +		imapAccount +			.installBackgroundTask(new parseMyRights(folderName, +								 rights)); +		return true; +	} + +	if (msgname == "LIST") +	{ +		imapAccount +			.installBackgroundTask(new listMyRights(folderName, +								rights)); +		return true; +	} +	return false; +} + +bool mail::imapGetMyRights::taggedMessage(imap &imapAccount, string msgname, +					  string message, +					  bool okfail, string errmsg) +{ +	if (!okfail) +	{ +		callback.fail(errmsg); +		imapAccount.uninstallHandler(this); +		return true; +	} +	callback.success(message); +	imapAccount.uninstallHandler(this); +	return true; +} + +/* ---- Parse ACL1 MYRIGHTS response ----- */ + +mail::imapGetMyRights::parseMyRights::parseMyRights(string folderArg, +						    string &rightsArg) +	: folder(folderArg), rights(rightsArg), +	  next_func(&mail::imapGetMyRights::parseMyRights::getFolder) +{ +	rights=""; +} + +mail::imapGetMyRights::parseMyRights::~parseMyRights() +{ +} + +void mail::imapGetMyRights::parseMyRights::installed(imap &imapAccount) +{ +} + +const char *mail::imapGetMyRights::parseMyRights::getName() +{ +	return "LISTMYRIGHTS_FOLDER"; +} + +void mail::imapGetMyRights::parseMyRights::timedOut(const char *dummy) +{ +} + +void mail::imapGetMyRights::parseMyRights::process(imap &imapAccount, Token t) +{ +	(this->*next_func)(imapAccount, t); +} + +void mail::imapGetMyRights::parseMyRights::getFolder(imap &imapAcct, Token t) +{ +	if (t != ATOM && t != STRING) +	{ +		error(imapAcct); +		return; +	} +	curfolder=t.text; +	next_func=&mail::imapGetMyRights::parseMyRights::getRights; +} + +void mail::imapGetMyRights::parseMyRights::getRights(imap &imapAcct, Token t) +{ +	if (t == EOL) +	{ +		done(); +		return; +	} + +	if (t != ATOM && t != STRING) +	{ +		error(imapAcct); +		return; +	} + +	string s=t.text; + +	size_t p=s.find(ACL_DELETE_SPECIAL[0]); + +	if (p != std::string::npos) +		s.replace(s.begin()+p, s.begin()+p+1, +			  ACL_DELETEMSGS ACL_DELETEFOLDER ACL_EXPUNGE); +	sort(s.begin(), s.end()); + +	if (curfolder == folder) +		rights=s; +} + +/* ---- Parse ACL2 LIST(MYRIGHTS) response ----- */ + +mail::imapGetMyRights::listMyRights::listMyRights(string folderNameArg, +						  string &rightsArg) +	: imapLIST( *this, 0), folderName(folderNameArg), +	  rights(rightsArg) +{ +} + +mail::imapGetMyRights::listMyRights::~listMyRights() +{ +} + +void mail::imapGetMyRights::listMyRights +::processExtendedAttributes(imapFolder &f) +{ +	if (f.getPath() != folderName) +		return; /* Sanity check */ + +	vector<mail::imapparsefmt *>::iterator b=xattributes.children.begin(), +		e=xattributes.children.end(); + +	while (b != e) +	{ +		mail::imapparsefmt *node= *b++; + +		if (node->children.size() < 2) +			continue; + +		string name=(*node->children.begin())->value; + +		mail::upper(name); + +		if (name != "MYRIGHTS") +			continue; + +		rights=node->children.begin()[1]->value; + +		size_t p=rights.find(ACL_DELETE_SPECIAL[0]); + +		if (p != std::string::npos) +			rights.replace(rights.begin()+p, rights.begin()+p+1, +				  ACL_DELETEMSGS ACL_DELETEFOLDER ACL_EXPUNGE); + +		sort(rights.begin(), rights.end()); +		break; +	} + +} + +/***** GET RIGHTS *****/ + +LIBMAIL_START + +/* +** ACL1 "ACL" response. +*/ + +class imapGetRights::parseGetRights : public imapHandlerStructured { + +	string folder; +	list<pair<string,string> > &rights; + +	string curfolder; +	string curidentifier; +	void (parseGetRights::*next_func)(imap &, Token); + +public: +	parseGetRights(string folderArg, list<pair<string,string> >&rightsArg); +	~parseGetRights(); +	void installed(imap &imapAccount); + +private: +	const char *getName(); +	void timedOut(const char *); +	void process(imap &imapAccount, Token t); + +	void getFolder(imap &imapAccount, Token t); +	void getIdentifier(imap &imapAccount, Token t); +	void getRights(imap &imapAccount, Token t); + +}; + +LIBMAIL_END + +/* +** ACL2 LIST(ACL) handler. +*/ + +class mail::imapGetRights::listGetRights : private vector<mail::imapFolder>, +	    public mail::imapLIST { + +	string folderName; +	list< pair< string, string> > &rights; + +public: +	listGetRights(string folderNameArg, +		      list<pair< string, string> > &rightsArg); +	~listGetRights(); + +	void processExtendedAttributes(mail::imapFolder &); +}; + +mail::imapGetRights::imapGetRights(string folderNameArg, +				   list<pair<string,string> >&rightsArg, +				   mail::callback &callbackArg) +	: folderName(folderNameArg), rights(rightsArg), +	  callback(callbackArg) +{ +} + +mail::imapGetRights::~imapGetRights() +{ +} + +void mail::imapGetRights::installed(imap &imapAccount) +{ +	if (imapAccount.getCapability("ACL") == "ACL") +	{ +		/* ACL 1 */ +	 +		imapAccount.imapcmd("GETACL", +				    "GETACL " +				    + imapAccount.quoteSimple(folderName) +				    + "\r\n"); +	} +	else +	{ +		imapAccount.imapcmd("GETACL", +				    "LIST (ACL) \"\" " +				    + imapAccount.quoteSimple(folderName) +				    + "\r\n"); +	} + +} + +const char *mail::imapGetRights::getName() +{ +	return "GETACL"; +} + +void mail::imapGetRights::timedOut(const char *errmsg) +{ +	callbackTimedOut(callback, errmsg); +} + +bool mail::imapGetRights::untaggedMessage(imap &imapAccount, string msgname) +{ +	if (msgname == "LIST") +	{ +		imapAccount +			.installBackgroundTask(new listGetRights(folderName, +								 rights)); +		return true; +	} + +	if (msgname == "ACL") +	{ +		imapAccount +			.installBackgroundTask(new parseGetRights(folderName, +								  rights)); +		return true; +	} +	return false; +} + +bool mail::imapGetRights::taggedMessage(imap &imapAccount, string msgname, +					string message, +					bool okfail, string errmsg) +{ +	if (!okfail) +	{ +		callback.fail(errmsg); +		imapAccount.uninstallHandler(this); +		return true; +	} +	callback.success(message); +	imapAccount.uninstallHandler(this); +	return true; +} + +/* --- Process ACL1 "ACL" response --- */ + +mail::imapGetRights::parseGetRights::parseGetRights(string folderArg, +						  list<pair<string,string> > +						  &rightsArg) +	: folder(folderArg), rights(rightsArg), +	  next_func(&mail::imapGetRights::parseGetRights::getFolder) +{ +	rights.clear(); +} + +mail::imapGetRights::parseGetRights::~parseGetRights() +{ +} + +void mail::imapGetRights::parseGetRights::installed(imap &imapAccount) +{ +} + +const char *mail::imapGetRights::parseGetRights::getName() +{ +	return "GETACL_FOLDER"; +} + +void mail::imapGetRights::parseGetRights::timedOut(const char *dummy) +{ +} + +void mail::imapGetRights::parseGetRights::process(imap &imapAccount, Token t) +{ +	(this->*next_func)(imapAccount, t); +} + +void mail::imapGetRights::parseGetRights::getFolder(imap &imapAcct, Token t) +{ +	if (t != ATOM && t != STRING) +	{ +		error(imapAcct); +		return; +	} +	curfolder=t.text; +	next_func=&mail::imapGetRights::parseGetRights::getIdentifier; +} + +void mail::imapGetRights::parseGetRights::getIdentifier(imap &imapAcct,Token t) +{ +	if (t == EOL) +	{ +		done(); +		return; +	} + +	if (t != ATOM && t != STRING) +	{ +		error(imapAcct); +		return; +	} + +	curidentifier=t.text; + +	/* Fudge ACL 1 identifiers into ACL 2 identifiers */ + +	if (curidentifier != "anyone" && +	    curidentifier != "anonymous" && +	    curidentifier != "authuser" && +	    curidentifier != "owner" && +	    curidentifier != "administrators") +		curidentifier="user=" + curidentifier; + +	next_func=&mail::imapGetRights::parseGetRights::getRights; +} + +void mail::imapGetRights::parseGetRights::getRights(imap &imapAcct, Token t) +{ +	if (t == EOL) +	{ +		done(); +		return; +	} + +	if (t != ATOM && t != STRING) +	{ +		error(imapAcct); +		return; +	} + +	string s=t.text; + +	size_t p=s.find(ACL_DELETE_SPECIAL[0]); + +	if (p != std::string::npos) +		s.replace(s.begin()+p, s.begin()+p+1, +			  ACL_DELETEMSGS ACL_DELETEFOLDER ACL_EXPUNGE); +	sort(s.begin(), s.end()); + +	if (curfolder == folder) +		rights.push_back(make_pair(curidentifier, s)); +	next_func=&mail::imapGetRights::parseGetRights::getIdentifier; +} + +/* --- Process ACL2 LIST(ACL) response --- */ + +mail::imapGetRights +::listGetRights::listGetRights(string folderNameArg, +			       list<pair<string,string> > &rightsArg) +	: imapLIST(*this, 0), folderName(folderNameArg), +	  rights(rightsArg) +{ +} + +mail::imapGetRights::listGetRights::~listGetRights() +{ +} + +void mail::imapGetRights::listGetRights +::processExtendedAttributes(imapFolder &f) +{ +	if (f.getPath() != folderName) +		return; /* Sanity check */ + +	vector<mail::imapparsefmt *>::iterator b=xattributes.children.begin(), +		e=xattributes.children.end(); + +	while (b != e) +	{ +		mail::imapparsefmt *node= *b++; + +		if (node->children.size() < 2) +			continue; + +		string name=(*node->children.begin())->value; + +		mail::upper(name); + +		if (name != "ACL") +			continue; + +		mail::imapparsefmt *rights_list=node->children.begin()[1]; + +		vector<mail::imapparsefmt *>::iterator +			bb=rights_list->children.begin(), +			ee=rights_list->children.end(); + +		while (bb != ee) +		{ +			mail::imapparsefmt *node= *bb++; + +			if (node->children.size() < 2) +				continue; + +			string identifier=node->children.begin()[0]->value; +			string r=node->children.begin()[1]->value; + +			size_t p=r.find(ACL_DELETE_SPECIAL[0]); + +			if (p != std::string::npos) +				r.replace(r.begin()+p, r.begin()+p+1, +					  ACL_DELETEMSGS ACL_DELETEFOLDER +					  ACL_EXPUNGE); + +			sort(r.begin(), r.end()); +			rights.push_back(make_pair(identifier, r)); +		} +		break; +	} +} + +/* --- DELETE or SET ACL rights */ + + +LIBMAIL_START + +/* ACL2 RIGHTS-INFO and ACLFAILED untagged messages */ + +class imapSetRights::parseRightsInfo : public imapHandlerStructured { + +	string &folderName; +	string &identifier; +	vector<string> &rights; + +	void (parseRightsInfo::*next_func)(imap &, Token); + +public: +	parseRightsInfo(string &folderNameArg, +			string &identifierArg, +			vector<string> &rightsArg); +	~parseRightsInfo(); + +	void installed(imap &imapAccount); +	const char *getName(); +	void timedOut(const char *); +	void process(imap &imapAccount, Token t); + +	void get_folder(imap &imapAccount, Token t); +	void get_identifier(imap &imapAccount, Token t); +	void get_rights(imap &imapAccount, Token t); + +}; + +class imapSetRights::parseAclFailed : public imapHandlerStructured { + +	string &folderName, &errmsg; +	bool wantErrorMessage; +	void (parseAclFailed::*next_func)(imap &, Token); +public: +	parseAclFailed(string &folderNameArg, string &errmsgArg); +	~parseAclFailed(); + +	void installed(imap &imapAccount); +	const char *getName(); +	void timedOut(const char *); +	void process(imap &imapAccount, Token t); + +private: +	int process(imap &imapAccount, std::string &buffer); +}; +LIBMAIL_END + +mail::imapSetRights::imapSetRights(string folderNameArg, +				   string identifierArg, +				   string rightsArg, +				   bool delIdentifierArg, +				   string &errorIdentifierArg, +				   vector<string> &errorRightsArg, +				   mail::callback &callbackArg) +	: folderName(folderNameArg), +	  identifier(identifierArg), +	  rights(rightsArg), +	  delIdentifier(delIdentifierArg), +	  errorIdentifier(errorIdentifierArg), +	  errorRights(errorRightsArg), +	  callback(callbackArg) +{ +} + +mail::imapSetRights::~imapSetRights() +{ +} + +void mail::imapSetRights::installed(imap &imapAccount) +{ +	if (imapAccount.getCapability("ACL") == "ACL") +	{ +		/* ACL 1 */ + +		string n=identifier; + +		if (n != "anyone" && +		    n != "anonymous" && +		    n != "authuser" && +		    n != "owner" && +		    n != "administrators") +		{ +			if (strncmp(n.c_str(), "user=", 5)) +			{ +				callback.fail("Invalid ACL identifier."); +				imapAccount.uninstallHandler(this); +				return; +			} + +			n=n.substr(5); +		} + +		// If all three "etx" were originally set, it would've been +		// replaced with a "d".  If we still have one or more of them +		// it means that not all three were specified. + +		if (rights.find(ACL_DELETEMSGS[0]) != std::string::npos || +		    rights.find(ACL_DELETEFOLDER[0]) != std::string::npos || +		    rights.find(ACL_EXPUNGE[0]) != std::string::npos) +		{ +			errorIdentifier=identifier; +			errorRights.push_back(""); +			errorRights.push_back(ACL_DELETEMSGS +					      ACL_EXPUNGE +					      ACL_DELETEFOLDER); +			errorRights.push_back(ACL_LOOKUP); +			errorRights.push_back(ACL_READ); +			errorRights.push_back(ACL_SEEN); +			errorRights.push_back(ACL_WRITE); +			errorRights.push_back(ACL_INSERT); +			errorRights.push_back(ACL_POST); +			errorRights.push_back(ACL_CREATE); +			errorRights.push_back(ACL_ADMINISTER); +			callback.fail("Invalid access right combination."); +			imapAccount.uninstallHandler(this); +			return; +		} + +		imapAccount.imapcmd("SETACL", +				    delIdentifier ? +				    "DELETEACL " +				    + imapAccount.quoteSimple(folderName) +				    + " " +				    + imapAccount.quoteSimple(n) +				    + "\r\n" +				    : +				    "SETACL " +				    + imapAccount.quoteSimple(folderName) +				    + " " +				    + imapAccount.quoteSimple(n) +				    + " " +				    + imapAccount.quoteSimple(rights) +				    + "\r\n"); +	} +	else +	{ +		imapAccount.imapcmd("SETACL", +				    delIdentifier ? +				    "ACL DELETE " +				    + imapAccount.quoteSimple(folderName) +				    + " " +				    + imapAccount.quoteSimple(identifier) +				    + "\r\n" +				    : +				    "ACL STORE " +				    + imapAccount.quoteSimple(folderName) +				    + " " +				    + imapAccount.quoteSimple(identifier) +				    + " " +				    + imapAccount.quoteSimple(rights) +				    + "\r\n"); +	} +} + +const char *mail::imapSetRights::getName() +{ +	return "SETACL"; +} + +void mail::imapSetRights::timedOut(const char *errmsg) +{ +	callbackTimedOut(callback, errmsg); +} + +bool mail::imapSetRights::untaggedMessage(imap &imapAccount, string msgname) +{ +	if (msgname == "LIST") +	{ +		dummy_rights.clear(); +		imapAccount +			.installBackgroundTask(new imapGetRights +					       ::listGetRights(folderName, +							       dummy_rights)); +		return true; +	} + +	if (msgname == "ACLFAILED") +	{ +		imapAccount +			.installBackgroundTask(new parseAclFailed(dummy, +								  dummy)); +		return true; +	} + +	if (msgname == "RIGHTS-INFO") +	{ +		imapAccount +			.installBackgroundTask(new +					       parseRightsInfo(dummy, +							       errorIdentifier, +							       errorRights)); +		return true; +	} + +	return false; +} + +bool mail::imapSetRights::taggedMessage(imap &imapAccount, string msgname, +					string message, +					bool okfail, string errmsg) +{ +	if (okfail && errorIdentifier.size() > 0) +	{ +		okfail=false; +		message="Invalid access rights."; +	} + +	if (!okfail) +	{ +		callback.fail(errmsg); +		imapAccount.uninstallHandler(this); +		return true; +	} +	callback.success(message); +	imapAccount.uninstallHandler(this); +	return true; +} + + +mail::imapSetRights::parseRightsInfo::parseRightsInfo(string &folderNameArg, +						      string &identifierArg, +						      vector<string> &rightsArg) +	: folderName(folderNameArg), +	  identifier(identifierArg), +	  rights(rightsArg), next_func(&mail::imapSetRights::parseRightsInfo +				       ::get_folder) +{ +} + +mail::imapSetRights::parseRightsInfo::~parseRightsInfo() +{ +} + +void mail::imapSetRights::parseRightsInfo::installed(imap &imapAccount) +{ +} + +const char *mail::imapSetRights::parseRightsInfo::getName() +{ +	return "RIGHTS-INFO"; +} + +void mail::imapSetRights::parseRightsInfo::timedOut(const char *dummy) +{ +} + +void mail::imapSetRights::parseRightsInfo::process(imap &imapAccount, Token t) +{ +	(this->*next_func)(imapAccount, t); +} + +void mail::imapSetRights::parseRightsInfo::get_folder(imap &imapAccount, +						      Token t) +{ +	if (t != ATOM && t != STRING) +	{ +		error(imapAccount); +		return; +	} +	folderName=t.text; +	next_func= &mail::imapSetRights::parseRightsInfo::get_identifier; +} + +void mail::imapSetRights::parseRightsInfo::get_identifier(imap &imapAccount, +							  Token t) +{ +	if (t != ATOM && t != STRING) +	{ +		error(imapAccount); +		return; +	} +	identifier=t.text; +	next_func= &mail::imapSetRights::parseRightsInfo::get_rights; +} + +void mail::imapSetRights::parseRightsInfo::get_rights(imap &imapAccount, +						      Token t) +{ +	if (t == EOL) +	{ +		done(); +		return; +	} +	if (t != ATOM && t != STRING) +	{ +		error(imapAccount); +		return; +	} +	rights.push_back(t.text); +} + +mail::imapSetRights::parseAclFailed::parseAclFailed(string &folderNameArg, +						    string &errmsgArg) +	: folderName(folderNameArg), +	  errmsg(errmsgArg), +	  wantErrorMessage(false) +{ +} + +mail::imapSetRights::parseAclFailed::~parseAclFailed() +{ +} + +void mail::imapSetRights::parseAclFailed::installed(imap &imapAccount) +{ +} + +const char *mail::imapSetRights::parseAclFailed::getName() +{ +	return "ACLFAILED"; +} + +void mail::imapSetRights::parseAclFailed::timedOut(const char *dummy) +{ +} + +void mail::imapSetRights::parseAclFailed::process(imap &imapAccount, +						  Token t) +{ +	if (t != ATOM && t != STRING) +	{ +		error(imapAccount); +		return; +	} + +	folderName=t.text; +	wantErrorMessage=true; +} + +int mail::imapSetRights::parseAclFailed::process(imap &imapAccount, +						 string &buffer) +{ +	if (!wantErrorMessage) +		return imapHandlerStructured::process(imapAccount, buffer); + +	size_t p=buffer.find('\n'); + +	if (p == std::string::npos) +		return 0; + +	string msg=buffer.substr(0, p); + +	size_t cr=msg.find('\r'); +	if (cr != std::string::npos) +		msg=msg.substr(0, cr); +	errmsg=msg; +	done(); +	return (int)p; +} | 
