- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

filter.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 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 // filter.cpp
19 //
20 // Provides filter_run(), filter_main() and filter_help().
21 //
22
23 #include "gdef.h"
24 #include "garg.h"
25 #include "gfile.h"
26 #include "gstr.h"
27 #include "gexception.h"
28 #include "gdirectory.h"
29 #include "legal.h"
30 #include "filter.h"
31 #include <iostream>
32 #include <exception>
33 #include <stdexcept>
34 #include <sstream>
35 #include <list>
36 #include <string>
37
38 G_EXCEPTION( FilterError , "filter error" ) ;
39
40 void filter_help( const std::string & prefix )
41 {
42 std::cout
43 << "usage: " << prefix << " <emailrelay-content-file>" << std::endl
44 << std::endl
45 << "Copies the corresponding emailrelay envelope file into all " << std::endl
46 << "subdirectories of the spool directory. Exits with a " << std::endl
47 << "value of 100 if copied once or more. Intended for use " << std::endl
48 << "with \"emailrelay --pop-by-name\"." << std::endl
49 << std::endl
50 << Main::Legal::warranty(std::string(),"\n") << std::endl
51 << Main::Legal::copyright() << std::endl ;
52 }
53
54 bool filter_run( const std::string & content )
55 {
56 // check the content file exists
57 //
58 G::Path content_path( content ) ;
59 bool ok = G::File::exists( content_path ) ;
60 if( !ok )
61 throw FilterError( "no such file" ) ;
62
63 // build the envelope name
64 //
65 G::Path dir_path = content_path.dirname() ;
66 std::string envelope_name = content_path.basename() ;
67 unsigned int n = G::Str::replaceAll( envelope_name , "content" , "envelope" ) ;
68 if( n != 1U )
69 throw FilterError( "invalid filename" ) ;
70
71 // check the envelope file exists
72 //
73 G::Path envelope_path = G::Path( dir_path , envelope_name + ".new" ) ;
74 if( ! G::File::exists(envelope_path) )
75 {
76 // fall back to no ".new" extension in case we are run manually for some reason
77 G::Path envelope_path_alt = G::Path( dir_path , envelope_name ) ;
78 if( G::File::exists(envelope_path_alt) )
79 envelope_path = envelope_path_alt ;
80 else
81 throw FilterError( std::string() + "no envelope file \"" + envelope_path.str() + "\"" ) ;
82 }
83
84 // read the content "to" address
85 std::string to = filter_read_to( content_path.str() ) ;
86
87 // copy the envelope into all sub-directories
88 //
89 int directory_count = 0 ;
90 std::list<std::string> failures ;
91 G::Directory dir( dir_path ) ;
92 G::DirectoryIterator iter( dir ) ;
93 while( iter.more() && !iter.error() )
94 {
95 if( iter.isDir() && filter_match(iter.filePath(),to) )
96 {
97 directory_count++ ;
98 G::Path target = G::Path( iter.filePath() , envelope_name ) ;
99 bool copied = G::File::copy( envelope_path , target , G::File::NoThrow() ) ;
100 if( !copied )
101 failures.push_back( iter.fileName().str() ) ;
102 }
103 }
104
105 // delete the parent envelope (ignore errors)
106 //
107 bool envelope_deleted = false ;
108 if( directory_count > 0 && failures.empty() )
109 {
110 envelope_deleted = G::File::remove( envelope_path , G::File::NoThrow() ) ;
111 }
112
113 // notify failures
114 //
115 if( ! failures.empty() )
116 {
117 std::ostringstream ss ;
118 ss << "failed to copy envelope file " << envelope_path.str() << " into " ;
119 if( failures.size() == 1U )
120 {
121 ss << "the \"" << failures.front() << "\" sub-directory" ;
122 }
123 else
124 {
125 ss << failures.size() << " sub-directories, including \"" << failures.front() << "\"" ;
126 }
127 throw FilterError( ss.str() ) ;
128 }
129 if( directory_count == 0 ) // probably a permissioning problem
130 {
131 throw FilterError( "no sub-directories to copy into: check permissions" ) ;
132 }
133
134 return envelope_deleted ;
135 }
136
137 int filter_main( int argc , char * argv [] )
138 {
139 try
140 {
141 G::Arg args( argc , argv ) ;
142
143 if( args.c() <= 1U )
144 throw FilterError( "usage error: must be run by emailrelay with the full path of a message content file" ) ;
145
146 if( args.v(1U) == "--help" )
147 {
148 filter_help( args.prefix() ) ;
149 return 1 ;
150 }
151 else
152 {
153 return filter_run( args.v(1U) ) ? 100 : 0 ;
154 }
155 }
156 catch( std::exception & e )
157 {
158 std::cout << "<<" << e.what() << ">>" << std::endl ;
159 }
160 catch(...)
161 {
162 std::cout << "<<" << "exception" << ">>" << std::endl ;
163 }
164 return 1 ;
165 }
166
G::Path::str
std::string str() const
Returns the path string.
Definition: gpath.cpp:135
gdirectory.h
Main::Legal::copyright
static std::string copyright()
Returns the copyright text.
Definition: legal.cpp:26
G::File::copy
static bool copy(const Path &from, const Path &to, const NoThrow &)
Copies a file. Returns false on error.
Definition: gfile.cpp:70
G::Arg::prefix
std::string prefix() const
Returns the basename of v(0) without any extension.
Definition: garg.cpp:142
Main::Legal::warranty
static std::string warranty(const std::string &prefix, const std::string &eol)
Returns the warranty text.
Definition: legal.cpp:31
filter.h
G::Path::basename
std::string basename() const
Returns the path, excluding drive/directory parts.
Definition: gpath.cpp:162
filter_help
void filter_help(const std::string &prefix)
Definition: filter.cpp:40
G::DirectoryIterator::filePath
Path filePath() const
Returns the path of the current item.
Definition: gdirectory_unix_glob.cpp:93
filter_main
int filter_main(int argc, char *argv[])
Definition: filter.cpp:137
filter_run
bool filter_run(const std::string &content)
Definition: filter.cpp:54
filter_match
bool filter_match(G::Path, std::string)
Definition: filter_copy.cpp:30
garg.h
G::Directory
An encapsulation of a file system directory which allows for iterating through the set of contained f...
Definition: gdirectory.h:46
filter_read_to
std::string filter_read_to(const std::string &)
Definition: filter_copy.cpp:35
G::DirectoryIterator::fileName
Path fileName() const
Returns the name of the current item.
Definition: gdirectory_unix_glob.cpp:98
G::Arg::v
std::string v(size_type i) const
Returns the i'th argument.
Definition: garg.cpp:136
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 occurences of sub-string 'from' with 'to'...
Definition: gstr.cpp:78
G::Arg::c
size_type c() const
Returns the number of tokens in the command line, including the program name.
Definition: garg.cpp:131
gfile.h
legal.h
G::File::exists
static bool exists(const Path &file)
Returns true if the file (directory, link, device etc.) exists.
Definition: gfile.cpp:130
G::Path::dirname
Path dirname() const
Returns the drive/directory parts of the path.
Definition: gpath.cpp:182
G::File::remove
static bool remove(const Path &path, const NoThrow &)
Deletes the file or directory. Returns false on error.
Definition: gfile.cpp:29
G::File::NoThrow
An overload discriminator class for File methods.
Definition: gfile.h:56
G::DirectoryIterator::more
bool more()
Returns true if more and advances by one.
Definition: gdirectory_unix_glob.cpp:88
gexception.h
G_EXCEPTION
#define G_EXCEPTION(class_name, description)
define as a function rather than a type if optimising for size
Definition: gexception.h:93
G::DirectoryIterator::isDir
bool isDir() const
Returns true if the current item is a directory.
Definition: gdirectory_unix_glob.cpp:103
G::DirectoryIterator
A Directory iterator.
Definition: gdirectory.h:108
G::Arg
A class which holds a represention of the argc/argv command line array, and supports simple command-l...
Definition: garg.h:46
G::DirectoryIterator::error
bool error() const
Returns true on error. The caller should stop the iteration.
Definition: gdirectory_unix_glob.cpp:83
G::Path
A Path object represents a file system path.
Definition: gpath.h:44