00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <assert.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029
00030 #include <stdexcept>
00031
00032 #include "SpamUtil.h"
00033 #include "Logger.h"
00034 #include "SpamParameters.h"
00035
00036 using namespace std;
00037
00038 const SpamParameters::enumTableElem SpamParameters::enumTable[] = {
00039 enumTableElem("to_list", to_list ),
00040 enumTableElem("from_address", from_address ),
00041 enumTableElem("from_kill", from_kill ),
00042 enumTableElem("spam_words", spam_words),
00043 enumTableElem("kill_words", kill_words ),
00044 enumTableElem("flags", flags),
00045 enumTableElem("my_domain", my_domain ),
00046 enumTableElem("valid_users", valid_users ),
00047 };
00048
00049 vector<const char *> SpamParameters::section[(size_t)SpamParameters::SpamEnumMax];
00050
00051 bool SpamParameters::initialized = false;
00052
00058 bool SpamParameters::skipLine(const char *buf)
00059 {
00060 bool skipIt = false;
00061 char ch = *buf;
00062 if (ch == '\0' || ch == '#') {
00063 skipIt = true;
00064 }
00065 return skipIt;
00066 }
00067
00072 SpamParameters::SpamEnum SpamParameters::findEnum(const char *str )
00073 {
00074 SpamEnum enumVal = SpamEnumMax;
00075 size_t tableSize = sizeof(enumTable) / sizeof(enumTableElem);
00076 for (size_t i = 0; i < tableSize; i++) {
00077 const char *enumName = enumTable[i].name;
00078 if (strcmp(str, enumName) == 0) {
00079 enumVal = enumTable[i].enumVal;
00080 break;
00081 }
00082 }
00083 return enumVal;
00084 }
00085
00086
00091 void SpamParameters::enterPhrase(const char *buf)
00092 {
00093 size_t len = strlen( buf );
00094 char *storage = new char[ len + 1 ];
00095 SpamUtil().strncpy(storage, buf, len + 1);
00096 section[ (size_t)currentSection ].push_back( storage );
00097 }
00098
00099
00106 void SpamParameters::finiteStateMachine( const char *buf )
00107 throw( SpamException )
00108 {
00109 paramState nextState = BadState;
00110 switch (currentState) {
00111 case sectionDef:
00112 {
00113 SpamEnum sec = findEnum(buf);
00114 if (sec != SpamEnumMax) {
00115 currentSection = sec;
00116 nextState = beginBracket;
00117 }
00118 else {
00119 throw SpamException("finiteStateMachine: section defintion expected");
00120 }
00121 }
00122 break;
00123 case beginBracket:
00124 {
00125 if (*buf == '[') {
00126 nextState = spamPhrase;
00127 }
00128 else {
00129 throw SpamException("finiteStateMachine: '[' expected");
00130 }
00131 }
00132 break;
00133 case spamPhrase:
00134 {
00135 if (*buf == ']') {
00136 nextState = sectionDef;
00137 }
00138 else {
00139 enterPhrase( buf );
00140 nextState = spamPhrase;
00141 }
00142 }
00143 break;
00144 default:
00145 {
00146 throw SpamException("finiteStateMachine: unexpected state");
00147 }
00148 break;
00149 }
00150
00151 currentState = nextState;
00152 }
00153
00154
00158 void SpamParameters::print()
00159 {
00160 size_t tableSize = sizeof(enumTable) / sizeof(enumTableElem);
00161 for (size_t i = 0; i < tableSize; i++) {
00162 const char *name = enumTable[i].name;
00163 printf("%s\n", name );
00164 printf("[\n");
00165 vector<const char *> &vec = getSection( (SpamEnum)i );
00166 size_t len = vec.size();
00167 for (size_t j = 0; j < len; j++) {
00168 const char *ptr = vec[j];
00169 printf(" %s\n", ptr );
00170 }
00171
00172 printf("]\n");
00173 }
00174 }
00175
00176
00177
00182 vector<const char *> &SpamParameters::getSection( SpamEnum sec )
00183 throw( SpamException )
00184 {
00185 static vector<const char *> bogus;
00186 vector<const char *> &vec = bogus;
00187 if (sec < SpamEnumMax) {
00188 vec = section[ (size_t)sec ];
00189 }
00190 else {
00191 throw out_of_range("getSection: bad enumeration argument");
00192 }
00193 return vec;
00194 }
00195
00196
00201 bool SpamParameters::hasFlag(const char *name)
00202 {
00203 bool foundFlag = false;
00204 vector<const char *> flagVec = getSection( flags );
00205 size_t len = flagVec.size();
00206 for (size_t i = 0; i < len; i++) {
00207 if (strcmp(flagVec[i], name) == 0) {
00208 foundFlag = true;
00209 break;
00210 }
00211 }
00212 return foundFlag;
00213 }
00214
00215
00216
00221 SpamParameters::~SpamParameters()
00222 {
00223 for (size_t i = 0; i < (size_t)SpamEnumMax; i++) {
00224 vector<const char *> oneSec = section[i];
00225 size_t len = oneSec.size();
00226 for (size_t j = 0; j < len; j++) {
00227 const char *ptr = oneSec[j];
00228 if (ptr != 0) {
00229 delete [] (char *)ptr;
00230 }
00231 }
00232 }
00233 }
00234
00235
00241 SpamParameters::SpamParameters()
00242 {
00243 assert( initialized );
00244 }
00245
00250 SpamParameters::SpamParameters(const char *paramFileName )
00251 throw( SpamException )
00252 {
00253 currentState = sectionDef;
00254 currentSection = SpamEnumMax;
00255
00256 const size_t BUF_SIZE = 1024;
00257 const char *mode = "r";
00258 FILE *file = fopen( paramFileName, mode );
00259 if (file != 0) {
00260 size_t lineNum = 0;
00261
00262 char buf[BUF_SIZE];
00263 while (fgets(buf, sizeof(buf), file) != 0) {
00264 lineNum++;
00265 SpamUtil().trim(buf);
00266 if (!skipLine(buf)) {
00267 try {
00268 finiteStateMachine( buf );
00269 }
00270 catch (SpamException e) {
00271 static char msg[128];
00272 sprintf(msg, "%s, line %d", e.what(), lineNum );
00273 throw SpamException( msg );
00274 }
00275 }
00276 }
00277 if (lineNum > 0) {
00278 Logger log = pLogger->getLogger("SpamParameters");
00279 log.log(Logger::DEBUG, "SpamParameters", "finished reading parameter file");
00280 }
00281 if (feof(file)) {
00282 fclose(file);
00283 }
00284 else {
00285 throw SpamException("SpamParameters::SpamParameters:error reading file");
00286 }
00287 }
00288 else {
00289 throw SpamException("SpamParameters::SpamParameters: could not open parameter file");
00290 }
00291 initialized = true;
00292 }