Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

PostfixMilterConf.cpp 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // /file PostfixMilterConf.cpp
  2. //
  3. // Copyright (C) 2011, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This file contains the functions for PostfixMilterConf.
  7. //
  8. // $Id$
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////////////////////////
  11. #include <exception>
  12. #include <stdexcept>
  13. #include <sstream>
  14. #include "Utility.hpp"
  15. #include "PostfixMilterConf.hpp"
  16. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // Configuration. ////////////////////////////////////////////////////////////////////////////////////////
  18. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  19. /// Milter keyword in the postfix main.cf file.
  20. const std::string SmtpdMilterKeyword("smtpd_milters");
  21. const std::string Whitespace(", \t");
  22. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  23. // End of configuration. /////////////////////////////////////////////////////////////////////////////////
  24. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  25. PostfixMilterConf::PostfixMilterConf(std::string SocketSpec) :
  26. SnfMilterSocketSpec(SocketSpec) {
  27. }
  28. void
  29. PostfixMilterConf::ConfLine(std::string Line) {
  30. ConfigurationLine = Utility::Trim(Line); // Remove leading and trailing whitespace.
  31. }
  32. bool
  33. PostfixMilterConf::IsIntegrated() {
  34. return (IsMilterLine() && ContainsSnfMilterSocketSpec());
  35. }
  36. void
  37. PostfixMilterConf::AddIntegration() {
  38. if (IsIntegrated()) {
  39. return;
  40. }
  41. if (IsMilterLine()) { // Add to existing milter line.
  42. std::string NewConfLine;
  43. NewConfLine = SmtpdMilterKeyword + " =";
  44. // Skip to "=" in configuration line.
  45. std::string::size_type NextIndex;
  46. NextIndex = ConfigurationLine.find("=");
  47. if (std::string::npos == NextIndex) { // Check format.
  48. std::ostringstream Temp;
  49. Temp << "Error processing postfix main.cf file smtpd_milters line: '"
  50. << ConfigurationLine << "'";
  51. throw std::runtime_error(Temp.str());
  52. }
  53. std::string ExistingMilters;
  54. ExistingMilters = Utility::Trim(ConfigurationLine.substr(NextIndex + 1)); // Should contain existing milters.
  55. while (std::string::npos != NextIndex) {
  56. NewConfLine += " ";
  57. std::string NextMilter;
  58. NextIndex = ExistingMilters.find_first_of(Whitespace);
  59. NextMilter = Utility::Trim(ExistingMilters.substr(0, NextIndex));
  60. ExistingMilters = Utility::Trim(ExistingMilters.substr(NextIndex + 1));
  61. if (NextMilter == "") {
  62. std::ostringstream Temp;
  63. Temp << "Error processing postfix main.cf file smtpd_milters line: '"
  64. << ConfigurationLine << "'";
  65. throw std::runtime_error(Temp.str());
  66. }
  67. NewConfLine += NextMilter;
  68. }
  69. ConfigurationLine = NewConfLine + " ";
  70. ConfigurationLine += SnfMilterSocketSpec;
  71. } else if (ConfigurationLine == "") { // Empty configuration line.
  72. ConfigurationLine = SmtpdMilterKeyword + " = ";
  73. ConfigurationLine += SnfMilterSocketSpec;
  74. } else { // Unexpected non-empty line.
  75. std::ostringstream Temp;
  76. Temp << "Internal error: Attempted to modify a line in main.cf that does not begin with '"
  77. << SmtpdMilterKeyword << "'";
  78. throw std::runtime_error(Temp.str());
  79. }
  80. ConfigurationLine = Utility::Trim(ConfigurationLine);
  81. }
  82. void
  83. PostfixMilterConf::RemoveIntegration() {
  84. if (!IsIntegrated()) {
  85. return;
  86. }
  87. std::string NewConfLine;
  88. NewConfLine = SmtpdMilterKeyword + " =";
  89. // Skip to "=" in configuration line.
  90. std::string::size_type NextIndex;
  91. NextIndex = ConfigurationLine.find("=");
  92. if (std::string::npos == NextIndex) { // Check format.
  93. std::ostringstream Temp;
  94. Temp << "Error processing postfix main.cf file smtpd_milters line: '"
  95. << ConfigurationLine << "'";
  96. throw std::runtime_error(Temp.str());
  97. }
  98. std::string ExistingMilters;
  99. bool AddedMilter = false;
  100. ExistingMilters = Utility::Trim(ConfigurationLine.substr(NextIndex + 1)); // Should contain existing milters.
  101. while (std::string::npos != NextIndex) {
  102. NewConfLine += " ";
  103. std::string NextMilter;
  104. NextIndex = ExistingMilters.find_first_of(Whitespace);
  105. NextMilter = Utility::Trim(ExistingMilters.substr(0, NextIndex));
  106. ExistingMilters = Utility::Trim(ExistingMilters.substr(NextIndex + 1));
  107. if (NextMilter == "") {
  108. std::ostringstream Temp;
  109. Temp << "Error processing postfix main.cf file smtpd_milters line: '"
  110. << ConfigurationLine << "'";
  111. throw std::runtime_error(Temp.str());
  112. }
  113. if (NextMilter != SnfMilterSocketSpec) { // Copy if not for SNFMilter.
  114. NewConfLine += NextMilter;
  115. AddedMilter = true;
  116. }
  117. }
  118. if (AddedMilter) {
  119. ConfigurationLine = NewConfLine;
  120. } else {
  121. ConfigurationLine = "";
  122. }
  123. ConfigurationLine = Utility::Trim(ConfigurationLine);
  124. }
  125. std::string
  126. PostfixMilterConf::ConfLine() {
  127. return ConfigurationLine;
  128. }
  129. bool
  130. PostfixMilterConf::IsMilterLine() {
  131. bool StartsWithKeyword;
  132. bool KeywordEndsCorrectly;
  133. char NextChar;
  134. StartsWithKeyword = (ConfigurationLine.find(SmtpdMilterKeyword) == 0);
  135. NextChar = ConfigurationLine[SmtpdMilterKeyword.length()];
  136. KeywordEndsCorrectly =
  137. (' ' == NextChar) ||
  138. ('\t' == NextChar) ||
  139. ('=' == NextChar);
  140. return (StartsWithKeyword && KeywordEndsCorrectly);
  141. }
  142. bool
  143. PostfixMilterConf::ContainsSnfMilterSocketSpec() {
  144. std::string::size_type SpecIndex;
  145. SpecIndex = ConfigurationLine.find("=");
  146. if (std::string::npos == SpecIndex) {
  147. return false;
  148. }
  149. SpecIndex++;
  150. while (SpecIndex < ConfigurationLine.length()) {
  151. SpecIndex = ConfigurationLine.find_first_not_of(Whitespace, SpecIndex); // Find next specification.
  152. if (ConfigurationLine.substr(SpecIndex, SnfMilterSocketSpec.length()) == SnfMilterSocketSpec) {
  153. SpecIndex += SnfMilterSocketSpec.length(); // Skip to after the specification.
  154. if (SpecIndex >= ConfigurationLine.length()) {
  155. return true; // No characters after the specification.
  156. }
  157. if ( (ConfigurationLine[SpecIndex] == ' ') ||
  158. (ConfigurationLine[SpecIndex] == '\t') ||
  159. (ConfigurationLine[SpecIndex] == ',') ) {
  160. return true; // Found specification.
  161. }
  162. }
  163. SpecIndex = ConfigurationLine.find_first_of(Whitespace, SpecIndex); // Find next specification.
  164. }
  165. return false;
  166. }