| 214 | }; |
| 215 | |
| 216 | string SetRedactionRulesFromFile(const string& rules_file_path) { |
| 217 | if (g_rules == NULL) g_rules = new Rules(); |
| 218 | g_rules->clear(); |
| 219 | |
| 220 | // Read the file. |
| 221 | FILE* rules_file = fopen(rules_file_path.c_str(), "r"); |
| 222 | if (rules_file == NULL) { |
| 223 | return Substitute("Could not open redaction rules file '$0'; $1", |
| 224 | rules_file_path, strerror(errno)); |
| 225 | } |
| 226 | // Check for an empty file and ignore it. This is done to play nice with automated |
| 227 | // cluster configuration tools that will generate empty files when no rules are in |
| 228 | // effect. Without this the JSON parser would produce an error. |
| 229 | struct stat rules_file_stats; |
| 230 | if (fstat(fileno(rules_file), &rules_file_stats)) { |
| 231 | fclose(rules_file); |
| 232 | return Substitute("Error reading redaction rules file; $0", strerror(errno)); |
| 233 | } |
| 234 | if (rules_file_stats.st_size == 0) { |
| 235 | fclose(rules_file); |
| 236 | return ""; |
| 237 | } |
| 238 | |
| 239 | char readBuffer[65536]; |
| 240 | rapidjson::FileReadStream stream(rules_file, readBuffer, sizeof(readBuffer)); |
| 241 | Document rules_doc; |
| 242 | rules_doc.ParseStream(stream); |
| 243 | fclose(rules_file); |
| 244 | if (rules_doc.HasParseError()) { |
| 245 | return Substitute("Error parsing redaction rules; $0", |
| 246 | GetParseError_En(rules_doc.GetParseError())); |
| 247 | } |
| 248 | if (!rules_doc.IsObject()) { |
| 249 | return "Error parsing redaction rules; root element must be a JSON Object."; |
| 250 | } |
| 251 | if (!rules_doc.HasMember("version")) { |
| 252 | return "Error parsing redaction rules; a document version is required."; |
| 253 | } |
| 254 | const Value& version = rules_doc["version"]; |
| 255 | if (version.IsNull()) { |
| 256 | return "Error parsing redaction rules; a document version is required."; |
| 257 | } |
| 258 | if (!version.IsInt()) { |
| 259 | return Substitute("Error parsing redaction rules; version must be an Integer but " |
| 260 | "is a $0", NameOfTypeOfJsonValue(version)); |
| 261 | } |
| 262 | if (version.GetInt() != 1) { |
| 263 | return "Error parsing redaction rules; only version 1 is supported."; |
| 264 | } |
| 265 | |
| 266 | RulesParser rules_parser; |
| 267 | return rules_parser.Parse(rules_doc); |
| 268 | } |
| 269 | |
| 270 | void Redact(string* value, bool* changed) { |
| 271 | DCHECK(value != NULL); |