예제 #1
0
void GPG::Key::getDescription(std::vector<std::string> &descrArray,
			      size_t width)
{
	std::string keyDescr=longname;

	do
	{
		std::vector<unicode_char> unicode_buf;

		size_t p=keyDescr.find('\n');

		if (p == std::string::npos)
		{
			unicode::iconvert::convert(keyDescr,
						unicode_default_chset(),
						unicode_buf);
			keyDescr="";
		}
		else
		{
			unicode::iconvert::convert(keyDescr.substr(0, p),
						unicode_default_chset(),
						unicode_buf);
			keyDescr=keyDescr.substr(p+1);
		}

		std::vector< std::vector<unicode_char> > wrapped_text;

		std::back_insert_iterator<std::vector< std::vector
						       <unicode_char> > >
			insert_iter(wrapped_text);

		unicodewordwrap(unicode_buf.begin(),
				unicode_buf.end(),
				unicoderewrapnone(),
				insert_iter,
				width,
				true);

		for (std::vector< std::vector<unicode_char> >::const_iterator
			     b(wrapped_text.begin()),
			     e(wrapped_text.end()); b != e; ++b)
		{
			descrArray.push_back(unicode::iconvert
					     ::convert(*b,
						       unicode_default_chset())
					     );
		}
	} while (keyDescr.size() > 0);
}
예제 #2
0
CursesMultilineLabel::CursesMultilineLabel(CursesContainer *parent,
					   std::string textArg,
					   Curses::CursesAttr attributeArg)
	: Curses(parent), width(0), attribute(attributeArg)
{
	mail::iconvert::convert(textArg, unicode_default_chset(), text);
}
예제 #3
0
파일: rfc2231.c 프로젝트: MhdAlyan/courier
static int conv_unicode(char **text, const char *fromChset,
			const char *toChset)
{
	int err;
	char *p;

	if (!toChset)
		toChset=unicode_default_chset();

	if (!fromChset || !*fromChset)
		return 0;

	p=libmail_u_convert_tobuf(*text, fromChset, toChset, &err);

	if (p && err)
	{
		free(p);
		p=NULL;
	}

	if (!p)
		return (-1);

	free(*text);
	*text=p;
	return (0);
}
예제 #4
0
파일: rfc2231.c 프로젝트: debdungeon/qint
static int conv_unicode(char **text, const char *fromChset,
			const struct unicode_info *toChset)
{
#if HAVE_UNICODE

	const struct unicode_info *u=unicode_find(fromChset);

	if (toChset == NULL)
	{
		toChset=unicode_find(unicode_default_chset());

		if (!toChset)
			toChset=&unicode_ISO8859_1;
	}

	if (u)
	{
		char *p=unicode_xconvert(*text, u, toChset);

		if (!p)
			return (-1);

		free(*text);
		*text=p;
	}
#endif
	return (0);
}
예제 #5
0
void CursesMultilineLabel::setText(std::string newText)
{
	erase();
	text.clear();
	mail::iconvert::convert(newText, unicode_default_chset(), text);
	init();
	draw();
}
예제 #6
0
int main()
{
int i;
const char *c, *d;

	for (i=0; unicode_chsetlist[i].chsetname; i++)
		printf("chset=%s\n", unicode_chsetlist[i].chsetname);

	c=unicode_default_chset();
	d=unicode_find(c)->chset;

	printf("default_chset=%s\n", c);
	printf("real_default_chset=%s\n", d);

	exit(0);
	return (0);
}
예제 #7
0
void Gettext::Key::init()
{
    if (keys.size() > 0)
        return; // Already wuz here

    const char *p=gettext(keyname);

    while (p && *p)
    {
        if (*p++ == ':')
            break;
    }

    std::string n(p);

    // gettext has problems with a literal \x04, so provide an alternative

    std::string::iterator b, e, q;

    for (b=n.begin(), e=n.end(), q=b; b != e; ++b)
    {
        if (*b == '\\')
        {
            std::string::iterator c=b;

            if (++c != e && *c++ == '\\' && c != e)
            {
                b=c;

                *q++ = *b & 31;
                continue;
            }
        }

        *q++=*b;
    }

    n.erase(q, b);

    unicode::iconvert::convert(n, unicode_default_chset(), keys);
}
예제 #8
0
파일: mailbot.c 프로젝트: MhdAlyan/courier
int main(int argc, char **argv)
{
	int argn;
	FILE *tmpfp;
	struct rfc2045 *rfcp;
	struct mimeautoreply_s replyinfo;
	const char *subj=0;
	const char *txtfile=0, *mimefile=0;
	const char *mimedsn=0;
	int nosend=0;
	const char *replymode="reply";
	int replytoenvelope=0;
	int donotquote=0;
	const char *forwardsep="--- Forwarded message ---";
	const char *replysalut="%F writes:";
	struct rfc2045src *src;

	setlocale(LC_ALL, "");
	charset=unicode_default_chset();

	sender=NULL;
	for (argn=1; argn < argc; argn++)
	{
		char optc;
		char *optarg;

		if (argv[argn][0] != '-')
			break;

		if (strcmp(argv[argn], "--") == 0)
		{
			++argn;
			break;
		}

		optc=argv[argn][1];
		optarg=argv[argn]+2;

		if (!*optarg)
			optarg=NULL;

		switch (optc) {
		case 'c':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			if (optarg && *optarg)
			{
				char *p=libmail_u_convert_tobuf("",
								optarg,
								libmail_u_ucs4_native,
								NULL);

				if (!p)
				{
					fprintf(stderr, "Unknown charset: %s\n",
						charset);
					exit(1);
				}
				free(p);
				charset=optarg;
			}
			continue;
		case 't':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			txtfile=optarg;
			continue;
		case 'm':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			mimefile=optarg;
			continue;
		case 'r':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			recips=optarg;
			continue;
		case 'M':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			mimedsn=optarg;
			continue;
		case 'd':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			dbfile=optarg;
			continue;
		case 'e':
			replytoenvelope=1;
			continue;
		case 'T':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			if (optarg && *optarg)
				replymode=optarg;
			continue;
		case 'N':
			donotquote=1;
			continue;
		case 'F':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			if (optarg && *optarg)
				forwardsep=optarg;
			continue;
		case 'S':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			if (optarg && *optarg)
				replysalut=optarg;
			continue;
		case 'D':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			interval=optarg ? atoi(optarg):1;
			continue;
		case 'A':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			if (optarg)
			{
				struct header **h;

				for (h= &extra_headers; *h;
				     h= &(*h)->next)
					;

				if ((*h=malloc(sizeof(struct header))) == 0 ||
				    ((*h)->buf=strdup(optarg)) == 0)
				{
					perror("malloc");
					exit(EX_TEMPFAIL);
				}
				(*h)->next=0;
			}
			continue;
		case 's':
			if (!optarg && argn+1 < argc)
				optarg=argv[++argn];

			subj=optarg;
			continue;

		case 'f':
			if (optarg && *optarg)
			{
				sender=strdup(optarg);
			}
			else
			{
				sender=getenv("SENDER");
				if (!sender)
					continue;
				sender=strdup(sender);
			}
			if (sender == NULL)
			{
				perror("malloc");
				exit(1);
			}
			continue;
		case 'n':
			nosend=1;
			continue;
		default:
			usage();
		}
	}

	if (!txtfile && !mimefile)
		usage();

	if (txtfile && mimefile)
		usage();

	tmpfp=tmpfile();

	if (!tmpfp)
	{
		perror("tmpfile");
		exit(1);
	}

	rfcp=savemessage(tmpfp);

	if (fseek(tmpfp, 0L, SEEK_SET) < 0)
	{
		perror("fseek(tempfile)");
		exit(1);
	}

	read_headers(tmpfp);

	if (sender == NULL || *sender == 0)
		check_sender();

	check_dsn();
	check_recips();
#ifdef DbObj
	check_db();
#endif

	src=rfc2045src_init_fd(fileno(tmpfp));

	memset(&replyinfo, 0, sizeof(replyinfo));

	replyinfo.info.src=src;
	replyinfo.info.rfc2045partp=rfcp;
	replyinfo.info.voidarg=&replyinfo;

	replyinfo.info.write_func=mimeautoreply_write_func;

	replyinfo.info.writesig_func=mimeautoreply_writesig_func;

	replyinfo.info.myaddr_func=mimeautoreply_myaddr_func;

	replyinfo.info.replymode=replymode;
	replyinfo.info.replytoenvelope=replytoenvelope;
	replyinfo.info.donotquote=donotquote;

	replyinfo.info.replysalut=replysalut;
	replyinfo.info.forwarddescr="Forwarded message";
	replyinfo.info.mailinglists="";
	replyinfo.info.charset=charset;
	replyinfo.info.subject=subj;
	replyinfo.info.forwardsep=forwardsep;

	if (mimedsn && *mimedsn)
	{
		replyinfo.info.dsnfrom=mimedsn;
		replyinfo.info.replymode="replydsn";
	}

	if (mimefile)
	{
		if ((replyinfo.contentf=fopen(mimefile, "r")) == NULL)
		{
			perror(mimefile);
			exit(1);
		}

		{
			struct rfc2045 *rfcp=rfc2045_alloc();
			static const char mv[]="Mime-Version: 1.0\n";
			char buf[BUFSIZ];
			int l;
			const char *content_type;
			const char *content_transfer_encoding;
			const char *charset;

			rfc2045_parse(rfcp, mv, sizeof(mv)-1);

			while ((l=fread(buf, 1, sizeof(buf), replyinfo.contentf)
				) > 0)
			{
				rfc2045_parse(rfcp, buf, l);
			}

			if (l < 0 ||
			    fseek(replyinfo.contentf, 0L, SEEK_SET) < 0)
			{
				perror(mimefile);
				exit(1);
			}

			rfc2045_mimeinfo(rfcp, &content_type,
					 &content_transfer_encoding,
					 &charset);

			if (strcasecmp(content_type, "text/plain"))
			{
				fprintf(stderr,
					"%s must specify text/plain MIME type\n",
					mimefile);
				exit(1);
			}
			{
				char *p=NULL;

				if (charset)
					p=libmail_u_convert_tobuf("",
								  charset,
								  libmail_u_ucs4_native,
								  NULL);

				if (!p)
				{
					fprintf(stderr, "Unknown charset in %s\n",
						mimefile);
					exit(1);
				}
				free(p);
				replyinfo.info.charset=strdup(charset);
			}
			rfc2045_free(rfcp);
		}
		replyinfo.info.content_set_charset=copy_headers;
		replyinfo.info.content_specify=copy_body;
	}
	else if (txtfile)
	{
		if ((replyinfo.contentf=fopen(txtfile, "r")) == NULL)
		{
			perror(mimefile);
			exit(1);
		}
		replyinfo.info.content_specify=copy_body;
	}

	if (replyinfo.contentf)
		fcntl(fileno(replyinfo.contentf), F_SETFD, FD_CLOEXEC);

	if (nosend)
		replyinfo.outf=stdout;
	else
	{
		replyinfo.outf=tmpfile();

		if (replyinfo.outf == NULL)
		{
			perror("tmpfile");
			exit(1);
		}
	}

	{
		struct header *h;

		for (h=extra_headers; h; h=h->next)
			fprintf(replyinfo.outf, "%s\n", h->buf);
	}
	fprintf(replyinfo.outf,
		"Precedence: junk\n"
		"Auto-Submitted: auto-replied\n");

	if (rfc2045_makereply(&replyinfo.info) < 0 ||
	    fflush(replyinfo.outf) < 0 || ferror(replyinfo.outf) ||
	    (!nosend &&
	     (
	      fseek(replyinfo.outf, 0L, SEEK_SET) < 0 ||
	      (close(0), dup(fileno(replyinfo.outf))) < 0)
	     ))
	{
		perror("tempfile");
		exit(1);
	}
	fclose(replyinfo.outf);
	fcntl(0, F_SETFD, 0);

	rfc2045_free(rfcp);
	rfc2045src_deinit(src);

	if (!nosend)
		opensendmail(argn, argc, argv);
	return (0);
}
예제 #9
0
void CursesFileReq::doresized()
{
	int w=getWidth();

	int c=filenameField.getCol();

	filenameField.setWidth(c > w ? 1: w-c);

	// If too narrow fo the full directory name, truncate it.

	c=directoryName.getCol();

	size_t dls=c < w ? w-c:1;

	std::vector<unicode_char> directoryW;

	mail::iconvert::convert(currentDir, unicode_default_chset(),
				directoryW);

	size_t directoryW_size;

	{
		widecharbuf wc;

		wc.init_unicode(directoryW.begin(), directoryW.end());
		wc.expandtabs(0);

		wc.tounicode(directoryW);

		directoryW_size=wc.wcwidth(0);
	}

	if (directoryW_size > dls)
	{
		std::vector<unicode_char>::iterator b, e, c, lastSlash;

		b=directoryW.begin();
		e=directoryW.end();

		lastSlash=b;

		for (c=b; c != e; )
		{
			if (*c++ == '/')
				lastSlash=c;
		}

		std::vector<unicode_char> replVector;

		replVector.push_back('/');
		replVector.push_back('.');
		replVector.push_back('.');
		replVector.push_back('.');
		replVector.push_back('/');

		replVector.insert(replVector.end(), lastSlash, e);

		size_t suffixSize;

		{
			widecharbuf wc;

			wc.init_unicode(replVector.begin(), replVector.end());

			suffixSize=wc.wcwidth(0);
		}

		if (suffixSize < dls)
		{
			widecharbuf wc;

			wc.init_unicode(directoryW.begin(), lastSlash);

			directoryW=wc.get_unicode_truncated(dls-suffixSize, 0)
				.first;

			lastSlash=b=directoryW.begin();
			e=directoryW.end();

			for (c=b; c != e; ++c)
			{
				if (*c == '/')
					lastSlash=c;
			}

		}
		else
		{
			lastSlash=directoryW.begin();
		}

		directoryW.erase(lastSlash, directoryW.end());

		directoryW.insert(directoryW.end(),
				  replVector.begin(), replVector.end());
	}

	directoryName.setText(mail::iconvert::convert(directoryW,
						      unicode_default_chset()));
}
예제 #10
0
bool CursesMessageDisplay::processKeyInFocus(const Curses::Key &key)
{
	CursesMessage *messageInfo=messageInfoPtr;

	if (!messageInfo)
		return false;

	if (key == key.ENTER)
	{
		size_t row;
		size_t col;
		std::string url;

		if (!messageInfo->getCurrentLink(row, col, url))
			return true;


		if (url.substr(0, 7) == "mailto:")
		{
			if (myMessage::checkInterrupted(false) &&
			    (messageInfo=messageInfoPtr) != NULL)
				myMessage::newMessage(messageInfo->myfolder
						      ->getFolder(),
						      messageInfo->myfolder
						      ->getServer(),
						      url.substr(7));
			return true;
		}


		std::string handler;

		size_t p=url.find(':');

		if (p != std::string::npos)
		{
			handler=myServer::getConfigDir() + "/"
				+ url.substr(0, p) + ".handler";

			if (access(handler.c_str(), X_OK))
			{
				handler=FILTERDIR "/"
					+ url.substr(0, p) + ".handler";

				if (access(handler.c_str(), X_OK))
					handler="";
			}
		}

		if (handler.size() == 0)
		{
			statusBar->clearstatus();
			statusBar->
				status(Gettext(_("Cannot find handler for %1%"))
				       << url);
			statusBar->beepError();
			return true;
		}

		pid_t pp=fork();

		if (pp < 0)
		{
			statusBar->clearstatus();
			statusBar->status(strerror(errno));
			statusBar->beepError();
			return true;
		}

		if (pp == 0)
		{
			close(1);
			open("/dev/null", O_WRONLY);
			dup2(1, 2);
			dup2(1, 0);

			execl(handler.c_str(), handler.c_str(), url.c_str(),
			      (char *)NULL);

			exit(1);
		}

		pid_t p2;
		int waitstat;

		while ((p2=wait(&waitstat)) != pp)
		{
			if (p2 < 0 && errno != EINTR)
				break;
		}

		if (p2 == pp && WIFEXITED(waitstat) &&
		    WEXITSTATUS(waitstat) == 0)
		{
			statusBar->status(_("Started external handler."));
			return true;
		}

		statusBar->clearstatus();
		statusBar->status(_("External handler terminated with a non-zero exit code."),
				  statusBar->SYSERROR);
		return true;
	}

	if (key == key_TAKEADDR)
	{
		mail::envelope *e=messageInfo->getEnvelope();

		std::vector<mail::address> addrList;

		addrList.reserve(e->from.size() +
				 e->to.size() +
				 e->cc.size() +
				 e->bcc.size() +
				 e->sender.size() +
				 e->replyto.size());

		addrList.insert(addrList.end(),
				e->from.begin(),
				e->from.end());

		addrList.insert(addrList.end(),
				e->to.begin(),
				e->to.end());

		addrList.insert(addrList.end(),
				e->cc.begin(),
				e->cc.end());

		addrList.insert(addrList.end(),
				e->bcc.begin(),
				e->bcc.end());

		addrList.insert(addrList.end(),
				e->sender.begin(),
				e->sender.end());

		addrList.insert(addrList.end(),
				e->replyto.begin(),
				e->replyto.end());

		AddressBook::take(addrList);
		return true;
	}
	if (key == key_FOLDERINDEX ||
	    key == key_LESSTHAN)
	{
		keepgoing=false;
		myServer::nextScreen=&folderIndexScreen;
		myServer::nextScreenArg=messageInfo->myfolder;
		return true;
	}


	if (key == key_DELETE)
		messageInfo->myfolder->markDeleted( messageInfo->messagesortednum,
						    true, false);

	if (key == key_UNDELETE)
		messageInfo->myfolder->markDeleted( messageInfo->messagesortednum,
						    false, false);

	if (key == key_NEXTMESSAGE ||
	    key == key_DELETE ||
	    key == key_UNDELETE)
	{
		size_t dummy;

		if (messageInfo->myfolder->getNextMessage(dummy))
		{
			Curses::keepgoing=false;
			myServer::nextScreen= &goNextMessage;
			myServer::nextScreenArg=messageInfo->myfolder;
			return true;
		}
		return true;
	}

	if (key == key_PREVMESSAGE)
	{
		size_t dummy;

		if (messageInfo->myfolder->getPrevMessage(dummy))
		{
			Curses::keepgoing=false;
			myServer::nextScreen= &goPrevMessage;
			myServer::nextScreenArg=messageInfo->myfolder;
		}
		return true;
	}

	if (key == ' ' || key == Key::RIGHT ||
	    key == Key::PGDN || key == Key::DOWN)
	{
		if ((key == Key::DOWN || key == Key::RIGHT) &&
		    messageInfo->nextLink())
			return true; // Went to next link instead

		size_t nLines=messageInfo->nLines();
		size_t h=getHeight();

		size_t lastLine= nLines > h ? nLines-h:0;

		size_t firstLineSaved=getFirstLineShown();

		if (key == Key::DOWN || key == Key::RIGHT)
			setFirstLineShown(getFirstLineShown()+1);
		else
			setFirstLineShown(getFirstLineShown()+h);

		if (getFirstLineShown() > lastLine)
			setFirstLineShown(lastLine);

		if (firstLineSaved == getFirstLineShown() && key == ' ')
		{
			size_t dummy;

			if (messageInfo->myfolder->
			    getNextUnreadMessage(dummy))
			{
				Curses::keepgoing=false;
				myServer::nextScreen= &goNextUnreadMessage;
				myServer::nextScreenArg=messageInfo->myfolder;
				return true;
			}

			statusBar->clearstatus();
			statusBar->status(Gettext(_("No more unread mail in %1%"))
					  << messageInfo->myfolder
					  ->getFolder()->getName());
			return true;
		}

		folderUpdated();
		draw2();
		messageInfo->toLastLink();
		return true;
	}

	if (key == Key::LEFT || key == Key::PGUP || key == Key::UP)
	{
		if (key != Key::PGUP && messageInfo->prevLink())
			return true;

		size_t h=key != Key::PGUP ? 1:getHeight();

		setFirstLineShown(getFirstLineShown() < h ? 0:
				  getFirstLineShown()-h);
		folderUpdated();
		draw2();
		return true;
	}

	if (key == key_VIEWATT)
	{
		Curses::keepgoing=false;
		myServer::nextScreen=showAttachments;
		myServer::nextScreenArg=messageInfo;
		return true;
	}

	if (key == key_SAVE)
	{
		std::string filename;

		{
			SaveDialog save_dialog(filename);

			save_dialog.requestFocus();
			myServer::eventloop();

			filename=save_dialog;
			mainScreen->erase();
		}
		mainScreen->draw();
		requestFocus();

		if (messageInfoPtr.isDestroyed() || filename == "")
			return true;

		CursesAttachmentDisplay::downloadTo(messageInfoPtr,
						    messageInfoPtr->shownMimeId
						    != ""
						    ?
						    messageInfoPtr->structure
						    .find(messageInfoPtr->
							  shownMimeId)
						    :NULL,
						    filename);
		return true;
	}


	if (key == key_BOUNCE)
	{
		if (messageInfo->shownMimeId.size())
		{
			statusBar->clearstatus();
			statusBar->status(_("Cannot forward only an attachment, just the whole message."));
			statusBar->beepError();
			return true;
		}

		mail::smtpInfo sendInfo;

		std::string from;
		std::string replyto;
		std::string fcc;
		std::string customheaders;

		if (!myMessage::getDefaultHeaders(messageInfo->myfolder
						  ->getFolder(),
						  messageInfo->myfolder
						  ->getServer(),
						  from, replyto, fcc,
						  customheaders))
		{
			return true;
		}

		{
			std::vector<mail::address> addrList;
			size_t errIndex;

			if (mail::address::fromString(from, addrList,
						      errIndex)
			    && addrList.size() > 0)
				sendInfo.sender=addrList[0].getAddr();
		}

		mail::ptr<myFolder> folderPtr=messageInfo->myfolder;

		if (!CursesMessage::getBounceTo(sendInfo)
		    || !CursesMessage::getSendInfo(Gettext(_("Blind-forward message to %1% address(es)? (Y/N) "))
						   << sendInfo.recipients
						   .size(), "",
						   sendInfo, NULL))
			return true;

		disconnectCallbackStub disconnectStub;
		myServer::Callback sendCallback;

		mail::account *smtpServer;
		mail::folder *folder=
			CursesMessage::getSendFolder(sendInfo, smtpServer,
						     NULL,
						     disconnectStub);

		if (!folder)
			return true;

		if (folderPtr.isDestroyed() || messageInfoPtr.isDestroyed())
		{
			delete folder;
			if (smtpServer)
				delete smtpServer;
			return true;
		}

		try {
			messageInfo->copyContentsTo(folder, sendCallback);

			bool rc=myServer::eventloop(sendCallback);

			delete folder;
			folder=NULL;

			if (smtpServer)
			{
				if (rc)
				{
					myServer::Callback disconnectCallback;

					disconnectCallback.noreport=true;

					smtpServer->logout(disconnectCallback);
					myServer::
						eventloop(disconnectCallback);
				}

				delete smtpServer;
				smtpServer=NULL;
			}
			

		} catch (...) {

			if (folder)
				delete folder;
			if (smtpServer)
				delete smtpServer;
			LIBMAIL_THROW(LIBMAIL_THROW_EMPTY);
		}

		return true;
	}

	if (key == key_REPLY)
	{
		mail::ptr<myFolder> folder=messageInfo->myfolder;

		if (myMessage::checkInterrupted() &&
		    !folder.isDestroyed() &&
		    !messageInfoPtr.isDestroyed())
			messageInfo->reply();
		return true;
	}

	if (key == key_FWD)
	{
		mail::ptr<myFolder> folder=messageInfo->myfolder;

		if (myMessage::checkInterrupted() &&
		    !folder.isDestroyed() &&
		    !messageInfoPtr.isDestroyed())
			messageInfo->forward();
		return true;
	}

	if (key == key_HEADERS)
	{
		erase();
		messageInfo->fullEnvelopeHeaders=
			!messageInfo->fullEnvelopeHeaders;
		setFirstLineShown(0);
		messageInfo->beginReformat(getWidth());
		folderUpdated();
		return true;
	}

	if (key == key_PRINT)
	{
		mail::ptr<CursesMessage> ptr=messageInfo;
		int pipefd[2];
		pid_t pid1;

		myServer::promptInfo
			printPrompt(_("Print to: "));

		if (printCommand.size() == 0)
			printCommand="lpr";

		printPrompt=myServer::prompt(printPrompt
					     .initialValue(printCommand));

		if (printPrompt.abortflag || ptr.isDestroyed())
			return true;

		std::vector<const char *> args;

		{
			const char *p=getenv("SHELL");

			if (!p || !*p)
				p="/bin/sh";

			args.push_back(p);
		}

		args.push_back("-c");

		printCommand=printPrompt;

		args.push_back(printCommand.c_str());
		args.push_back(0);

		//
		// Fork a child process which writes the text image of the
		// message to a pipe.
		//
		// The parent process runs the print command, piping the text
		// into it.

		signal(SIGCHLD, SIG_DFL);

		if (pipe(pipefd) < 0)
		{
			statusBar->clearstatus();
			statusBar->status(strerror(errno));
			statusBar->beepError();
			return true;
		}

		if ((pid1=fork()) == 0)
		{
			FILE *fp;

			// First child exits, the second child generates the
			// text.

			if (fork())
				exit(0);
			signal(SIGPIPE, SIG_DFL);
			close(pipefd[0]);

			fp=fdopen(pipefd[1], "w");
			if (fp)
			{
				size_t nLines=messageInfo->nLines();
				size_t i;
				std::vector<std::pair<textAttributes, std::string> > line;

				std::vector<std::pair<textAttributes, std::string> >
					::iterator b, e;

				for (i=0; i<nLines; i++)
				{
					messageInfo->getLineImage(i, line);

					for (b=line.begin(), e=line.end();
					     b != e; ++b)
					{
						fprintf(fp, "%s",
							b->second.c_str());
					}
					fprintf(fp, "\n");
				}
				fflush(fp);
			}
			exit(0);
		}

		// Wait for the first child to exit.

		if (pid1 < 0)
		{
			close(pipefd[0]);
			close(pipefd[1]);
			statusBar->clearstatus();
			statusBar->status(strerror(errno));
			statusBar->beepError();
			return true;
		}

		close(pipefd[1]);

		while (wait(NULL) != pid1)
			;

		Curses::runCommand(args, pipefd[0], "");
		close(pipefd[0]);
		return true;
	}

	if (key == key_ROT13)
	{
		erase();
		messageInfo->rot13=!messageInfo->rot13;
		setFirstLineShown(0);
		messageInfo->beginReformat(getWidth());
		folderUpdated();
		return true;
	}

	if ((key == key_UNENCRYPT) &&
	    (messageInfo->isSigned() ||
	     messageInfo->isEncrypted()) &&
	    GPG::gpg.gpg_installed())
	{
		mail::ptr<CursesMessage> ptr=messageInfo;
		std::string passphrase;
		std::vector<std::string> options;
		bool wasEncrypted=messageInfo->isEncrypted();

		if (wasEncrypted)
		{
			if (!PasswordList::passwordList.check("decrypt:",
							      passphrase))
			{

				myServer::promptInfo
					passPrompt(_("Passphrase (if"
						     " required): "));

				passPrompt=myServer::prompt(passPrompt
							    .password());

				if (passPrompt.abortflag || ptr.isDestroyed())
					return true;

				passphrase=passPrompt;
			}
		}

		std::string::iterator b=GPG::gpg.extraDecryptVerifyOptions.begin();

		while (b != GPG::gpg.extraDecryptVerifyOptions.end())
		{
			if (unicode_isspace((unsigned char)*b))
			{
				b++;
				continue;
			}

			std::string::iterator s=b;

			while (b != GPG::gpg.extraDecryptVerifyOptions.end())
			{
				if (unicode_isspace((unsigned char)*b))
					break;
				b++;
			}

			options.push_back(std::string(s, b));
		}

		bool decryptFailed;

		if (messageInfo->decrypt(passphrase, options, decryptFailed))
		{
			if (wasEncrypted && !decryptFailed)
				PasswordList::passwordList
					.save("decrypt:", passphrase);

			erase();
			setFirstLineShown(0);
			messageInfo->beginReformat(getWidth());
			folderUpdated();

			if (wasEncrypted && decryptFailed)
			{
				statusBar->clearstatus();
				statusBar->status(_("ERROR: Decryption failed,"
						    " passphrase forgotten."));
				statusBar->beepError();
			}
		}

		return true;
	}
	
	if (key == key_MSGSEARCH)
	{
		mail::ptr<CursesMessage> ptr=messageInfo;

		myServer::promptInfo searchPrompt(_("Search: "));

		searchPrompt=myServer::prompt(searchPrompt
					      .initialValue(searchString));

		if (searchPrompt.abortflag || ptr.isDestroyed())
			return true;

		searchString=searchPrompt;

		if (searchString.size() == 0)
			return true;

		mail::Search searchEngine;

		if (!searchEngine.setString(searchString,
					    unicode_default_chset()))
		{
			statusBar->clearstatus();
			statusBar->status(strerror(errno));
			statusBar->beepError();
			return true;
		}

		searchEngine.reset();

		statusBar->clearstatus();
		statusBar->status(_("Searching..."));
		statusBar->flush();

		size_t n=messageInfo->nLines();

		std::vector<std::pair<textAttributes, std::string> > line;

		while (firstLineToSearch < n)
		{
			messageInfo->getLineImage(firstLineToSearch, line);

			std::string s;

			std::vector<std::pair<textAttributes, std::string> >
				::iterator b, e;

			for (b=line.begin(), e=line.end(); b != e; ++b)
				s += Gettext::toutf8(b->second);

			unicode_char *uc;
			size_t ucsize;

			if (unicode_convert_tou_tobuf(s.c_str(),
							s.size(),
							"utf-8",
							&uc,
							&ucsize,
							NULL))
			{
				statusBar->clearstatus();
				statusBar->status(strerror(errno));
				statusBar->beepError();
				return true;
			}

			if (ucsize == 0)
			{
				free(uc);
				++firstLineToSearch;
				continue;
			}

			size_t i;

			for (i=0; i<ucsize; ++i)
			{
				searchEngine << uc[i];
			}
			free(uc);
			searchEngine << (unicode_char)' '; // EOL

			if (searchEngine)
			{
				size_t nLines=messageInfo->nLines();
				size_t h=getHeight();
				size_t lastLine= nLines > h ? nLines-h:0;

				size_t foundAt=firstLineToSearch;

				size_t n=foundAt > 0 ? foundAt-1:0;

				if (n > lastLine)
					n=lastLine;

				setFirstLineShown(n);
				firstLineToSearch=foundAt+1;

				statusBar->clearstatus();
				statusBar->status(Gettext(_("Text located,"
							    " displayed on"
							    " line #%1%"))
						  << (firstLineToSearch-n));
				draw();
				return true;
			}
			++firstLineToSearch;
		}
		statusBar->clearstatus();
		statusBar->status(_("Not found."));
		return true;
	}

	if (key.fkey())
	{
		std::string local_cmd;

		if (!CursesIndexDisplay::FilterMessageCallback
		    ::getFilterCmd(key.fkeynum(), local_cmd))
			return true;

		CursesIndexDisplay::FilterMessageCallback cb(local_cmd);

		std::vector<size_t> msgvec;

		msgvec.push_back(messageInfo->myfolder->getServerIndex
				 (messageInfo->myfolder->getCurrentMessage()));

		messageInfo->myfolder->getServer()
			->server->readMessageContent(msgvec, true,
						     mail::readBoth, cb);

		if (myServer::eventloop(cb))
		{
			cb.finish();

			if (myServer::nextScreen)
				return true;

			if (cb.errmsg.size())
			{
				statusBar->clearstatus();
				statusBar->status(cb.errmsg);
				statusBar->beepError();
			}
		}
		return true;
	}
	return false;
}
예제 #11
0
std::string Gettext::fromutf8(std::string str)
{
    return unicode::iconvert::convert(str, "utf-8",
                                      unicode_default_chset());
}
예제 #12
0
std::string Gettext::toutf8(std::string str)
{
    return unicode::iconvert::convert(str, unicode_default_chset(),
                                      "utf-8");
}