E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gexecutablefilter.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gexecutablefilter.cpp
19 //
20
21 #include "gdef.h"
22 #include "gsmtp.h"
23 #include "gprocess.h"
24 #include "gnewprocess.h"
25 #include "gexecutablecommand.h"
26 #include "gexecutablefilter.h"
27 #include "gstr.h"
28 #include "groot.h"
29 #include "gdebug.h"
30
31 GSmtp::ExecutableFilter::ExecutableFilter( GNet::ExceptionHandler & eh ,
32 bool server_side , const std::string & path ) :
33 m_server_side(server_side) ,
34 m_prefix(server_side?"filter":"client filter") ,
35 m_exit(0,server_side) ,
36 m_path(path) ,
37 m_task(*this,eh,"<<filter exec error: __strerror__>>",G::Root::nobody())
38 {
39 }
40
41 GSmtp::ExecutableFilter::~ExecutableFilter()
42 {
43 }
44
45 bool GSmtp::ExecutableFilter::simple() const
46 {
47 return false ;
48 }
49
50 std::string GSmtp::ExecutableFilter::id() const
51 {
52 return m_path.str() ;
53 }
54
55 bool GSmtp::ExecutableFilter::special() const
56 {
57 return m_exit.special ;
58 }
59
60 std::string GSmtp::ExecutableFilter::response() const
61 {
62 G_ASSERT( m_exit.ok() || m_exit.abandon() || !m_response.empty() ) ;
63 if( m_exit.ok() || m_exit.abandon() )
64 return std::string() ;
65 else
66 return m_response ;
67 }
68
69 std::string GSmtp::ExecutableFilter::reason() const
70 {
71 G_ASSERT( m_exit.ok() || m_exit.abandon() || !m_reason.empty() ) ;
72 if( m_exit.ok() || m_exit.abandon() )
73 return std::string() ;
74 else
75 return m_reason ;
76 }
77
78 void GSmtp::ExecutableFilter::start( const std::string & message_file )
79 {
80 // run the program
81 G::StringArray args ;
82 args.push_back( G::Path(message_file).str() ) ;
83 G::ExecutableCommand commandline( m_path.str() , args ) ;
84 G_LOG( "GSmtp::ExecutableFilter::start: " << m_prefix << ": running " << commandline.displayString() ) ;
85 m_task.start( commandline ) ;
86 }
87
88 void GSmtp::ExecutableFilter::onTaskDone( int exit_code , const std::string & output )
89 {
90 // search the output for diagnostics
91 std::pair<std::string,std::string> pair = parseOutput( output , "rejected" ) ;
92 m_response = pair.first ;
93 m_reason = pair.second ;
94 if( m_response.find("filter exec error") == 0U ) // see ctor
95 {
96 m_reason = m_response ;
97 m_response = "rejected" ;
98 }
99
100 m_exit = Exit( exit_code , m_server_side ) ;
101 if( !m_exit.ok() )
102 {
103 G_WARNING( "GSmtp::ExecutableFilter::onTaskDone: " << m_prefix << " failed: "
104 << "exit code " << exit_code << " [" << m_response << "]" ) ;
105 }
106
107 // callback
108 m_done_signal.emit( m_exit.result ) ;
109 }
110
111 std::pair<std::string,std::string> GSmtp::ExecutableFilter::parseOutput( std::string s , const std::string & default_ ) const
112 {
113 G_DEBUG( "GSmtp::ExecutableFilter::parseOutput: in: \"" << G::Str::printable(s) << "\"" ) ;
114
115 const std::string start_1("<<") ;
116 const std::string end_1(">>") ;
117 const std::string start_2("[[") ;
118 const std::string end_2("]]") ;
119
120 G::StringArray lines ;
121 while( G::Str::replaceAll( s , "\r\n" , "\n" ) ) ;
122 G::Str::replaceAll( s , "\r" , "\n" ) ;
123 G::Str::splitIntoFields( s , lines , "\n" ) ;
124
125 for( G::StringArray::iterator p = lines.begin() ; p != lines.end() ; )
126 {
127 std::string line = *p ;
128 size_t pos_start = line.find(start_1) ;
129 size_t pos_end = line.find(end_1) ;
130 if( pos_start != 0U )
131 {
132 pos_start = line.find(start_2) ;
133 pos_end = line.find(end_2) ;
134 }
135 if( pos_start == 0U && pos_end != std::string::npos )
136 {
137 *p++ = G::Str::printable(line.substr(2U,pos_end-2U)) ;
138 }
139 else
140 {
141 p = lines.erase( p ) ;
142 }
143 }
144
145 G_DEBUG( "GSmtp::ExecutableFilter::parseOutput: out: [" << G::Str::join("|",lines) << "]" ) ;
146
147 std::string response = ( !lines.empty() && !lines.at(0U).empty() ) ? lines.at(0U) : default_ ;
148 std::string reason = ( lines.size() > 1U && !lines.at(1U).empty() ) ? lines.at(1U) : response ;
149 return std::make_pair( response , reason ) ;
150 }
151
152 G::Slot::Signal1<int> & GSmtp::ExecutableFilter::doneSignal()
153 {
154 return m_done_signal ;
155 }
156
157 void GSmtp::ExecutableFilter::cancel()
158 {
159 m_task.stop() ;
160 }
161
162 bool GSmtp::ExecutableFilter::abandoned() const
163 {
164 return m_exit.abandon() ;
165 }
166
167 /// \file gexecutablefilter.cpp
G::Str::printable
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
Definition: gstr.cpp:701
GSmtp::ExecutableFilter::simple
virtual bool simple() const override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:45
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
GSmtp::ExecutableFilter::ExecutableFilter
ExecutableFilter(GNet::ExceptionHandler &, bool server_side, const std::string &)
Constructor.
Definition: gexecutablefilter.cpp:31
groot.h
GSmtp::ExecutableFilter::~ExecutableFilter
virtual ~ExecutableFilter()
Destructor.
Definition: gexecutablefilter.cpp:41
gexecutablecommand.h
gexecutablefilter.h
GNet::ExceptionHandler
An abstract interface for handling exceptions thrown out of event-loop callbacks (socket events...
Definition: gexceptionhandler.h:44
gstr.h
G::Str::replaceAll
static unsigned int replaceAll(std::string &s, const std::string &from, const std::string &to)
Does a global replace on string 's', replacing all occurances of sub-string 'from' with 'to'...
Definition: gstr.cpp:195
G
Low-level classes.
Definition: garg.h:29
GSmtp::ExecutableFilter::abandoned
virtual bool abandoned() const override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:162
GSmtp::ExecutableFilter::start
virtual void start(const std::string &path) override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:78
GSmtp::ExecutableFilter::special
virtual bool special() const override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:55
GSmtp::ExecutableFilter::id
virtual std::string id() const override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:50
gprocess.h
gnewprocess.h
G::ExecutableCommand
A structure representing an external program, holding a path and a set of arguments.
Definition: gexecutablecommand.h:43
GSmtp::ExecutableFilter::doneSignal
virtual G::Slot::Signal1< int > & doneSignal() override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:152
GSmtp::ExecutableFilter::reason
virtual std::string reason() const override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:69
GSmtp::ExecutableFilter::cancel
virtual void cancel() override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:157
G::Str::join
static std::string join(const std::string &sep, const StringArray &strings)
Concatenates an array of strings with separators.
Definition: gstr.cpp:1023
gsmtp.h
G::Str::splitIntoFields
static void splitIntoFields(const std::string &in, StringArray &out, const std::string &separators, char escape= '\0', bool remove_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:975
G::Slot::Signal1< int >
G::Path
A Path object represents a file system path.
Definition: gpath.h:72
GSmtp::ExecutableFilter::response
virtual std::string response() const override
Override from from GSmtp::Filter.
Definition: gexecutablefilter.cpp:60
gdebug.h