示例#1
0
/*------------------------------------------------------------------------------*\
	FetchOwnFQDN()
		-	fetches hostname and domainname from network settings and build FQDN 
			from that.
\*------------------------------------------------------------------------------*/
void BmRoster::FetchOwnFQDN() {
	BmString buffer;
	Regexx rx;
#ifdef BEAM_FOR_BONE
	FetchFile( "/etc/hostname", mOwnFQDN);
	mOwnFQDN.RemoveSet( " \n\r\t");
	if (!mOwnFQDN.Length())
		mOwnFQDN = "bepc";
	FetchFile( "/etc/resolv.conf", buffer);
	if (rx.exec( buffer, "DOMAIN\\s*(\\S*)", Regexx::nocase)
	&& rx.match[0].atom[0].Length())
		mOwnFQDN << "." << rx.match[0].atom[0];
	else
		mOwnFQDN << "." << time( NULL) << ".fake";
#else
	BPath path;
	if (find_directory( B_COMMON_SETTINGS_DIRECTORY, &path) == B_OK) {
		FetchFile( BmString(path.Path())<<"/network", buffer);
		if (rx.exec( buffer, "HOSTNAME\\s*=[ \\t]*(\\S*)", Regexx::nocase)) {
			mOwnFQDN = rx.match[0].atom[0];
			if (!mOwnFQDN.Length())
				mOwnFQDN = "bepc";
			if (rx.exec( buffer, "DNS_DOMAIN\\s*=[ \\t]*(\\S*)", Regexx::nocase)
			&& rx.match[0].atom[0].Length())
				mOwnFQDN << "." << rx.match[0].atom[0];
			else
				mOwnFQDN << "." << time( NULL) << ".fake";
		}
	}
#endif
	if (!mOwnFQDN.Length())
		mOwnFQDN << "bepc." << time( NULL) << ".fake";
	mOwnFQDN.RemoveSet( "\r\n");
}
示例#2
0
/*------------------------------------------------------------------------------*\
	StateConnect()
		-	Initiates network-connection to POP-server
\*------------------------------------------------------------------------------*/
void BmPopper::StateConnect() {
	BNetAddress addr;
	if (addr.SetTo( mPopAccount->Server().String(),
						 mPopAccount->PortNr()) != B_OK) {
		BmString s = BmString("Could not determine address of POP-Server ")
							<< mPopAccount->Server();
		throw BM_network_error( s);
	}
	if (!Connect( &addr)) {
		BmString s = BmString("Could not connect to POP-Server ")
							<< mPopAccount->Server()
						  	<< "\n\bError:\n\t" << mErrorString;
		throw BM_network_error( s);
	}
	BmString encryptionType = mPopAccount->EncryptionType();
	if (TheNetEndpointRoster->SupportsEncryption()
	&& (encryptionType.ICompare(BmPopAccount::ENCR_TLS) == 0
		|| encryptionType.ICompare(BmPopAccount::ENCR_SSL) == 0)) {
		// straight TLS or SSL, we start the encryption layer:
		if (!StartEncryption(encryptionType.String()))
			return;
	}
	// accept server greeting (either encrypted or unencrypted):
	CheckForPositiveAnswer();
	Regexx rx;
	if (rx.exec( StatusText(), "(<.+?>)\\s*$", Regexx::newline)) {
		mServerTimestamp = rx.match[0];
	}
}
示例#3
0
std::vector<std::string>
regexx::splitex(const std::string& _regex, const std::string& _str)
{
  std::vector<std::string> v;
  Regexx rxx;
  rxx.expr(_regex);
  rxx.str(_str);
  v.reserve(rxx.exec());
  std::vector<RegexxMatch>::const_iterator i;
  std::string::size_type lastpos = 0;
  for(i = rxx.match.begin(); i != rxx.match.end(); i++) {
    v.push_back(_str.substr(lastpos,i->start()-lastpos));
    lastpos = i->start()+i->length();
  }
  v.push_back(_str.substr(lastpos,i->start()));
  return v;
}
示例#4
0
/*------------------------------------------------------------------------------*\
	Mail( mail)
		-	announces the given mail to the server
\*------------------------------------------------------------------------------*/
void BmSmtp::Mail( BmMail* mail) {
	BmString sender = mail->Header()->DetermineSender();
	Regexx rx;
	if (!rx.exec( sender, "@\\w+")) {
		// no domain part within sender-address, we add our current domain:
		if (sender.FindFirst("@") == B_ERROR)
			sender << "@";
		BmString fqdn = mSmtpAccount->DomainToAnnounce();
		sender << OwnDomain( fqdn);
	}
	BmString cmd = BmString("MAIL from:<") << sender <<">";
	if (mServerMayHaveSizeLimit) {
		int32 mailSize = mail->RawText().Length();
		cmd << " SIZE=" << mailSize;
	}
	SendCommand( cmd);
	CheckForPositiveAnswer();
}
示例#5
0
/*------------------------------------------------------------------------------*\
	StateHelo()
		-	Sends greeting to server and checks result
		-	EHLO is tried first, aiming to find out more about server
			capabilities; if that fails, HELO is used
		-	if EHLO succeeds, info about the server-capabilities are extracted
			from the answer
\*------------------------------------------------------------------------------*/
void BmSmtp::StateHelo() {
	BmString domain = mSmtpAccount->DomainToAnnounce();
	if (!domain.Length())
		domain = BeamRoster->OwnFQDN();
	BmString cmd = BmString("EHLO ") << domain;
	SendCommand( cmd);
	try {
		CheckForPositiveAnswer();
		Regexx rx;
		if (rx.exec( StatusText(), "^\\d\\d\\d.SIZE\\b", Regexx::newline)) {
			mServerMayHaveSizeLimit = true;
		}
		if (rx.exec( StatusText(), "^\\d\\d\\d.DSN\\b", Regexx::newline)) {
			mServerSupportsDSN = true;
		}
		if (rx.exec(
			StatusText(), "^\\d\\d\\d.AUTH\\s+(.*?)$", Regexx::newline
		)) {
			mSupportedAuthTypes = rx.match[0].atom[0];
		} else if (rx.exec(
			StatusText(), "^\\d\\d\\d.AUTH\\s*=\\s*(.*?)$", Regexx::newline
		)) {
			mSupportedAuthTypes = rx.match[0].atom[0];
		}
		if (rx.exec( StatusText(), "^\\d\\d\\d.STARTTLS\\b", Regexx::newline)) {
			mServerSupportsTLS = true;
		}
	} catch(...) {
		cmd = BmString("HELO ") << domain;
		SendCommand( cmd);
		CheckForPositiveAnswer();
	}
}
示例#6
0
/*------------------------------------------------------------------------------*\
	StateCapa()
		-	asks server for its capabilities
\*------------------------------------------------------------------------------*/
void BmPopper::StateCapa() {
	BmString cmd("CAPA");
	SendCommand( cmd);
	try {
		CheckForPositiveAnswer( 16384, true);
							// we expect a multiline string as answer
		Regexx rx;
		if (rx.exec(
			mAnswerText, "^\\s*SASL\\s+(.*?)$", Regexx::newline
		)) {
			mSupportedAuthTypes = rx.match[0].atom[0];
		} else if (rx.exec(
			mAnswerText, "^\\s*AUTH\\s+(.*?)$", Regexx::newline
		)) {
			mSupportedAuthTypes = rx.match[0].atom[0];
		}
		if (rx.exec( mAnswerText, "^\\s*STLS\\b", Regexx::newline))
			mServerSupportsTLS = true;
		else
			mServerSupportsTLS = false;
	} catch(...) {
	}
}
示例#7
0
int main()
{
  Regexx rxx;

  try {

    // 1 - Replacing strings with atom substitution:
    
    std::cout << "1: ";
    std::cout << rxx.replace("I love expensive software!","expensive (soft[a-z]*)",
			"free %0");
    std::cout << std::endl;


    // 2 - Atom retrieving:

    std::cout << "2: ";
    rxx.exec("http://distro.conectiva.com/projetos/32/","http://([-1-9a-zA-Z\\.]*)/");
    if(rxx.match.size() > 0 && rxx.match[0].atom.size() > 0)
      std::cout << "Regexx's host is " << rxx.match[0].atom[0] << "." << std::endl;
    else
      std::cout << "Oops, no hosts found!" << std::endl;


    // 3 - Patern matching:

    std::cout << "3: ";
    if(rxx.exec("*****@*****.**",".+@gnu\\.org$"))
      std::cout << "Yeah! It's from gnu.org!" << std::endl;
    else
      std::cout << "No, it's not from gnu.org." << std::endl;


    // 4 - Counting occurrences:

    std::cout << "4: ";
    std::cout << "There are "
	 << rxx.exec("There are n 'a's in this phrase.",
		     "a",Regexx::global|Regexx::nomatch)
	 << " 'a's in this phrase." << std::endl;


    // 5 - Removing HTML tags:

    std::cout << "5: ";
    std::cout << rxx.replace("<B>Please, <STRIKE>no</STRIKE> tags.</B>",
			"</?[a-z]+( [^>]*)*>", "",
			Regexx::global|Regexx::nocase|Regexx::study);
    std::cout << std::endl;


    // 6 - Customizing replaces

    std::cout << "6: ";
    std::cout << rxx.replacef("Turn your free software into expensive software.",
			 "free|expensive", invert, Regexx::global);
    std::cout << std::endl;


    // 7 - One-line regular expressions using constructors

    std::cout << "7: ";
    if(Regexx("Using constructor!","constructor"))
      std::cout << "I've found the 'constructor' word!" << std::endl;
    else
      std::cout << "I haven't found the 'constructor' word!" << std::endl;

  }
  catch(Regexx::CompileException &e) {
    std::cerr << e.message() << std::endl;
  }
  return 0;
}
示例#8
0
/*------------------------------------------------------------------------------*\
	StateCheck()
		-	looks for new mail
\*------------------------------------------------------------------------------*/
void BmPopper::StateCheck() {
	uint32 msgNum = 0;

	BmString cmd("STAT");
	SendCommand( cmd);
	if (!CheckForPositiveAnswer())
		return;
	Regexx rx;
	if (!rx.exec( StatusText(), "^\\+OK\\s+(\\d+)", Regexx::nocase))
		throw BM_network_error( "answer to STAT has unknown format");
	BmString numStr = rx.match[0].atom[0];
	mMsgCount = atoi(numStr.String());
	if (mMsgCount == 0) {
		UpdateMailStatus( 0, NULL, 0);
		// we remove all local UIDs, since none are listed on the server:
		BmString removedUids = mPopAccount->AdjustToCurrentServerUids( mMsgUIDs);
		BM_LOG2( BM_LogRecv, removedUids);
		return;									// no messages found, nothing more to do
	}

	// we try to fetch a list of unique message IDs from server:
	cmd = BmString("UIDL");
	SendCommand( cmd);
	try {
		// The UIDL-command may not be implemented by this server, so we
		// do not require a positive answer, we just hope for it:
		if (!CheckForPositiveAnswer( 16384, true))
			return;								// interrupted, we give up
		// ok, we've got the UIDL-listing, so we fetch it,
		// fetch UIDLs one per line and store them in array:
		int numLines = rx.exec( mAnswerText, "\\s*(\\d+)\\s+(.+?)\\s*$",
										Regexx::newline | Regexx::global);
		if (numLines < mMsgCount)
			throw BM_network_error(	BmString("answer to UIDL has unknown format"
														", too few lines matching"));
		for( int32 i=0; i<mMsgCount; ++i)
			mMsgUIDs.push_back( rx.match[i].atom[1]);
		// we remove local UIDs that are not listed on the server anymore:
		BmString removedUids = mPopAccount->AdjustToCurrentServerUids( mMsgUIDs);
		BM_LOG( BM_LogRecv, removedUids);
	} catch( BM_network_error& err) {
		// no UIDL-listing from server, we will have to get by without...
	}

	// compute total size of messages that are new to us:
	mNewMsgTotalSize = 0;
	mNewMsgCount = 0;
	mCleanupMsgs.clear();
	cmd = "LIST";
	SendCommand( cmd);
	if (!CheckForPositiveAnswer( 16384, true))
		return;
	vector<BmString> listAnswerVect;
	split( "\r\n", mAnswerText, listAnswerVect);
	uint32 count = mMsgCount;
	if (count != listAnswerVect.size()) {
		BM_LOG( BM_LogRecv,
				  BmString("Strange: server indicated ")<< mMsgCount
						<< " mails, but LIST received " << listAnswerVect.size()
						<< " lines!");
		if (count > listAnswerVect.size())
			count = listAnswerVect.size();
	}
	for( uint32 i=0; i<count; i++) {
		int32 msgSize;
		if (!mPopAccount->IsUIDDownloaded( mMsgUIDs[i])) {
			// msg is new (according to unknown UID)
			// fetch msgsize for message...
			Regexx rx;
			if (!rx.exec( listAnswerVect[i], "^\\s*(\\d+)\\s+(\\d+)\\s*$"))
				throw BM_network_error(
					BmString("answer to LIST has unknown format, msg ") << i+1
				);
			BmString msgNumStr = rx.match[0].atom[0];
			msgNum = atoi(msgNumStr.String());
			if (msgNum != i+1)
				throw BM_network_error(
					BmString("answer to LIST has unexpected msg-nr. ") << msgNum
						<< " in line " << i+1
				);
			BmString msgSizeStr = rx.match[0].atom[1];
			msgSize = atoi(msgSizeStr.String());
			// add msg-size to total:
			mNewMsgTotalSize += msgSize;
			mNewMsgSizes.push_back( msgSize);
			mNewMsgCount++;
		} else {
			// msg is old (according to known UID), we may have to remove it now:
			BmString log;
			bool shouldBeRemoved
				= mPopAccount->ShouldUIDBeDeletedFromServer(mMsgUIDs[i], log);
			BM_LOG2( BM_LogRecv, log);
			if (shouldBeRemoved) {
				// store msg-index-number for cleanup state
				mCleanupMsgs.push_back(i + 1);
			}
		}
	}
	if (mNewMsgCount == 0)
		UpdateMailStatus( 0, NULL, 0);
}
示例#9
0
/*------------------------------------------------------------------------------*\
	StateSendMails()
		-	sends the queued mails to the server (invokes MAIL, RCPT and
			DATA-commands)
		-	depending on the handling of Bcc-recipients, each mail is only sent to
			the server once (SpecialHeaderForEachBcc=false) or each mail is being
			sent once for the standard recipients (To, Cc) plus a personalized
			version for each Bcc-recipient (SpecialHeaderForEachBcc=true)
\*------------------------------------------------------------------------------*/
void BmSmtp::StateSendMails() {
	mMailCount = mQueuedRefVect.size();

	mMsgTotalSize = 0;
	vector<BmRef<BmMailRef> > mailRefs;
	BmRef<BmMail> mail;
	for( int32 i=0; i<mMailCount; ++i) {
		mailRefs.push_back(BmMailRef::CreateInstance( mQueuedRefVect[i]));
		if (mailRefs[i] && mailRefs[i]->IsValid())
			mMsgTotalSize += int32(mailRefs[i]->Size());
	}

	Regexx rx;
	mCurrMailNr = 1;
	for( int32 i=0; i<mMailCount; ++i, ++mCurrMailNr) {
		if (!mailRefs[i] || !mailRefs[i]->IsValid()) {
			BM_LOGERR( BmString("SendMails(): mail no. ") << i+1
								<< " can't be found, skipping it.");
			continue;
		}
		BmRef<BmMail> mail = BmMail::CreateInstance( mailRefs[i].Get());
		if (mail) {
			if (mail->InitCheck() != B_OK)
				mail->StartJobInThisThread( BmMail::BM_READ_MAIL_JOB);
			if (mail->InitCheck() != B_OK) {
				BM_LOGERR( BmString("SendMails(): mail no. ") << i+1
									<< " can't be read, skipping it.");
				continue;
			}
		}
		mCurrMailSize = mail->RawText().Length();

		BmString headerText = mail->HeaderText();
		if (!mail->Header()->IsFieldEmpty(BM_FIELD_RESENT_BCC)) {
			// remove RESENT-BCC-header from mailtext...
			headerText = rx.replace(
				headerText,
				"^Resent-Bcc:\\s*.+?\\r\\n(\\s+.*?\\r\\n)*",
				"", Regexx::newline
			);
		}
		if (!mail->Header()->IsFieldEmpty(BM_FIELD_BCC)) {
			// remove BCC-header from mailtext...
			headerText = rx.replace(
				headerText,
				"^Bcc:\\s*.+?\\r\\n(\\s+.*?\\r\\n)*",
				"", Regexx::newline
			);
		}

		try {
			BmRcptSet rcptSet;
			if (ThePrefs->GetBool("SpecialHeaderForEachBcc")) {
				if (HasStdRcpts( mail.Get(), rcptSet)) {
					Mail( mail.Get());
					Rcpt( rcptSet);
					Data( mail.Get(), headerText);
				}
				BccRcpt( mail.Get(), true, headerText);
			} else {
				Mail( mail.Get());
				if (HasStdRcpts( mail.Get(), rcptSet))
					Rcpt( rcptSet);
				BccRcpt( mail.Get(), false, headerText);
				Data( mail.Get(), headerText);
			}
			if (ShouldContinue()) {
				mail->MarkAs( BM_MAIL_STATUS_SENT);
				mail->ApplyOutboundFilters();
					// give filters a chance that check for 'Sent'-status...
			}
		} catch( BM_runtime_error &err) {
			// a problem occurred, we tell the user:
			BM_LOGERR( BmString("SendMails(): mail no. ") << i+1
								<< " couldn't be sent.\n\nError:\n" << err.what());
			mail->MarkAs( BM_MAIL_STATUS_ERROR);
				// mark mail as ERROR since it couldn't be sent
			SendCommand("RSET");
				// reset SMTP-state in order to start afresh with next mail
		}
	}
	mCurrMailSize = 0;
	mCurrMailNr = 0;
}