////////////////////////////////////////////////////////////////////// // Mini INI File Crackers // Written by Jonathan A. Foster // Started June 1st, 2021 // Copyright JF Possibilities, Inc. All rights reserved. // Used with permission in the "Poor Man's IDS" project ////////////////////////////////////////////////////////////////////// #include #include #include #include "miniini.h" ////////////////////////////////////////////////////////////////////// // MiniINIvars ////////////////////////////////////////////////////////////////////// std::string MiniINIvars::get(const std::string &name, const std::string &def) { NameVal::iterator v = vals.find(name); if(v!=vals.end()) return v->second; vals[name]=def; return def; } std::string MiniINIvars::get(const std::string &name) const { NameVal::const_iterator v = vals.find(name); return v!=vals.end() ? v->second : ""; } // TODO: come up with better range checking to allow full range of 32bit ints. int MiniINIvars::geti(const std::string &name, int def, int min, int max) const { int r; NameVal::const_iterator v = vals.find(name); if(v!=vals.end()) { const std::string &s = v->second; if(s!="" && s.size()<=9+(s[0]=='+' || s[0]=='-')) { r = atoi(s.c_str()); if(r>=min && r<=max) return r; } } return def; } void MiniINIvars::add(const std::string &in) { std::string s = trim(in); std::string::size_type i; if(s=="" or s[0]=='#' or s[0]==';') return; // NOP i = s.find('='); if(i==s.npos || i==0) throw std::runtime_error( "MiniINIvars.add: incorrectly formatted name / value pair"); // TODO: catch dupe vars? vals[trim(s.substr(0, i-1))] = trim(s.substr(i+1)); } std::ostream &MiniINIvars::save(std::ostream &out) const { NameVal::const_iterator var; for(var = vals.begin(); var!=vals.end(); var++) out << var->first << " = " << var->second << '\n'; return out; } ////////////////////////////////////////////////////////////////////// // MiniINIlines ////////////////////////////////////////////////////////////////////// void MiniINIlines::add(const std::string &in) { vals.push_back(in); } std::ostream &MiniINIlines::save(std::ostream &out) const { StringList::const_iterator val; for(val = vals.begin(); val!=vals.end(); val++) out << *val << '\n'; return out; } ////////////////////////////////////////////////////////////////////// // MiniINI ////////////////////////////////////////////////////////////////////// void MiniINI::load(const std::string &fname) { std::string l; std::string gname; MiniINIgroup *group = 0; std::ifstream f(fname.c_str()); INIgroupList::iterator gmap; int ln=0; while(std::getline(f, l)) { ln++; gname = trim(l); if(gname.size()>2 && gname[0]=='[' && gname.end()[-1]==']') { gname = gname.substr(1, gname.size()-2); group = (gmap = groups.find(gname))==groups.end() ? 0 : gmap->second; continue; } try { if(group) group->add(l); } catch(const std::exception &e) { throw std::runtime_error("Error parsing "+fname+" line "+str(ln)+ " "+e.what()); } } } void MiniINI::save(const std::string &fname) { std::ofstream f(fname.c_str()); INIgroupList::iterator group; for(group = groups.begin(); group!=groups.end(); group++) { f << '[' << group->first << "]\n"; f << *group->second << '\n'; } }