Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <cctype>
- #include <ciso646>
- #include <ctime>
- #include <fstream>
- #include <functional>
- #include <iomanip>
- #include <iostream>
- #include <iterator>
- #include <sstream>
- #include <string>
- #include <vector>
- using namespace std;
- //----------------------------------------------------------------------------
- string titlecase( const string& s )
- {
- string result( s );
- if (result.length())
- {
- transform(
- s.begin(),
- s.end(),
- result.begin(),
- ptr_fun <int, int> ( tolower )
- );
- result[ 0 ] = toupper( s[ 0 ] );
- }
- return result;
- }
- //----------------------------------------------------------------------------
- struct date_t
- //----------------------------------------------------------------------------
- {
- // (table driven data)
- static const char* month_names_abbr[ 12 ];
- static unsigned days_per_month[ 2 ][ 13 ];
- static unsigned yday_per_month[ 2 ][ 13 ];
- unsigned year, month, day; // 0..N, 1..12, 1..31
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
- date_t( unsigned year = 0, unsigned month = 0, unsigned day = 0 ):
- year( year ), month( month ), day( day )
- { }
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
- bool is_leap_year() const
- {
- return ((year % 400) == 0) or (((year % 4) == 0) and ((year % 100) != 0));
- }
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
- unsigned day_of_year() const
- {
- return yday_per_month[ is_leap_year() ][ month - 1 ] + day;
- }
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
- void day_of_year( unsigned d )
- {
- unsigned leap;
- // The following trick allows us to add days...
- while (d > yday_per_month[ leap = is_leap_year() ][ 12 ])
- {
- d -= yday_per_month[ leap ][ 12 ];
- year += 1;
- }
- if (d > yday_per_month[ leap ][ 12 ]) return;
- month = find_if(
- yday_per_month[ leap ],
- yday_per_month[ leap ] + 12,
- bind2nd( greater_equal <unsigned> (), d )
- )
- - yday_per_month[ leap ];
- day = d - yday_per_month[ leap ][ month - 1 ];
- }
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
- bool valid() const
- {
- if ((year < 0) or (month < 1) or (month > 12) or (day < 1))
- return false;
- return day <= days_per_month[ is_leap_year() ][ month ];
- }
- };
- //............................................................................
- const char* date_t::month_names_abbr[ 12 ] =
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- unsigned date_t::days_per_month[ 2 ][ 13 ] =
- {
- { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
- };
- unsigned date_t::yday_per_month[ 2 ][ 13 ] =
- {
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
- //............................................................................
- istream& operator >> ( istream& ins, date_t& date )
- {
- int day, year;
- string month;
- ins >> day >> month >> year;
- if (ins)
- {
- month = titlecase( month.substr( 0, 3 ) );
- date.year = year;
- date.month = find(
- date_t::month_names_abbr,
- date_t::month_names_abbr + 12,
- month
- )
- - date_t::month_names_abbr + 1;
- date.day = day;
- if (!date.valid())
- ins.setstate( ios::failbit );
- }
- return ins;
- }
- //............................................................................
- ostream& operator << ( ostream& outs, const date_t& date )
- {
- ostringstream ss;
- ss << setw( 2 ) << date.day << " " << date_t::month_names_abbr[ date.month - 1 ] << " " << date.year;
- if (!ss) outs.setstate( ss.rdstate() );
- else outs << ss.str();
- return outs;
- }
- //............................................................................
- date_t& operator += ( date_t& date, unsigned days )
- {
- date.day_of_year( days + date.day_of_year() );
- return date;
- }
- //............................................................................
- bool operator == ( const date_t& lhs, const date_t& rhs )
- {
- return (lhs.year == rhs.year) && (lhs.month == rhs.month) && (lhs.day == rhs.day);
- }
- //............................................................................
- bool operator < ( const date_t& lhs, const date_t& rhs )
- {
- return (lhs.year != rhs.year)
- ? (lhs.year < rhs.year)
- : (lhs.day_of_year() < rhs.day_of_year());
- }
- //............................................................................
- bool operator <= ( const date_t& lhs, const date_t& rhs )
- {
- return (lhs == rhs) or (lhs < rhs);
- }
- //............................................................................
- date_t now()
- {
- date_t result;
- time_t t = time( NULL );
- struct tm now = *gmtime( &t );
- result.year = now.tm_year + 1900;
- result.month = now.tm_mon + 1;
- result.day = now.tm_mday;
- return result;
- }
- template <bool Verbose = false>
- //----------------------------------------------------------------------------
- struct certificate_t
- //----------------------------------------------------------------------------
- {
- string name;
- string password_policy;
- string type;
- date_t renewal_start_date;
- date_t private_key_expiry;
- string DN;
- certificate_t() { }
- template <bool V>
- certificate_t( const certificate_t <V> & certificate ):
- name ( certificate.name ),
- password_policy ( certificate.password_policy ),
- type ( certificate.type ),
- renewal_start_date ( certificate.renewal_start_date ),
- private_key_expiry ( certificate.private_key_expiry ),
- DN ( certificate.DN )
- { }
- };
- //............................................................................
- template <bool Verbose>
- istream& operator >> ( istream& ins, certificate_t <Verbose> & certificate )
- {
- string s;
- // Get the next non-empty line
- do getline( ins, s );
- while (ins && s.empty());
- // Remove any trailing whitespace
- s.erase( s.find_last_not_of( " \t\v\f\r\n" ) + 1 );
- istringstream ss( s );
- ss >> s;
- ss >> certificate.name
- >> certificate.password_policy
- >> certificate.type
- >> certificate.renewal_start_date
- >> certificate.private_key_expiry
- >> ws;
- getline( ss, certificate.DN );
- certificate.name = s + " " + certificate.name;
- if (ss.fail())
- ins.setstate( ss.rdstate() );
- // Do some error checking here on password_policy, type, and DN //
- return ins;
- }
- //............................................................................
- template <bool Verbose>
- ostream& operator << ( ostream& outs, const certificate_t <Verbose> & certificate )
- {
- ostringstream ss;
- ss << left;
- if (Verbose)
- ss << setw( 16 ) << certificate.name << " "
- << setw( 11 ) << certificate.password_policy << " "
- << setw( 12 ) << certificate.type << " "
- << setw( 15 ) << certificate.renewal_start_date << " "
- << setw( 15 ) << certificate.private_key_expiry << " "
- << certificate.DN;
- else
- ss << setw( 16 ) << certificate.name << " "
- << setw( 15 ) << certificate.renewal_start_date << " "
- << setw( 15 ) << certificate.private_key_expiry;
- if (!ss) outs.setstate( ss.rdstate() );
- else outs << ss.str();
- return outs;
- }
- //----------------------------------------------------------------------------
- struct expired
- //----------------------------------------------------------------------------
- {
- date_t when;
- explicit expired( const date_t& when ):
- when( when )
- { }
- template <bool Verbose>
- bool operator () ( const certificate_t <Verbose> & certificate ) const
- {
- return not( (certificate.renewal_start_date <= when)
- or (certificate.private_key_expiry <= when) );
- }
- };
- //----------------------------------------------------------------------------
- int usage( const char* arg0, int exitcode, const char* message = "" )
- {
- (exitcode ? cerr : cout) << message << (message ? "\n" : "") <<
- "usage:\n"
- " " << arg0 << " --help\n"
- " " << arg0 << " /?\n"
- " Display this help.\n\n"
- " " << arg0 << " [--verbose] DAYS FILENAME\n"
- " " << arg0 << " [/v] DAYS FILENAME\n"
- " Search the file for certificates expiring in DAYS days or less.\n"
- " If the VERBOSE option (\"--verbose\" or \"/v\") is specified, then\n"
- " all data about the matching entry is displayed, otherwise only the\n"
- " entry name is displayed.\n"
- " DAYS must be a non-negative whole number.\n\n";
- return exitcode;
- }
- //----------------------------------------------------------------------------
- int getdays( const char* days )
- {
- int result = -1;
- istringstream ss( days );
- ss >> result;
- return result;
- }
- //----------------------------------------------------------------------------
- bool ishelp( const string& arg1 )
- {
- return (arg1 == "--help") or (arg1 == "/?");
- }
- //----------------------------------------------------------------------------
- bool isverbose( const string& arg1 )
- {
- return (arg1 == "--verbose") or (arg1 == "/v");
- }
- //----------------------------------------------------------------------------
- int main( int argc, char** argv )
- {
- // Parse command arguments .................................................
- if ((argc == 1) or ishelp( argv[ 1 ] ))
- return usage( argv[ 0 ], 0 );
- bool verbose = isverbose( argv[ 1 ] );
- if (argc != (verbose ? 4 : 3))
- return usage( argv[ 0 ], 1, "Incorrect arguments" );
- int days = getdays( argv[ verbose ? 2 : 1 ] );
- if (days < 0)
- return usage( argv[ 0 ], 1, "Invalid DAYS" );
- ifstream f( argv[ verbose ? 3 : 2 ] );
- if (!f)
- return usage( argv[ 0 ], 1, "Invalid FILENAME" );
- date_t today = now();
- date_t tomorrow = today; tomorrow += days;
- // Skip the non-data lines .................................................
- // (up to and including the first line starting with a "-")
- vector <certificate_t <> > certificates;
- {
- string s;
- do { getline( f, s ); }
- while (s.substr( 0, 1 ) != "-");
- copy(
- istream_iterator <certificate_t <> > ( f ),
- istream_iterator <certificate_t <> > (),
- back_inserter( certificates )
- );
- }
- cout << "There are " << certificates.size() << " certificates.\n\n";
- // Find and display all items past due .....................................
- // (Expired items are moved to the END of the vector)
- vector <certificate_t <> > ::iterator
- certificates_past_due_begin
- = stable_partition(
- certificates.begin(),
- certificates.end(),
- expired( today )
- );
- if (certificates_past_due_begin != certificates.end())
- {
- cout << "Items PAST DUE\n ";
- if (verbose)
- copy(
- certificates_past_due_begin,
- certificates.end(),
- ostream_iterator <certificate_t <true> > ( cout, "\n " )
- );
- else
- copy(
- certificates_past_due_begin,
- certificates.end(),
- ostream_iterator <certificate_t <false> > ( cout, "\n " )
- );
- certificates.erase( certificates_past_due_begin, certificates.end() );
- }
- else
- cout << "No items past due\n";
- // Find and display all items due "tomorrow" (today + DAYS) ................
- // (Erase all items not soon to expire)
- certificates.erase(
- remove_if(
- certificates.begin(),
- certificates.end(),
- expired( tomorrow )
- ),
- certificates.end()
- );
- if (certificates.size())
- {
- cout << "\nItems due to expire in " << days << " DAYS\n ";
- if (verbose)
- copy(
- certificates.begin(),
- certificates.end(),
- ostream_iterator <certificate_t <true> > ( cout, "\n " )
- );
- else
- copy(
- certificates.begin(),
- certificates.end(),
- ostream_iterator <certificate_t <false> > ( cout, "\n " )
- );
- }
- else
- cout << "\nNo items due to expire in " << days << " days\n";
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment