/*************************************************
* X.509 Certificate Store Searching Source File  *
* (C) 1999-2003 The Botan Project                *
*************************************************/

#include <botan/x509stor.h>
#include <algorithm>

namespace Botan {

namespace X509_Store_Search {

namespace {

/*************************************************
* Comparison Function Pointer                    *
*************************************************/
typedef bool (*compare_fn)(const std::string&, const std::string&);

/*************************************************
* Predicate for caseless searching               *
*************************************************/
bool caseless_cmp(char a, char b)
   {
   return (to_lower(a) == to_lower(b));
   }

/*************************************************
* Compare based on case-insensive substrings     *
*************************************************/
bool substring_match(const std::string& searching_for,
                     const std::string& found)
   {
   if(std::search(found.begin(), found.end(), searching_for.begin(),
                  searching_for.end(), caseless_cmp) != found.end())
      return true;
   return false;
   }

/*************************************************
* Compare based on case-insensive match          *
*************************************************/
bool ignore_case(const std::string& searching_for, const std::string& found)
   {
   if(searching_for.size() != found.size())
      return false;

   return std::equal(found.begin(), found.end(),
                     searching_for.begin(), caseless_cmp);
   }

/*************************************************
* Search for a certificate by email address      *
*************************************************/
std::vector<X509_Certificate> do_search(const X509_Store& store,
                                        const std::string& info,
                                        const std::string& value,
                                        compare_fn compare)
   {
   std::vector<X509_Certificate> all_certs = store.get_certs();
   std::vector<X509_Certificate> found_certs;

   for(u32bit j = 0; j != all_certs.size(); j++)
      {
      const X509_Certificate& this_cert = all_certs[j];
      const std::string this_value = this_cert.subject_info(info);
      if(compare(value, this_value))
         found_certs.push_back(this_cert);
      }
   return found_certs;
   }

}

/*************************************************
* Search for a certificate by email address      *
*************************************************/
std::vector<X509_Certificate> by_email(const X509_Store& store,
                                       const std::string& email)
   {
   return do_search(store, "RFC822", email, ignore_case);
   }

/*************************************************
* Search for a certificate by CommonName         *
*************************************************/
std::vector<X509_Certificate> by_name(const X509_Store& store,
                                      const std::string& name)
   {
   return do_search(store, "CommonName", name, substring_match);
   }

/*************************************************
* Search for a certificate by DNS name           *
*************************************************/
std::vector<X509_Certificate> by_dns(const X509_Store& store,
                                     const std::string& dns)
   {
   return do_search(store, "DNS", dns, ignore_case);
   }

}

}
