E-MailRelay
gcopyfilter.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 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/// \file gcopyfilter.cpp
19///
20
21#include "gdef.h"
22#include "gcopyfilter.h"
23#include "gfiledelivery.h"
24#include "gdirectory.h"
25#include "gstringtoken.h"
26#include "groot.h"
27#include "gfile.h"
28#include "glog.h"
29
31 Filter::Type filter_type , const Filter::Config & filter_config , const std::string & spec ) :
32 SimpleFilterBase(es,filter_type,"copy:") ,
33 m_store(store) ,
34 m_filter_config(filter_config) ,
35 m_spec(spec)
36{
37 std::string_view spec_sv = spec ;
38 for( G::StringTokenView t( spec_sv , ";" , 1U ) ; t ; ++t )
39 {
40 if( t() == "p" || t() == "pop" ) m_pop_by_name = true ;
41 if( t() == "h" || t() == "hardlink" ) m_hardlink = true ;
42 if( t() == "n" || t() == "nodelete" || t() == "no_delete" ) m_no_delete = true ;
43 }
44}
45
46GSmtp::Filter::Result GFilters::CopyFilter::run( const GStore::MessageId & message_id ,
47 bool & , GStore::FileStore::State e_state )
48{
49 G::Path content_path = m_store.contentPath( message_id ) ;
50 G::Path envelope_path = m_store.envelopePath( message_id , e_state ) ;
51 GStore::Envelope envelope = GStore::FileStore::readEnvelope( envelope_path ) ;
52
53 G::DirectoryList list ;
54 {
55 G::Root claim_root ;
56 list.readDirectories( m_store.directory() ) ;
57 }
58
59 G::StringArray copy_names ;
60 G::StringArray ignore_names ;
61 while( list.more() )
62 {
63 G::Path subdir = list.filePath() ;
64 std::string name = subdir.basename() ;
65 if( name.empty() || name.at(0U) == '.' || name == "postmaster" )
66 {
67 ignore_names.push_back( name ) ;
68 }
69 else
70 {
71 copy_names.push_back( name ) ;
72 GStore::FileDelivery::deliverTo( m_store , "copy" ,
73 subdir , envelope_path , content_path ,
74 m_hardlink , m_pop_by_name ) ;
75 }
76 }
77
78 if( copy_names.empty() )
79 {
80 G_WARNING_ONCE( "GFilters::CopyFilter::start: copy filter: "
81 "no sub-directories of [" << m_store.directory() << "] to copy in to" ) ;
82 return Result::ok ;
83 }
84 else
85 {
86 G_LOG( "GFilters::CopyFilter::start: " << prefix() << ": "
87 << message_id.str() << " copied to [" << G::Str::join(",",copy_names) << "]"
88 << (ignore_names.empty()?"":" not [") << G::Str::join(",",ignore_names)
89 << (ignore_names.empty()?"":"]") ) ;
90
91 if( m_no_delete )
92 {
93 return Result::ok ;
94 }
95 else
96 {
97 G::Root claim_root ;
98 G::File::remove( envelope_path ) ;
99 if( !m_pop_by_name )
100 G::File::remove( content_path ) ;
101 return Result::abandon ;
102 }
103 }
104}
105
CopyFilter(GNet::EventState es, GStore::FileStore &, Filter::Type, const Filter::Config &, const std::string &spec)
Constructor.
Definition: gcopyfilter.cpp:30
A GSmtp::Filter base class for filters that run synchronously.
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
A structure containing the contents of an envelope file, with support for file reading,...
Definition: genvelope.h:41
static void deliverTo(FileStore &, std::string_view prefix, const G::Path &dst_dir, const G::Path &envelope_path, const G::Path &content_path, bool hardlink=false, bool pop_by_name=false)
Low-level function to copy a single message into a mailbox sub-directory or a pop-by-name sub-directo...
A concrete implementation of the MessageStore interface dealing in paired flat files.
Definition: gfilestore.h:56
static Envelope readEnvelope(const G::Path &, std::ifstream *=nullptr)
Used by FileStore sibling classes to read an envelope file.
Definition: gfilestore.cpp:308
A somewhat opaque identifer for a GStore::MessageStore message id.
Definition: gmessagestore.h:43
std::string str() const
Returns the id string.
A iterator similar to G::DirectoryIterator but doing all file i/o in one go and providing a sorted re...
Definition: gdirectory.h:150
Path filePath() const
Returns the current path.
Definition: gdirectory.cpp:158
bool more()
Returns true if more and advances by one.
Definition: gdirectory.cpp:130
std::size_t readDirectories(const Path &dir, unsigned int limit=0U)
An initialiser that reads all sub-directories.
Definition: gdirectory.cpp:88
static bool remove(const Path &path, std::nothrow_t) noexcept
Deletes the file or directory. Returns false on error.
Definition: gfile_unix.cpp:177
A Path object represents a file system path.
Definition: gpath.h:82
std::string basename() const
Returns the rightmost part of the path, ignoring "." parts.
Definition: gpath.cpp:339
A class which acquires the process's special privileges on construction and releases them on destruct...
Definition: groot.h:52
static std::string join(std::string_view sep, const StringArray &strings)
Concatenates an array of strings with separators.
Definition: gstr.cpp:1221
A zero-copy string token iterator where the token separators are runs of whitespace characters,...
Definition: gstringtoken.h:54
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30