1 /*
2
3 Firewall Builder
4
5 Copyright (C) 2009 NetCitadel, LLC
6
7 Author: Vadim Kurland vadim@fwbuilder.org
8
9 $Id$
10
11 This program is free software which we release under the GNU General Public
12 License. You may redistribute and/or modify this program under the terms
13 of that license as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 To get a copy of the GNU General Public License, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24 */
25
26 #include "config.h"
27 #include "fwbuilder/libfwbuilder-config.h"
28
29 #include <assert.h>
30
31 #include "BaseCompiler.h"
32
33 #include <iostream>
34 #include <iomanip>
35 #include <algorithm>
36 #include <functional>
37 #include <fstream>
38 #include <string>
39
40
41 using namespace libfwbuilder;
42 using namespace fwcompiler;
43 using namespace std;
44
45
FWCompilerException(Rule * r,const string & err)46 FWCompilerException::FWCompilerException(Rule *r, const string &err) : FWException(err)
47 {
48 rule=r;
49 }
50
51
haveErrorsAndWarnings()52 bool BaseCompiler::haveErrorsAndWarnings()
53 {
54 return (int(errors_buffer.tellp()) > 0);
55 }
56
getErrors(const string & comment_sep)57 string BaseCompiler::getErrors(const string &comment_sep)
58 {
59 ostringstream ostr;
60 istringstream istr(errors_buffer.str());
61 while (!istr.eof())
62 {
63 string tmpstr;
64 getline(istr, tmpstr);
65 if (tmpstr.length())
66 ostr << comment_sep << tmpstr << endl;
67 }
68 return ostr.str();
69 }
70
clearErrors()71 void BaseCompiler::clearErrors()
72 {
73 errors_buffer.str("");
74 rule_errors.clear();
75 }
76
getErrorsForRule(Rule * rule,const std::string & comment_sep)77 string BaseCompiler::getErrorsForRule(Rule *rule, const std::string &comment_sep)
78 {
79 string rule_label = rule->getLabel();
80 rule_errors[rule_label].sort();
81 ostringstream ostr;
82 list<string>::iterator it;
83 string prev; // used to remove duplicate messages
84 for (it=rule_errors[rule_label].begin(); it!=rule_errors[rule_label].end(); ++it)
85 {
86 if (*it != prev) ostr << comment_sep << *it << endl;
87 prev = *it;
88 }
89 return ostr.str();
90 }
91
92
93 /*
94 * Error and warning format:
95 *
96 * fw-object-name:ruleset-name:rule-number: message
97 */
stdErrorMessage(FWObject * fw,FWObject * ruleset,FWObject * rule,const std::string & errstr)98 string BaseCompiler::stdErrorMessage(FWObject *fw,
99 FWObject *ruleset,
100 FWObject *rule,
101 const std::string &errstr)
102 {
103 ostringstream tmpstr;
104
105 // TODO: (some day) get rid of the argument @fw and use attribute
106 // ".ruleset_owner" instead. Set this attribute in the place where
107 // we prepare rules for processing and copy them to the
108 // queue. This way, when CompilerDriver prepares rules from the
109 // cluster, it can override the same attribute to make error and
110 // warning messges refer to correct object that really owns rule
111 // sets.
112 string ruleset_owner;
113 if (ruleset)
114 {
115 ruleset_owner = ruleset->getStr(".ruleset_owner");
116 }
117 if (ruleset_owner.empty() && fw) ruleset_owner = fw->getName();
118
119 tmpstr << ruleset_owner << ":";
120 if (ruleset) tmpstr << ruleset->getName();
121 tmpstr << ":";
122 if (rule && Rule::cast(rule)) tmpstr << Rule::cast(rule)->getPosition();
123 tmpstr << ": ";
124 tmpstr << level_macro << ": ";
125 tmpstr << errstr;
126 return tmpstr.str();
127 }
128
setLevel(const string & level,const string & errstr)129 string BaseCompiler::setLevel(const string &level, const string &errstr)
130 {
131 string str = errstr;
132 while (str.at(str.length() - 1) == '\n') str = str.substr(0, str.length() - 1);
133 size_t n = str.find(level_macro);
134 if (n != string::npos) str.replace(n, level_macro.length(), level);
135 return str;
136 }
137
message(const std::string & level,FWObject * fw,FWObject * ruleset,FWObject * rule,const string & errstr)138 void BaseCompiler::message(const std::string &level,
139 FWObject *fw,
140 FWObject *ruleset,
141 FWObject *rule,
142 const string &errstr)
143 {
144 string str = setLevel(level, stdErrorMessage(fw, ruleset, rule, errstr));
145 printError(str);
146 Rule *cast_rule = Rule::cast(rule);
147 if (cast_rule)
148 {
149 cast_rule->setCompilerMessage(str);
150 rule_errors[cast_rule->getLabel()].push_back(str);
151 }
152 }
153
printError(const string & errstr)154 void BaseCompiler::printError(const string &errstr)
155 {
156 if (!inEmbeddedMode())
157 {
158 cout << flush;
159 cerr << errstr << endl;
160 }
161 errors_buffer << errstr << endl;
162 }
163
164 /*
165 * Note that when this code runs as part of the command line compiler
166 * rather than as a single-rule compile function inside the GUI (that
167 * is, it is not in embedded mode) and if test mode was activated
168 * (usually via command line flag "-xt"), then abort() behaves as
169 * error(), that is, it prints error message but does not terminate
170 * the process but just returns. In embedded mode it always throws
171 * exception to stop compiling
172 */
abort(const string & errstr)173 void BaseCompiler::abort(const string &errstr) throw(FWException)
174 {
175 printError(errstr);
176 if (inEmbeddedMode())
177 throw FatalErrorInSingleRuleCompileMode(errors_buffer.str());
178 status = FWCOMPILER_ERROR;
179 if (test_mode) return;
180 throw FWException("Fatal error");
181 }
182
abort(FWObject * fw,FWObject * ruleset,FWObject * rule,const string & errstr)183 void BaseCompiler::abort(FWObject *fw,
184 FWObject *ruleset,
185 FWObject *rule,
186 const string &errstr) throw(FWException)
187 {
188 message("error", fw, ruleset, rule, errstr);
189 if (inEmbeddedMode())
190 throw FatalErrorInSingleRuleCompileMode(errors_buffer.str());
191 status = FWCOMPILER_ERROR;
192 if (test_mode) return;
193 throw FWException("Fatal error");
194 }
195
error(const string & str)196 void BaseCompiler::error(const string &str)
197 {
198 status = FWCOMPILER_ERROR;
199 printError(str);
200 }
201
error(FWObject * fw,FWObject * ruleset,FWObject * rule,const string & errstr)202 void BaseCompiler::error(FWObject *fw,
203 FWObject *ruleset,
204 FWObject *rule,
205 const string &errstr)
206 {
207 status = FWCOMPILER_ERROR;
208 message("error", fw, ruleset, rule, errstr);
209 }
210
warning(const string & str)211 void BaseCompiler::warning(const string &str)
212 {
213 status = FWCOMPILER_WARNING;
214 printError(str);
215 }
216
warning(FWObject * fw,FWObject * ruleset,FWObject * rule,const string & errstr)217 void BaseCompiler::warning(FWObject *fw,
218 FWObject *ruleset,
219 FWObject *rule,
220 const string &errstr)
221 {
222 status = FWCOMPILER_WARNING;
223 message("warning", fw, ruleset, rule, errstr);
224 }
225
info(const string & str)226 void BaseCompiler::info(const string &str)
227 {
228 if (!inEmbeddedMode())
229 {
230 cout << str << endl << flush;
231 }
232 }
233
errorRegExp(std::list<std::string> * err_regexp)234 void BaseCompiler::errorRegExp(std::list<std::string> *err_regexp)
235 {
236 err_regexp->clear();
237 err_regexp->push_back("([^:]*):([^:]*):.*[Ee]rror:");
238 err_regexp->push_back("(Error(:| )[^\n]*)");
239 }
240
warningRegExp(std::list<std::string> * warn_regexp)241 void BaseCompiler::warningRegExp(std::list<std::string> *warn_regexp)
242 {
243 warn_regexp->clear();
244 warn_regexp->push_back("([^:]*):([^:]*):.*[Ww]arning:");
245 warn_regexp->push_back("(Warning(:| )[^\n]*)");
246 }
247
248