int split (vec<str> *out, rxx pat, str expr, size_t lim, bool emptylast) { const char *p = expr; const char *const e = p + expr.len (); size_t n; if (out) out->clear (); // check p < e to see that we're not dealing with an empty // string (especially since x? matches ""). for (n = 0; p < e && n + 1 < lim; n++) { if (!pat._exec (p, e - p, 0)) { return 0; } if (!pat.success ()) break; if (out) out->push_back (str (p, pat.start (0))); p += max (pat.end (0), 1); } if (lim && (p < e || emptylast)) { n++; if (out) { out->push_back (str (p, e - p)); } } return n; }
str rxx_replace_2 (str input, rxx pat, str repl_str) { repl_t repl; str ret; if (!repl.parse (repl_str)) { warn << "XX cannot parse replacement string: " << repl_str << "\n"; } else { const char *p = input; const char *const e = p + input.len (); strbuf b; bool go = true; bool err = false; // check p < e to see that we're not dealing with an empty // string (especially since x? matches ""). while (go && !err && p < e) { if (!pat._exec (p, e - p, 0)) { warn << "XX regex execution failed\n"; err = true; } else if (!pat.success ()) { go = false; } else { str pre = str (p, pat.start (0)); strbuf_output (b, pre); repl.output (b, p, pat); p += max (pat.end (0), 1); } } if (p < e && !err) { str post = str (p, e - p); strbuf_output (b, post); } if (!err) { ret = b; } } return ret; }
// Call the replace function for each matched pattern. str rxx_replace (str input, rxx pat, rxx_replace_cb_t cb) { const char *p = input; const char *const e = p + input.len (); strbuf b; bool go = true; bool err = false; str ret; // check p < e to see that we're not dealing with an empty // string (especially since x? matches ""). while (go && !err && p < e) { if (!pat._exec (p, e - p, 0)) { warn << "XX regex execution failed\n"; err = true; } else if (!pat.success ()) { go = false; } else { str pre = str (p, pat.start (0)); strbuf_output (b, pre); vec<str> v; extract_matches (&v, p, pat); str repl = (*cb) (&v); if (repl) { strbuf_output (b, repl); } p += max (pat.end (0), 1); } } if (p < e && !err) { str post = str (p, e - p); strbuf_output (b, post); } if (!err) { ret = b; } return ret; }
void authclnt::update_group (svccb *sbp, update_info &i) { dbfile *udbp; ptr<authcursor> uac; sfsauth_dbrec udbr; *i.kname.name = i.argp->req.rec.groupinfo->name; bool create = i.argp->req.rec.groupinfo->id == 0 && i.argp->req.rec.groupinfo->vers == 1; bool exists = get_group_cursor (&udbp, &uac, &udbr, i.kname, true, create); if (exists && create && udbr.groupinfo->id > udbp->grprange->id_max) { *i.res.errmsg = strbuf () << "all group IDs in the allowed range (" << udbp->grprange->id_min << "-" << udbp->grprange->id_max << ") are in use"; return; } if (!exists) { if (!create) { *i.res.errmsg = "perhaps record is read-only " "or database doesn't accept group updates"; return; } else { *i.res.errmsg = "no writable databases that accept group updates"; return; } } if (create && udbr.groupinfo->vers != 0) { *i.res.errmsg = strbuf () << "group `" << udbr.groupinfo->name << "'already exists"; return; } if (!i.admin) { if (create) { str gname; if (!(gname = group_prefix (udbr.groupinfo->name, i.cdbr.userinfo->name)) || gname.len () < 1) { *i.res.errmsg = strbuf () << "group name must be of the form `" << i.cdbr.userinfo->name << ".groupname'"; return; } static rxx groupquotarx ("(\\A|,)groupquota=([0-9]+)(\\Z|,)"); if (groupquotarx.search (i.cdbr.userinfo->privs) || udbp->default_groupquota >= 0) { u_int32_t max_groups; u_int32_t cur_groups; if (groupquotarx.success ()) convertint (groupquotarx[2], &max_groups); else max_groups = udbp->default_groupquota; // XXX - open could fail ptr<authcursor> gac = udbp->db->open (udbp->dbflags); cur_groups = gac->count_group_prefix (strbuf () << i.cdbr.userinfo->name << "."); if (cur_groups + 1 > max_groups) { *i.res.errmsg = strbuf () << "group quota exceeded (current=" << cur_groups << "/quota=" << max_groups << ")"; return; } } } else { ptr<sfspub> pk = sfscrypt.alloc (i.cdbr.userinfo->pubkey); str h = armor32 (pk->get_pubkey_hash ()); sfs_groupmembers list; unsigned int n = udbr.groupinfo->owners.size (); for (unsigned int j = 0; j < n; j++) list.push_back (udbr.groupinfo->owners[j]); if (!group_prefix (udbr.groupinfo->name, i.cdbr.userinfo->name) && !is_a_member (i.cdbr.userinfo->name, h, list)) { *i.res.errmsg = "access denied"; return; } } } if (i.argp->req.rec.groupinfo->vers < 1) { *i.res.errmsg = "version number of record must be greater than 0"; return; } if (i.argp->req.rec.groupinfo->vers != udbr.groupinfo->vers + 1) { *i.res.errmsg = "version mismatch"; return; } uac->ae.groupinfo->vers = i.argp->req.rec.groupinfo->vers; strbuf sb; sb << "Last modified " << timestr () << " by " ; if (uid && !*uid) sb << "*superuser*"; else sb << i.cp->unixcred->username; sb << "@" << client_name; uac->ae.groupinfo->audit = sb; // XXX: checking to make sure that the owners/groups are well-formed happens in update process_group_updates (udbr.groupinfo->owners, i.argp->req.rec.groupinfo->owners); process_group_updates (udbr.groupinfo->members, i.argp->req.rec.groupinfo->members); uac->ae.groupinfo->owners = udbr.groupinfo->owners; uac->ae.groupinfo->members = udbr.groupinfo->members; bool chlogok = write_group_changelog (i.argp->req.rec.groupinfo->name, i.argp->req.rec.groupinfo->vers, i.argp->req.rec.groupinfo->members, sb); if (!chlogok) { *i.res.errmsg = "could not write changelog; database unmodified"; return; } if (!uac->update ()) { // XXX: remove changelog entry *i.res.errmsg = "database refused update; see SFS documentation for correct syntax"; return; } i.res.set_ok (true); udbp->mkpub (); uac->find_group_name (udbr.groupinfo->name); if (global_dbcache) update_dbcache (uac); }