⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imapparser.hpp

📁 MIME解析的代码
💻 HPP
📖 第 1 页 / 共 5 页
字号:
//// VMime library (http://www.vmime.org)// Copyright (C) 2002-2008 Vincent Richard <vincent@vincent-richard.net>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of// the License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// General Public License for more details.//// You should have received a copy of the GNU General Public License along// with this program; if not, write to the Free Software Foundation, Inc.,// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.//// Linking this library statically or dynamically with other modules is making// a combined work based on this library.  Thus, the terms and conditions of// the GNU General Public License cover the whole combination.//#ifndef VMIME_NET_IMAP_IMAPPARSER_HPP_INCLUDED#define VMIME_NET_IMAP_IMAPPARSER_HPP_INCLUDED#include "vmime/base.hpp"#include "vmime/dateTime.hpp"#include "vmime/charset.hpp"#include "vmime/exception.hpp"#include "vmime/utility/smartPtr.hpp"#include "vmime/utility/stringUtils.hpp"#include "vmime/utility/progressListener.hpp"#include "vmime/utility/encoder/b64Encoder.hpp"#include "vmime/utility/encoder/qpEncoder.hpp"#include "vmime/platform.hpp"#include "vmime/net/timeoutHandler.hpp"#include "vmime/net/socket.hpp"#include "vmime/net/imap/IMAPTag.hpp"#include <vector>#include <stdexcept>//#define DEBUG_RESPONSE 1#if DEBUG_RESPONSE#   include <iostream>#endifnamespace vmime {namespace net {namespace imap {#if DEBUG_RESPONSE	static int IMAPParserDebugResponse_level = 0;	static std::vector <string> IMAPParserDebugResponse_stack;	class IMAPParserDebugResponse	{	public:		IMAPParserDebugResponse(const string& name, string& line, const string::size_type currentPos)			: m_name(name), m_line(line), m_pos(currentPos)		{			++IMAPParserDebugResponse_level;			IMAPParserDebugResponse_stack.push_back(name);			for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i)				std::cout << "  ";			std::cout << "ENTER(" << m_name << "), pos=" << m_pos;			std::cout << std::endl;			for (std::vector <string>::iterator it = IMAPParserDebugResponse_stack.begin() ;			     it != IMAPParserDebugResponse_stack.end() ; ++it)			{				std::cout << "> " << *it << " ";			}			std::cout << std::endl;			std::cout << string(m_line.begin() + (m_pos < 30 ? 0U : m_pos - 30),				m_line.begin() + std::min(m_line.length(), m_pos + 30)) << std::endl;			for (string::size_type i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i)				std::cout << " ";			std::cout << "^" << std::endl;		}		~IMAPParserDebugResponse()		{			for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i)				std::cout << "  ";			std::cout << "LEAVE(" << m_name << "), result=";			std::cout << (std::uncaught_exception() ? "FALSE" : "TRUE") << ", pos=" << m_pos;			std::cout << std::endl;			--IMAPParserDebugResponse_level;			IMAPParserDebugResponse_stack.pop_back();		}	private:		const string& m_name;		string& m_line;		string::size_type m_pos;	};	#define DEBUG_ENTER_COMPONENT(x) \		IMAPParserDebugResponse dbg(x, line, *currentPos)	#define DEBUG_FOUND(x, y) \		std::cout << "FOUND: " << x << ": " << y << std::endl;#else	#define DEBUG_ENTER_COMPONENT(x)	#define DEBUG_FOUND(x, y)#endifclass IMAPParser : public object{public:	IMAPParser(weak_ref <IMAPTag> tag, weak_ref <socket> sok, weak_ref <timeoutHandler> _timeoutHandler)		: m_tag(tag), m_socket(sok), m_progress(NULL), m_strict(false),		  m_literalHandler(NULL), m_timeoutHandler(_timeoutHandler)	{	}	ref <const IMAPTag> getTag() const	{		return m_tag.acquire();	}	void setSocket(ref <socket> sok)	{		m_socket = sok;	}	/** Set whether we operate in strict mode (this may not work	  * with some servers which are not fully standard-compliant).	  *	  * @param strict true to operate in strict mode, or false	  * to operate in default, relaxed mode	  */	void setStrict(const bool strict)	{		m_strict = strict;	}	/** Return true if the parser operates in strict mode, or	  * false otherwise.	  *	  * @return true if we are in strict mode, false otherwise	  */	bool isStrict() const	{		return m_strict;	}	const string lastLine() const	{		// Remove blanks and new lines at the end of the line.		string line(m_lastLine);		string::const_iterator it = line.end();		int count = 0;		while (it != line.begin())		{			const unsigned char c = *(it - 1);			if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))				break;			++count;			--it;		}		line.resize(line.length() - count);		return (line);	}	//	// literalHandler : literal content handler	//	class component;	class literalHandler	{	public:		virtual ~literalHandler() { }		// Abstract target class		class target		{		protected:			target(utility::progressListener* progress) : m_progress(progress) {}			target(const target&) {}		public:			virtual ~target() { }			utility::progressListener* progressListener() { return (m_progress); }			virtual void putData(const string& chunk) = 0;		private:			utility::progressListener* m_progress;		};		// Target: put in a string		class targetString : public target		{		public:			targetString(utility::progressListener* progress, vmime::string& str)				: target(progress), m_string(str) { }			const vmime::string& string() const { return (m_string); }			vmime::string& string() { return (m_string); }			void putData(const vmime::string& chunk)			{				m_string += chunk;			}		private:			vmime::string& m_string;		};		// Target: redirect to an output stream		class targetStream : public target		{		public:			targetStream(utility::progressListener* progress, utility::outputStream& stream)				: target(progress), m_stream(stream) { }			const utility::outputStream& stream() const { return (m_stream); }			utility::outputStream& stream() { return (m_stream); }			void putData(const string& chunk)			{				m_stream.write(chunk.data(), chunk.length());			}		private:			utility::outputStream& m_stream;		};		// Called when the parser needs to know what to do with a literal		//    . comp: the component in which we are at this moment		//    . data: data specific to the component (may not be used)		//		// Returns :		//    . == NULL to put the literal into the response		//    . != NULL to redirect the literal to the specified target		virtual target* targetFor(const component& comp, const int data) = 0;	};	//	// Base class for a terminal or a non-terminal	//	class component	{	public:		component() { }		virtual ~component() { }		virtual void go(IMAPParser& parser, string& line, string::size_type* currentPos) = 0;		const string makeResponseLine(const string& comp, const string& line,		                              const string::size_type pos)		{#if DEBUG_RESPONSE			if (pos > line.length())				std::cout << "WARNING: component::makeResponseLine(): pos > line.length()" << std::endl;#endif			string result(line.substr(0, pos));			result += "[^]";   // indicates current parser position			result += line.substr(pos, line.length());			if (!comp.empty()) result += " [" + comp + "]";			return (result);		}	};#define COMPONENT_ALIAS(parent, name) \	class name : public parent \	{ \		void go(IMAPParser& parser, string& line, string::size_type* currentPos) \		{ \			DEBUG_ENTER_COMPONENT(#name); \			parent::go(parser, line, currentPos); \		} \	}	//	// Parse one character	//	template <char C>	class one_char : public component	{	public:		void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos)		{			DEBUG_ENTER_COMPONENT(string("one_char <") + C + ">: current='" + ((*currentPos < line.length() ? line[*currentPos] : '?')) + "'");			const string::size_type pos = *currentPos;			if (pos < line.length() && line[pos] == C)				*currentPos = pos + 1;			else				throw exceptions::invalid_response("", makeResponseLine("", line, pos));		}	};	//	// SPACE  ::= <ASCII SP, space, 0x20>	//	class SPACE : public component	{	public:		void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos)		{			DEBUG_ENTER_COMPONENT("SPACE");			string::size_type pos = *currentPos;			while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t'))				++pos;			if (pos > *currentPos)				*currentPos = pos;			else				throw exceptions::invalid_response("", makeResponseLine("SPACE", line, pos));		}	};	//	// CR    ::= <ASCII CR, carriage return, 0x0D>	// LF    ::= <ASCII LF, line feed, 0x0A>	// CRLF  ::= CR LF	//	class CRLF : public component	{	public:		void go(IMAPParser& parser, string& line, string::size_type* currentPos)		{			DEBUG_ENTER_COMPONENT("CRLF");			string::size_type pos = *currentPos;			parser.check <SPACE>(line, &pos, true);			if (pos + 1 < line.length() &&			    line[pos] == 0x0d && line[pos + 1] == 0x0a)			{				*currentPos = pos + 2;			}			else			{				throw exceptions::invalid_response("", makeResponseLine("CRLF", line, pos));			}		}	};	//	// SPACE           ::= <ASCII SP, space, 0x20>	// CTL             ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f>	// CHAR            ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>	// ATOM_CHAR       ::= <any CHAR except atom_specials>	// atom_specials   ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials	// list_wildcards  ::= "%" / "*"	// quoted_specials ::= <"> / "\"	//	// tag             ::= 1*<any ATOM_CHAR except "+">    (named "xtag")	//	class xtag : public component	{	public:		void go(IMAPParser& parser, string& line, string::size_type* currentPos)		{			DEBUG_ENTER_COMPONENT("tag");			string::size_type pos = *currentPos;			bool end = false;			string tagString;			tagString.reserve(10);			while (!end && pos < line.length())			{				const unsigned char c = line[pos];				switch (c)				{				case '+':				case '(':				case ')':				case '{':				case 0x20:  // SPACE				case '%':   // list_wildcards				case '*':   // list_wildcards				case '"':   // quoted_specials				case '\\':  // quoted_specials					end = true;					break;				default:					if (c <= 0x1f || c >= 0x7f)						end = true;					else					{						tagString += c;						++pos;					}					break;				}			}			if (tagString == string(*parser.getTag()))			{				*currentPos = pos;			}			else			{				// Invalid tag				throw exceptions::invalid_response("", makeResponseLine("tag", line, pos));			}		}	};	//	// digit     ::= "0" / digit_nz	// digit_nz  ::= "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"	//	// number    ::= 1*digit	//               ;; Unsigned 32-bit integer	//               ;; (0 <= n < 4,294,967,296)	//	class number : public component	{	public:		number(const bool nonZero = false)			: m_nonZero(nonZero), m_value(0)		{		}		void go(IMAPParser& /* parser */, string& line, string::size_type* currentPos)		{			DEBUG_ENTER_COMPONENT("number");			string::size_type pos = *currentPos;			bool valid = true;			unsigned int val = 0;			while (valid && pos < line.length())			{				const char c = line[pos];				if (c >= '0' && c <= '9')				{					val = (val * 10) + (c - '0');					++pos;				}				else				{					valid = false;				}			}			// Check for non-null length (and for non-zero number)			if (!(m_nonZero && val == 0) && pos != *currentPos)			{				m_value = val;				*currentPos = pos;			}			else			{				throw exceptions::invalid_response("", makeResponseLine("number", line, pos));			}		}	private:		const bool m_nonZero;		unsigned int m_value;	public:		unsigned int value() const { return (m_value); }	};	// nz_number  ::= digit_nz *digit	//                ;; Non-zero unsigned 32-bit integer	//                ;; (0 < n < 4,294,967,296)	//	class nz_number : public number	{	public:		nz_number() : number(true)		{		}	};	//	// text       ::= 1*TEXT_CHAR	//	// CHAR       ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>	// TEXT_CHAR  ::= <any CHAR except CR and LF>	//	class text : public component	{	public:		text(bool allow8bits = false, const char except = 0)			: m_allow8bits(allow8bits), m_except(except)		{		}		void go(IMAPParser& parser, string& line, string::size_type* currentPos)		{			DEBUG_ENTER_COMPONENT("text");			string::size_type pos = *currentPos;			string::size_type len = 0;			if (m_allow8bits || !parser.isStrict())			{				const unsigned char except = m_except;				for (bool end = false ; !end && pos < line.length() ; )				{					const unsigned char c = line[pos];					if (c == 0x00 || c == 0x0d || c == 0x0a || c == except)					{						end = true;					}					else					{						++pos;						++len;					}				}			}			else			{				const unsigned char except = m_except;				for (bool end = false ; !end && pos < line.length() ; )				{					const unsigned char c = line[pos];					if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except)					{						end = true;					}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -