35 m_envelope_path(envelope_path) ,
40 m_name = m_envelope_path.
basename() ;
41 size_t pos = m_name.rfind(
".envelope") ;
42 if( pos != std::string::npos ) m_name.erase( pos ) ;
43 G_DEBUG(
"StoredFile: \"" << m_name <<
"\"" ) ;
64 return contentPath().str() ;
74 readEnvelopeCore(
true ) ;
81 readEnvelopeCore( check ) ;
84 catch( std::exception & e )
91 void GSmtp::StoredFile::readEnvelopeCore(
bool check )
94 std::ifstream stream( m_envelope_path.str().c_str() , std::ios_base::binary | std::ios_base::in ) ;
96 throw OpenError( m_envelope_path.str() ) ;
98 readFormat( stream ) ;
101 readToList( stream ) ;
102 readAuthentication( stream ) ;
103 readClientSocketAddress( stream ) ;
106 readClientSocketName( stream ) ;
107 readClientCertificate( stream ) ;
111 if( check && m_to_remote.size() == 0U )
112 throw NoRecipients() ;
114 if( ! stream.good() )
115 throw StreamError() ;
117 readReasons( stream ) ;
120 void GSmtp::StoredFile::readFormat( std::istream & stream )
122 std::string format_line = getline(stream) ;
123 m_format = value(format_line,
"Format") ;
125 throw InvalidFormat( m_format ) ;
128 void GSmtp::StoredFile::readFlag( std::istream & stream )
130 std::string content_line = getline(stream) ;
131 m_eight_bit = value(content_line,
"Content") ==
"8bit" ;
134 void GSmtp::StoredFile::readFrom( std::istream & stream )
136 m_from = value(getline(stream),
"From") ;
137 G_DEBUG(
"GSmtp::StoredFile::readFrom: from \"" << m_from <<
"\"" ) ;
140 void GSmtp::StoredFile::readToList( std::istream & stream )
143 m_to_remote.clear() ;
145 std::string to_count_line = getline(stream) ;
146 unsigned int to_count =
G::Str::toUInt( value(to_count_line,
"ToCount") ) ;
148 for(
unsigned int i = 0U ; i < to_count ; i++ )
150 std::string to_line = getline(stream) ;
151 bool is_local = to_line.find(
FileStore::x()+
"To-Local") == 0U ;
152 bool is_remote = to_line.find(
FileStore::x()+
"To-Remote") == 0U ;
153 if( ! is_local && ! is_remote )
154 throw InvalidTo(to_line) ;
156 G_DEBUG(
"GSmtp::StoredFile::readToList: to "
157 "[" << (i+1U) <<
"/" << to_count <<
"] "
158 "(" << (is_local?
"local":
"remote") <<
") "
159 <<
"\"" << value(to_line) <<
"\"" ) ;
162 m_to_local.push_back( value(to_line) ) ;
164 m_to_remote.push_back( value(to_line) ) ;
168 void GSmtp::StoredFile::readAuthentication( std::istream & stream )
170 m_authentication =
G::Xtext::decode(value(getline(stream),
"Authentication")) ;
173 void GSmtp::StoredFile::readClientSocketAddress( std::istream & stream )
175 m_client_socket_address = value(getline(stream),
"Client") ;
178 void GSmtp::StoredFile::readClientSocketName( std::istream & stream )
180 m_client_socket_name =
G::Xtext::decode(value(getline(stream),
"ClientName")) ;
183 void GSmtp::StoredFile::readClientCertificate( std::istream & stream )
185 m_client_certificate =
G::Xtext::decode(value(getline(stream),
"ClientCertificate")) ;
188 void GSmtp::StoredFile::readEnd( std::istream & stream )
190 std::string end = getline(stream) ;
195 void GSmtp::StoredFile::readReasons( std::istream & stream )
198 while( stream.good() )
200 std::string reason = getline(stream) ;
211 G::Path content_path = contentPath() ;
212 G_DEBUG(
"GSmtp::FileStore::openContent: \"" << content_path <<
"\"" ) ;
213 std::auto_ptr<std::istream> stream(
new std::ifstream(
214 content_path.
str().c_str() , std::ios_base::in | std::ios_base::binary ) ) ;
215 if( !stream->good() )
217 reason =
"cannot open content file" ;
221 G_DEBUG(
"GSmtp::MessageStore: processing envelope \"" << m_envelope_path.basename() <<
"\"" ) ;
222 G_DEBUG(
"GSmtp::MessageStore: processing content \"" << content_path.
basename() <<
"\"" ) ;
227 catch( std::exception & e )
229 G_DEBUG(
"GSmtp::FileStore: exception: " << e.what() ) ;
235 std::string GSmtp::StoredFile::getline( std::istream & stream )
const
240 std::string GSmtp::StoredFile::value(
const std::string & s ,
const std::string & key )
const
242 size_t pos = s.find(
":") ;
243 if( pos == std::string::npos )
244 throw MessageStore::FormatError(key) ;
248 size_t key_pos = s.find(key) ;
249 if( key_pos == std::string::npos || (key_pos+key.length()) != pos )
250 throw MessageStore::FormatError(key) ;
253 return s.substr(pos+2U) ;
256 const std::string & GSmtp::StoredFile::crlf()
258 static const std::string s(
"\015\012" ) ;
264 const G::Path src = m_envelope_path ;
273 G_LOG(
"GSmtp::StoredMessage: locking file \"" << src.
basename() <<
"\"" ) ;
274 m_envelope_path = dst ;
275 m_old_envelope_path = src ;
282 void GSmtp::StoredFile::unlock()
286 G_LOG(
"GSmtp::StoredMessage: unlocking file \"" << m_envelope_path.basename() <<
"\"" ) ;
291 m_envelope_path = m_old_envelope_path ;
301 addReason( m_envelope_path , reason , reason_code ) ;
303 G::Path bad_path = badPath( m_envelope_path ) ;
304 G_LOG_S(
"GSmtp::StoredMessage: failing file: "
305 <<
"\"" << m_envelope_path.basename() <<
"\" -> "
306 <<
"\"" << bad_path.
basename() <<
"\"" ) ;
315 G_DEBUG(
"GSmtp::StoredMessage: unfailing file: " << m_envelope_path ) ;
316 if( m_envelope_path.extension() ==
"bad" )
318 G::Path dst = m_envelope_path ;
327 G_LOG(
"GSmtp::StoredMessage: unfailed file: "
328 <<
"\"" << m_envelope_path.basename() <<
"\" -> "
329 <<
"\"" << dst.
basename() <<
"\"" ) ;
330 m_envelope_path = dst ;
334 G_WARNING(
"GSmtp::StoredMessage: failed to unfail file: \"" << m_envelope_path <<
"\"" ) ;
339 void GSmtp::StoredFile::addReason(
const G::Path & path ,
const std::string & reason ,
int reason_code )
342 std::ofstream file( path.
str().c_str() ,
343 std::ios_base::binary | std::ios_base::app ) ;
344 file <<
FileStore::x() <<
"Reason: " << reason << crlf() ;
345 file <<
FileStore::x() <<
"ReasonCode:" ;
if( reason_code ) file <<
" " << reason_code ; file << crlf() ;
356 G_LOG(
"GSmtp::StoredMessage: deleting file: \"" << m_envelope_path.basename() <<
"\"" ) ;
362 G::Path content_path = contentPath() ;
363 G_LOG(
"GSmtp::StoredMessage: deleting file: \"" << content_path.
basename() <<
"\"" ) ;
383 G_ASSERT( m_content.get() != NULL ) ;
387 G::Path GSmtp::StoredFile::contentPath()
const
389 std::string s = m_envelope_path.
str() ;
390 std::string e(
".envelope" ) ;
391 size_t pos = s.rfind( e ) ;
392 if( pos == std::string::npos )
throw InvalidFilename(s) ;
394 s.append(
".content" ) ;
400 return m_to_remote.size() ;
410 return m_authentication ;
bool readEnvelope(std::string &reason, bool check_for_no_remote_recipients)
Reads the envelope.
static std::string format()
Returns an identifier for the storage format implemented by this class.
std::string str() const
Returns the path string.
virtual void destroy()
Final override from GSmtp::StoredMessage.
virtual size_t errorCount() const
Final override from GSmtp::StoredMessage.
static std::string x()
Returns the prefix for envelope header lines.
static std::string decode(const std::string &)
Decodes the given string.
static unsigned int toUInt(const std::string &s, bool limited=false)
Converts string 's' to an unsigned int.
std::string basename() const
Returns the path, excluding drive/directory parts.
std::list< std::string > Strings
A std::list of std::strings.
virtual std::string name() const
Final override from GSmtp::StoredMessage.
Used by GSmtp::FileStore, GSmtp::NewFile and GSmtp::StoredFile to claim write permissions.
static bool rename(const Path &from, const Path &to, const NoThrow &)
Renames the file. Returns false on error.
virtual bool eightBit() const
Final override from GSmtp::StoredMessage.
virtual void sync()
Final override from GSmtp::StoredMessage.
virtual ~StoredFile()
Destructor.
virtual std::auto_ptr< std::istream > extractContentStream()
Final override from GSmtp::StoredMessage.
virtual const G::Strings & to() const
Final override from GSmtp::StoredMessage.
bool openContent(std::string &reason)
Opens the content file.
static bool exists(const Path &file)
Returns true if the file (directory, link, device etc.) exists.
static std::string readLineFrom(std::istream &stream, const std::string &eol=std::string())
Reads a line from the stream using the given line terminator.
StoredFile(FileStore &store, const G::Path &envelope_path)
Constructor.
virtual const std::string & from() const
Final override from GSmtp::StoredMessage.
virtual void fail(const std::string &reason, int reason_code)
Final override from GSmtp::StoredMessage.
static bool remove(const Path &path, const NoThrow &)
Deletes the file or directory. Returns false on error.
virtual std::string authentication() const
Final override from GSmtp::StoredMessage.
virtual std::string location() const
Final override from GSmtp::StoredMessage.
An overload discriminator class for File methods.
virtual void unfail()
Final override from GSmtp::StoredMessage.
virtual size_t remoteRecipientCount() const
Final override from GSmtp::StoredMessage.
A concrete implementation of the MessageStore interface dealing in paired flat files and with an opti...
static bool knownFormat(const std::string &format)
Returns true if the storage format string is recognised and supported for reading.
Used by GSmtp::FileStore, GSmtp::NewFile and GSmtp::StoredFile to claim read permissions for reading ...
bool lock()
Locks the file by renaming the envelope file.
A Path object represents a file system path.
void removeExtension()
Modifies the path by removing any extension.