31 std::string folded(
const std::string & ) ;
32 std::string xnormalise(
const std::string & ) ;
33 std::string readLine( std::istream & ,
bool * =
nullptr ) ;
34 std::string readValue( std::istream & ,
const std::string & ,
bool * =
nullptr ) ;
35 std::string value(
const std::string & ) ;
36 std::string readFormat( std::istream & stream ,
bool * ) ;
37 void readEightBitFlag( std::istream & , Envelope & ) ;
38 void readFrom( std::istream & , Envelope & ) ;
39 void readFromAuthIn( std::istream & , Envelope & ) ;
40 void readFromAuthOut( std::istream & , Envelope & ) ;
41 void readToList( std::istream & , Envelope & ) ;
42 void readAuthentication( std::istream & , Envelope & ) ;
43 void readClientSocketAddress( std::istream & , Envelope & ) ;
44 void readClientSocketName( std::istream & , Envelope & ) ;
45 void readClientCertificate( std::istream & , Envelope & ) ;
46 void readEnd( std::istream & , Envelope & ) ;
52 namespace imp = GSmtp::EnvelopeImp ;
54 const char * crlf =
"\r\n" ;
56 std::streampos pos = stream.tellp() ;
57 if( pos < 0 || stream.fail() )
61 stream << x <<
"Content: " << (e.m_eight_bit==1?
"8bit":(e.m_eight_bit==0?
"7bit":
"unknown")) << crlf ;
62 stream << x <<
"From: " << e.m_from << crlf ;
63 stream << x <<
"ToCount: " << (e.m_to_local.size()+e.m_to_remote.size()) << crlf ;
65 auto to_p = e.m_to_local.begin() ;
66 for( ; to_p != e.m_to_local.end() ; ++to_p )
67 stream << x <<
"To-Local: " << *to_p << crlf ;
70 auto to_p = e.m_to_remote.begin() ;
71 for( ; to_p != e.m_to_remote.end() ; ++to_p )
72 stream << x <<
"To-Remote: " << *to_p << crlf ;
74 stream << x <<
"Authentication: " <<
G::Xtext::encode(e.m_authentication) << crlf ;
75 stream << x <<
"Client: " << e.m_client_socket_address << crlf ;
76 stream << x <<
"ClientCertificate: " << imp::folded(e.m_client_certificate) << crlf ;
77 stream << x <<
"MailFromAuthIn: " << imp::xnormalise(e.m_from_auth_in) << crlf ;
78 stream << x <<
"MailFromAuthOut: " << imp::xnormalise(e.m_from_auth_out) << crlf ;
79 stream << x <<
"End: 1" << crlf ;
81 return stream.fail() ? std::size_t(0U) :
static_cast<std::size_t
>( stream.tellp() - pos ) ;
94 out << line <<
"\r\n" ;
97 if( in.bad() || (in.fail()&&!in.eof()) )
99 in.clear( std::ios_base::eofbit ) ;
104 namespace imp = GSmtp::EnvelopeImp ;
105 std::streampos oldpos = stream.tellg() ;
106 std::string format = imp::readFormat( stream , &e.m_crlf ) ;
107 imp::readEightBitFlag( stream , e ) ;
108 imp::readFrom( stream , e ) ;
109 imp::readToList( stream , e ) ;
110 imp::readAuthentication( stream , e ) ;
111 imp::readClientSocketAddress( stream , e ) ;
114 imp::readClientCertificate( stream , e ) ;
115 imp::readFromAuthIn( stream , e ) ;
116 imp::readFromAuthOut( stream , e ) ;
120 imp::readClientSocketName( stream , e ) ;
121 imp::readClientCertificate( stream , e ) ;
123 imp::readEnd( stream , e ) ;
127 else if( stream.fail() && stream.eof() )
128 stream.clear( std::ios_base::eofbit ) ;
130 std::streampos newpos = stream.tellg() ;
131 if( newpos <= 0 || newpos < oldpos )
134 e.m_endpos =
static_cast<std::size_t
>(newpos-oldpos) ;
137std::string GSmtp::EnvelopeImp::folded(
const std::string & s_in )
139 std::string s = s_in ;
146std::string GSmtp::EnvelopeImp::xnormalise(
const std::string & s )
151std::string GSmtp::EnvelopeImp::readFormat( std::istream & stream ,
bool * crlf )
153 std::string format = readValue( stream ,
"Format" , crlf ) ;
155 throw Envelope::ReadError(
"unknown format id" , format ) ;
159void GSmtp::EnvelopeImp::readEightBitFlag( std::istream & stream , Envelope & e )
161 std::string content = readValue( stream ,
"Content" ) ;
162 e.m_eight_bit = content ==
"8bit" ? 1 : ( content ==
"7bit" ? 0 : -1 ) ;
165void GSmtp::EnvelopeImp::readFrom( std::istream & stream , Envelope & e )
167 e.m_from = readValue( stream ,
"From" ) ;
168 G_DEBUG(
"GSmtp::EnvelopeImp::readFrom: from \"" << e.m_from <<
"\"" ) ;
171void GSmtp::EnvelopeImp::readFromAuthIn( std::istream & stream , Envelope & e )
173 e.m_from_auth_in = readValue( stream ,
"MailFromAuthIn" ) ;
174 if( !e.m_from_auth_in.empty() && e.m_from_auth_in !=
"+" && !
G::Xtext::valid(e.m_from_auth_in) )
175 throw Envelope::ReadError(
"invalid mail-from-auth-in encoding" ) ;
178void GSmtp::EnvelopeImp::readFromAuthOut( std::istream & stream , Envelope & e )
180 e.m_from_auth_out = readValue( stream ,
"MailFromAuthOut" ) ;
181 if( !e.m_from_auth_out.empty() && e.m_from_auth_out !=
"+" && !
G::Xtext::valid(e.m_from_auth_out) )
182 throw Envelope::ReadError(
"invalid mail-from-auth-out encoding" ) ;
185void GSmtp::EnvelopeImp::readToList( std::istream & stream , Envelope & e )
187 e.m_to_local.clear() ;
188 e.m_to_remote.clear() ;
190 unsigned int to_count =
G::Str::toUInt( readValue(stream,
"ToCount") ) ;
192 for(
unsigned int i = 0U ; i < to_count ; i++ )
194 std::string to_line = readLine( stream ) ;
195 bool is_local = to_line.find(
FileStore::x()+
"To-Local: ") == 0U ;
196 bool is_remote = to_line.find(
FileStore::x()+
"To-Remote: ") == 0U ;
197 if( ! is_local && ! is_remote )
198 throw Envelope::ReadError(
"bad 'to' line" ) ;
201 e.m_to_local.push_back( value(to_line) ) ;
203 e.m_to_remote.push_back( value(to_line) ) ;
207void GSmtp::EnvelopeImp::readAuthentication( std::istream & stream , Envelope & e )
209 e.m_authentication =
G::Xtext::decode( readValue(stream,
"Authentication") ) ;
212void GSmtp::EnvelopeImp::readClientSocketAddress( std::istream & stream , Envelope & e )
214 e.m_client_socket_address = readValue( stream ,
"Client" ) ;
217void GSmtp::EnvelopeImp::readClientSocketName( std::istream & stream , Envelope & )
222void GSmtp::EnvelopeImp::readClientCertificate( std::istream & stream , Envelope & e )
224 e.m_client_certificate = readValue( stream ,
"ClientCertificate" ) ;
227void GSmtp::EnvelopeImp::readEnd( std::istream & stream , Envelope & )
229 std::string end = readLine( stream ) ;
231 throw Envelope::ReadError(
"no end line" ) ;
234std::string GSmtp::EnvelopeImp::readValue( std::istream & stream ,
const std::string & expected_key ,
bool * crlf )
236 std::string line = readLine( stream , crlf ) ;
238 std::string prefix =
FileStore::x() + expected_key +
":" ;
240 return std::string() ;
242 prefix.append( 1U ,
' ' ) ;
243 std::size_t pos = line.find( prefix ) ;
245 throw Envelope::ReadError(
"expected \"" +
FileStore::x() + expected_key +
":\"" ) ;
250 int c = stream.peek() ;
251 if( c ==
' ' || c ==
'\t' )
253 std::string next_line = readLine( stream ) ;
254 if( next_line.empty() || (next_line[0]!=
' '&&next_line[0]!=
'\t') )
255 throw Envelope::ReadError() ;
256 next_line[0] =
'\n' ;
257 line.append( next_line ) ;
263 return value( line ) ;
266std::string GSmtp::EnvelopeImp::readLine( std::istream & stream ,
bool * crlf )
270 if( crlf && !line.empty() )
271 *crlf = line.at(line.size()-1U) ==
'\r' ;
277std::string GSmtp::EnvelopeImp::value(
const std::string & line )
A structure containing the contents of an envelope file, with support for file reading,...
static void read(std::istream &, Envelope &)
Reads an envelope from a stream.
static std::size_t write(std::ostream &, const Envelope &)
Writes an envelope to a stream.
static void copy(std::istream &, std::ostream &)
A convenience function to copy lines from an input stream to an output stream.
static bool knownFormat(const std::string &format)
Returns true if the storage format string is recognised and supported for reading.
static std::string x()
Returns the prefix for envelope header lines.
static std::string format(int generation=0)
Returns an identifier for the storage format implemented by this class, or some older generation of i...
static string_view ws()
Returns a string of standard whitespace characters.
static std::string tail(const std::string &in, std::size_t pos, const std::string &default_=std::string())
Returns the last part of the string after the given position.
static std::string & trimRight(std::string &s, string_view ws, std::size_t limit=0U)
Trims the rhs of s, taking off up to 'limit' of the 'ws' characters.
static unsigned int replaceAll(std::string &s, const std::string &from, const std::string &to)
Does a global replace on string 's', replacing all occurrences of sub-string 'from' with 'to'.
static unsigned int toUInt(const std::string &s)
Converts string 's' to an unsigned int.
static std::string trimmed(const std::string &s, string_view ws)
Returns a trim()med version of s.
static std::string readLineFrom(std::istream &stream, const std::string &eol=std::string())
Reads a line from the stream using the given line terminator.
static std::string & trim(std::string &s, string_view ws)
Trims both ends of s, taking off any of the 'ws' characters.
static std::string decode(const std::string &)
Decodes the given string.
static bool valid(const std::string &, bool strict=false)
Returns true if a valid encoding.
static std::string encode(const std::string &)
Encodes the given string.
SMTP and message-store classes.