/******************************************************************************* * Copyright (c) 2025, Jan Koester jan.koester@gmx.net * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "backend.h" #include "authdb.h" #include "user.h" #include "domain.h" #include "group.h" #include "types.h" #include "hash.h" namespace authdb { bool initalized=true; class DomainBackend { public: DomainBackend(authdb::AuthBackend &adminbck) : _adminbck(adminbck) { _domainbck=nullptr; } authdb::AuthBackend *data(uuid_t did){ size_t rd=sizeof(authdb::AuthHeader),end=_adminbck.end(); while(rdgetRequestURL(),"/settings/%[^/]",cdid)<0){ throw AuthBackendError("listUsers: wrong url!"); } DomainBackend dbackend(_AdminBackend); AuthBackend *backend=nullptr; if(strcmp(cdid,"admin") == 0 ){ backend=&_AdminBackend; }else if(uuid_parse(cdid,did) == 0 ){ backend=dbackend.data(did); }else{ throw AuthBackendError("listUsers: could not parse uuid!"); } size_t rd=sizeof(authdb::AuthHeader),end=backend->end(); content->appendChild(domel); userlist <<"

UserList:

"; while(rdsetPos(rd); backend->read((unsigned char*)&cur,sizeof(AuthData::Record)); rd=backend->getPos()+cur.datasize; if(cur.type == UserData && strcmp(cur.fieldname,"username")==0){ class UserData udat(cur.uuid); try { size_t upos=sizeof(authdb::AuthHeader); user.info(*backend,udat,upos); char cruid[20]; uuid_unparse(cur.uuid,cruid); userlist << "" << ""; }catch(AuthBackendError &e){ std::cerr << e.what() << std::endl; } } } userlist << "
" << udat.getUsername() << "
\"avatar\"" << "
  • " << "uid: " << cruid << "
  • " << "
  • Firstname:" << udat.getFirstname() << "
  • " << "
  • Lastname:" << udat.getLastname() << "
  • " << "
  • Email:" << udat.getMail() << "
  • " << "
"; content->appendChild(userlist.parse()); libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.send(curreq,out.c_str(),out.size()); } void createUser(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args,const char *baseurl){ libhttppp::HttpResponse rep; libhttppp::HttpForm curform; curform.parse(curreq); char cdid[255]; uuid_t did; if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/*",cdid)<0){ throw AuthBackendError("createUser: wrong url!"); } DomainBackend dbackend(_AdminBackend); AuthBackend *backend=nullptr; if(strcmp(cdid,"admin") == 0 ){ backend=&_AdminBackend; }else if(uuid_parse(cdid,did) == 0 ){ backend=dbackend.data(did); }else{ throw AuthBackendError("createUser: could not parse uuid!"); } if (curform.getBoundary()) { uuid_t uid; uuid_generate(uid); class UserData udat(uid); for (libhttppp::HttpForm::MultipartForm::Data* curformdat = curform.MultipartFormData.getFormData(); curformdat; curformdat = curformdat->nextData()) { if(curformdat->Value.empty()) continue; std::string name; int stortype=EmptyStorage; for(libhttppp::HttpForm::MultipartForm::Data::ContentDisposition *curdispo=curformdat->getDisposition(); curdispo; curdispo=curdispo->nextContentDisposition() ){ std::string tmp=curdispo->getKey(); std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c){ return std::tolower(c); }); if(tmp=="name"){ name=curdispo->getValue(); } if(tmp=="filename"){ stortype=BinaryStorage; } } if(stortype==EmptyStorage){ bool numeric=true; for(auto i : curformdat->Value){ if(!std::isdigit(i)){ numeric=false; break; } } if(!numeric) stortype=TextStorage; else stortype=IntStorage; } if(name.empty() || stortype == EmptyStorage) continue; struct AuthData::Record cudat; memset(&cudat,0,sizeof(AuthData::Record)); cudat.start=0xFE; uuid_copy(cudat.uuid,uid); cudat.type=UserData; cudat.storage=stortype; strcpy(cudat.fieldname,name.c_str()); if(cudat.storage==BinaryStorage){ cudat.datasize=curformdat->Value.size(); cudat.data=new char[cudat.datasize]; memcpy(cudat.data,curformdat->Value.data(), cudat.datasize); udat.Data->append(cudat); delete[] cudat.data; }else if(cudat.storage==TextStorage){ if(strcmp(cudat.fieldname,"pwhash")==0){ Hash hash; std::string pwhash,inpw; std::copy(curformdat->Value.begin(),curformdat->Value.end(), std::back_inserter(inpw)); hash.hash(inpw,pwhash); cudat.datasize=pwhash.length()+1; cudat.data=new char[cudat.datasize]; memcpy(cudat.data,pwhash.c_str(),pwhash.length()); cudat.data[pwhash.length()]='\0'; udat.Data->append(cudat); delete[] cudat.data; }else{ curformdat->Value.push_back('\0'); cudat.datasize=curformdat->Value.size(); cudat.data=new char[cudat.datasize]; memcpy(cudat.data,curformdat->Value.data(), curformdat->Value.size()); udat.Data->append(cudat); delete[] cudat.data; } }else if(cudat.storage==IntStorage){ curformdat->Value.push_back('\0'); int val=atoi(curformdat->Value.data()); cudat.datasize=sizeof(int); cudat.data=(char*)new int; memcpy(cudat.data,&val, curformdat->Value.size()); udat.Data->append(cudat); delete[] cudat.data; } } User user; user.create(*backend,&udat); std::cout << "user created!" << std::endl; } libhtmlpp::HtmlPage page; libhtmlpp::HtmlString form,out; form << "
" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "
" << "insertChild(form.parse()); libhtmlpp::print(&root,out,true); rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } void removeuser(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ char cdid[255],uid[255]; uuid_t did; if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/removeuser/%s",cdid,uid)<0){ throw AuthBackendError("listUsers: wrong url!"); } DomainBackend dbackend(_AdminBackend); AuthBackend *backend=nullptr; if(strcmp(cdid,"admin") == 0 ){ backend=&_AdminBackend; }else if(uuid_parse(cdid,did) == 0 ){ backend=dbackend.data(did); }else{ throw AuthBackendError("listUsers: could not parse uuid!"); } User user; uuid_t uuid; uuid_parse(uid,uuid); user.remove(*backend,uuid); libhttppp::HttpResponse rep; rep.setState(HTTP307); rep.setVersion(HTTPVERSION(1.1)); char rurl[255]; snprintf(rurl,255,"/settings/%s/listusers",cdid); rep.setHeaderData("Location")->push_back(rurl); rep.setContentType("text/html"); rep.send(curreq,nullptr,0); } void getAvatar(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ libhttppp::HttpResponse rep; DomainBackend dbackend(_AdminBackend); AuthBackend *backend=nullptr; char domain[255],cuid[255],ext[16]; if(sscanf(curreq->getRequestURL(),"/getavatar/%[^/]/%[^.].%s",domain,cuid,ext)<0) return; uuid_t did; if(strcmp(domain,"admin") == 0 ){ backend=&_AdminBackend; }else if(uuid_parse(domain,did) == 0 ){ backend=dbackend.data(did); }else{ throw AuthBackendError("createUser: could not parse uuid!"); } uuid_t uid; uuid_parse(cuid,uid); size_t rd=sizeof(authdb::AuthHeader),end=backend->end(); while(rdsetPos(rd); backend->read((unsigned char*)&cur,sizeof(AuthData::Record)); rd=backend->getPos()+cur.datasize; if(uuid_compare(cur.uuid,uid)==0 && strcmp(cur.fieldname,"avatar")==0){ cur.data = new char[cur.datasize]; backend->read((unsigned char*)cur.data,cur.datasize); char ctype[255]; snprintf(ctype,255,"image/%s",ext); rep.setContentType(ctype); rep.send(curreq,cur.data,cur.datasize); end=0; delete[] cur.data; } } if(end!=0){ rep.setState(HTTP404); rep.send(curreq,nullptr,0); } }; void editUser(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ char cdid[255],cuid[255]; uuid_t did; if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/edituser/%s",cdid,cuid)<0){ throw AuthBackendError("listUsers: wrong url!"); } DomainBackend dbackend(_AdminBackend); AuthBackend *backend=nullptr; if(strcmp(cdid,"admin") == 0 ){ backend=&_AdminBackend; }else if(uuid_parse(cdid,did) == 0 ){ backend=dbackend.data(did); }else{ throw AuthBackendError("listUsers: could not parse uuid!"); } size_t rd=sizeof(authdb::AuthHeader),end=backend->end(); uuid_t uid; uuid_parse(cuid,uid); AuthData editrec(uid); bool data = false; libhttppp::HttpForm curform; curform.parse(curreq); for (libhttppp::HttpForm::MultipartForm::Data* curformdat = curform.MultipartFormData.getFormData(); curformdat; curformdat = curformdat->nextData()) { AuthData curec(uid); curec.Data->type=UserData; curec.Data->storage=EmptyStorage; for(libhttppp::HttpForm::MultipartForm::Data::ContentDisposition *curdispo=curformdat->getDisposition(); curdispo; curdispo=curdispo->nextContentDisposition() ){ if(curformdat->Value.empty() || !curdispo->getValue()) continue; data = true; std::string key; if(curdispo->getKey()) key=curdispo->getKey(); else continue; std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c){ return std::tolower(c); }); if(key=="name"){ strcpy(curec.Data->fieldname,curdispo->getValue()); } if(key=="filename"){ curec.Data->storage=BinaryStorage; } } if(curec.Data->storage==EmptyStorage){ bool numeric=true; for(auto t : curformdat->Value){ if(!std::isdigit(t)){ numeric=false; break; } } if(numeric) curec.Data->storage=IntStorage; else curec.Data->storage=TextStorage; } if(curec.Data->storage==TextStorage) { curformdat->Value.push_back('\0'); if(strcmp(curec.Data->fieldname,"pwhash")==0){ Hash hash; std::string pwhash,inpw; std::copy(curformdat->Value.begin(),curformdat->Value.end(), std::back_inserter(inpw)); hash.hash(inpw,pwhash); curec.Data->datasize=pwhash.length()+1; curec.Data->data=new char[curec.Data->datasize]; std::copy(pwhash.begin(),pwhash.end(),curec.Data->data); curec.Data->data[pwhash.length()]='\0'; editrec.append(curec); delete[] curec.Data->data; }else{ curec.Data->datasize=curformdat->Value.size(); curec.Data->data=new char[curec.Data->datasize]; std::copy(curformdat->Value.begin(), curformdat->Value.end(),curec.Data->data); editrec.append(curec); delete[] curec.Data->data; } }else if(curec.Data->storage==BinaryStorage){ curec.Data->datasize=curformdat->Value.size(); curec.Data->data=new char[curec.Data->datasize]; memcpy(curec.Data->data,curformdat->Value.data(), curformdat->Value.size()); editrec.append(curec); delete[] curec.Data->data; }else if(curec.Data->storage==IntStorage){ curformdat->Value.push_back('\0'); curec.Data->datasize=sizeof(int); curec.Data->data=(char*)new int; int val=atoi(curformdat->Value.data()); memcpy(curec.Data->data,&val, curec.Data->datasize); editrec.append(curec); delete[] (int*)curec.Data->data; } } if(data){ editRecord(*backend,editrec,UserData); libhttppp::HttpResponse rep; rep.setState(HTTP307); rep.setVersion(HTTPVERSION(1.1)); char rurl[255]; snprintf(rurl,255,"/settings/%s/listusers",cdid); rep.setHeaderData("Location")->push_back(rurl); rep.setContentType("text/html"); rep.send(curreq,nullptr,0); return; } libhtmlpp::HtmlPage page; libhtmlpp::HtmlString form,out; form << "" << ""; while(rdsetPos(rd); backend->read((unsigned char*)&cur,sizeof(AuthData::Record)); rd=backend->getPos()+cur.datasize; if(uuid_compare(cur.uuid,uid)==0 && cur.type==UserData && cur.storage==TextStorage){ cur.data = new char[cur.datasize]; backend->read((unsigned char*)cur.data,cur.datasize); try { form << "" << ""; }catch(AuthBackendError &e){ std::cerr << e.what() << std::endl; } delete[] cur.data; } } form << "" << "" << "" << "
" << "insertChild(form.parse()); libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } libhtmlpp::HtmlElement *DomainChangeForm(libhttppp::HttpRequest *curreq,const char *url,AuthBackend &backend,libhtmlpp::HtmlString &dest){ libhttppp::HttpForm form; form.parse(curreq); char cdid[255]; if(sscanf(curreq->getRequestURL(),"/settings/%[^/]",cdid)<0) cdid[0]='\0'; for (libhttppp::HttpForm::UrlcodedForm::Data* cururlform = form.UrlFormData.getFormData(); cururlform; cururlform = cururlform->nextData()) { if( strcmp(cururlform->getKey(),"domaindid")==0){ if(strcmp(cdid,cururlform->getValue())!=0){ char rurl[255]; snprintf(rurl,255,"/settings/%s/%s",cururlform->getValue(),url); libhttppp::HttpResponse rep; rep.setState(HTTP307); rep.setVersion(HTTPVERSION(1.1)); rep.setHeaderData("Location")->push_back(rurl); rep.setContentType("text/html"); rep.send(curreq,nullptr,0); return nullptr; } } } size_t rd=sizeof(authdb::AuthHeader),end=backend.end(); Domain domain; dest.clear(); dest << ""; return (libhtmlpp::HtmlElement*)dest.parse(); } void listDomains(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ size_t rd=sizeof(authdb::AuthHeader),end=_AdminBackend.end(); libhtmlpp::HtmlString list,out; libhtmlpp::HtmlElement root=_IndexElement; libhtmlpp::HtmlElement *content=root.getElementbyID("content"); Domain domain; list <<"

DomainList:

"; while(rd"; }catch(AuthBackendError &e){ std::cerr << e.what() << std::endl; } } } list << "
" << ddat.getDomainName() << "
  • " << "Domainid: " << crdid << "
  • " << "
  • Storagetype: " << ddat.getStorageType() << "
  • " << "
  • Storageoptions: " << ddat.getStorageOptions() << "
  • " << "
"; content->appendChild(list.parse()); libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } void createDomain(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ libhttppp::HttpForm curform; curform.parse(curreq); if (curform.getBoundary()) { uuid_t uid; uuid_generate(uid); class DomainData ddat(uid); for (libhttppp::HttpForm::MultipartForm::Data* curformdat = curform.MultipartFormData.getFormData(); curformdat; curformdat = curformdat->nextData()) { if(curformdat->Value.empty()) continue; std::string name; int stortype=TextStorage; for(libhttppp::HttpForm::MultipartForm::Data::ContentDisposition *curdispo=curformdat->getDisposition(); curdispo; curdispo=curdispo->nextContentDisposition() ){ std::string tmp=curdispo->getKey(); std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c){ return std::tolower(c); }); if(tmp=="name") name=curdispo->getValue(); if(tmp=="filename"){ stortype=BinaryStorage; continue; } bool numeric=true; for(auto t=curformdat->Value.begin(); t!=curformdat->Value.end(); ++t){ if(!std::isdigit(*t)){ numeric=false; break; } } if(numeric){ stortype=StorageType::IntStorage; } } if(name.empty() || stortype == EmptyStorage) continue; struct AuthData::Record dodat; memset(&dodat,0,sizeof(AuthData::Record)); dodat.start=0xFE; uuid_copy(dodat.uuid,uid); dodat.type=UserData; dodat.storage=stortype; strcpy(dodat.fieldname,name.c_str()); if(dodat.storage==TextStorage){ curformdat->Value.push_back('\0'); dodat.datasize=curformdat->Value.size(); dodat.data=new char[dodat.datasize]; memcpy(dodat.data,curformdat->Value.data(), curformdat->Value.size()); ddat.Data->append(dodat); delete[] dodat.data; }else if(dodat.storage==IntStorage){ curformdat->Value.push_back('\0'); dodat.datasize=sizeof(int); dodat.data=(char*)new int; int val=atoi(curformdat->Value.data()); memcpy(dodat.data,&val, dodat.datasize); ddat.Data->append(dodat); delete (int*)dodat.data; }else { dodat.datasize=curformdat->Value.size(); dodat.data=new char[dodat.datasize]; memcpy(dodat.data,curformdat->Value.data(), dodat.datasize); ddat.Data->append(dodat); delete[] dodat.data; } } Domain domain; domain.create(_AdminBackend,&ddat); std::cout << "domain created!" << std::endl; } libhtmlpp::HtmlString form,out; libhtmlpp::HtmlElement root=_IndexElement; libhtmlpp::HtmlElement *content=root.getElementbyID("content"); form << "
" << "" << "" << "" << "" << "" << "" << "" << "" << "
"; content->insertChild(form.parse()); libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } void removeDomain(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ char did[255]; sscanf(curreq->getRequestURL(),"/settings/%[^/]/removedomain",did); Domain domain; uuid_t uuid; uuid_parse(did,uuid); domain.remove(_AdminBackend,uuid); libhttppp::HttpResponse rep; rep.setState(HTTP307); rep.setVersion(HTTPVERSION(1.1)); rep.setHeaderData("Location")->push_back("/settings/index"); rep.setContentType("text/html"); rep.send(curreq,nullptr,0); } void listGroups(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args,const char *url){ libhtmlpp::HtmlString grouplist,out,ddat; libhtmlpp::HtmlElement root=_IndexElement; libhtmlpp::HtmlElement *content=root.getElementbyID("content"),*domel=nullptr; Group group; domel=DomainChangeForm(curreq,url,_AdminBackend,ddat); if(!domel){ throw AuthBackendError("listGroups: cannot load doamin's!"); } char cdid[255]; uuid_t did; if(sscanf(curreq->getRequestURL(),"/settings/%[^/]",cdid)<0){ throw AuthBackendError("listGroups: wrong url!"); } DomainBackend dbackend(_AdminBackend); AuthBackend *backend=nullptr; if(strcmp(cdid,"admin") == 0 ){ backend=&_AdminBackend; }else if(uuid_parse(cdid,did) == 0 ){ backend=dbackend.data(did); }else{ throw AuthBackendError("listGroups: could not parse uuid!"); } size_t rd=sizeof(authdb::AuthHeader),end=backend->end(); content->appendChild(domel); grouplist << ""; content->appendChild(grouplist.parse()); libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } void createGroup(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args,const char *url){ } void SettingsController(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ _AdminBackend.lock(); char domain[255],url[255]; if(sscanf(curreq->getRequestURL(),"/settings/%[^/]/%s",domain,url)<0) throw AuthBackendError("wrong url!"); try { if(strncmp(url,"listusers",9)==0){ listUsers(curreq,tid,args,"listusers"); }else if(strncmp(url,"createuser",9)==0){ createUser(curreq,tid,args,"createuser"); }else if(strncmp(url,"removeuser",9)==0){ removeuser(curreq,tid,args); }else if(strncmp(url,"edituser",8)==0){ editUser(curreq,tid,args); }else if(strncmp(url,"listdomains",9)==0){ listDomains(curreq,tid,args); }else if(strncmp(url,"createdomain",12)==0){ createDomain(curreq,tid,args); }else if(strncmp(url,"removedomain",12)==0){ removeDomain(curreq,tid,args); }else if(strncmp(url,"listgroups",10)==0){ listGroups(curreq,tid,args,"listgroups"); }else if(strncmp(url,"creategroup",11)==0){ createGroup(curreq,tid,args,"creategroup"); }else{ libhtmlpp::HtmlElement root=_IndexElement; libhtmlpp::HtmlString out; libhtmlpp::print(&root,out,true); libhttppp::HttpResponse rep; rep.setContentType("text/html"); rep.setContentLength(out.size()); rep.send(curreq,out.c_str(),out.size()); } }catch(AuthBackendError &e){ libhttppp::HttpResponse rep; rep.setState(HTTP500); rep.setContentType("text/html"); rep.send(curreq,e.what(),strlen(e.what())); } _AdminBackend.unlock(); } void RequestEvent(libhttppp::HttpRequest *curreq, const int tid, ULONG_PTR args){ if(strncmp(curreq->getRequestURL(),"/settings",9)==0){ SettingsController(curreq,tid,args); }if(strncmp(curreq->getRequestURL(),"/getavatar/",11)==0){ getAvatar(curreq,tid,args); }else if(strncmp(curreq->getRequestURL(),"/api",4)==0){ }else if(strncmp(curreq->getRequestURL(),"/authdb.js",10)==0){ libhttppp::HttpResponse rep; rep.setContentType("text/javascript"); rep.send(curreq,_AuthJs.data(),_AuthJs.size()); }else{ libhttppp::HttpResponse rep; rep.setState(HTTP307); rep.setVersion(HTTPVERSION(1.1)); rep.setHeaderData("Location")->push_back("/settings/admin/index"); rep.setContentType("text/html"); rep.send(curreq,nullptr,0); } }; private: authdb::AuthBackend _AdminBackend; libhtmlpp::HtmlElement _IndexElement; libhtmlpp::HtmlPage _Indexpage; std::vector _AuthJs; }; int searchValue(authdb::AuthBackend &backend,const char*fieldname,const char *value){ authdb::AuthData::Record *user=new AuthData::Record; int rd=sizeof(authdb::AuthHeader),brd=rd; while(rd>backend.end()){ backend.setPos(rd); backend.read((unsigned char*)user,sizeof(AuthData::Record)); rd=backend.getPos(); if(strcmp(user->fieldname,fieldname) == 0){ user->data = new char[user->datasize]; backend.read((unsigned char*)user->data,user->datasize); if(strcmp(user->data,value) == 0){ delete[] user->data; goto VALUEFOUND; } delete[] user->data; } brd=rd; } VALUEFOUND: delete user; return brd; } AuthData::AuthData(const uuid_t id){ Data = new struct AuthData::Record; memset(Data,0,sizeof(AuthData::Record)); uuid_copy(Data->uuid,id); Data->start=0xFE; Data->storage=EmptyStorage; Data->type=DataType::EmptyData; Data->fieldname[0]='\0'; Data->data=nullptr; Data->datasize=0; _next=nullptr; } AuthData::AuthData(const AuthData &src) :AuthData(src.Data->uuid){ AuthData *dest=this; for(const AuthData *cursrc=&src; cursrc; cursrc=cursrc->next()){ memcpy(dest->Data,cursrc->Data,sizeof(AuthData::Record)); dest->Data->datasize=cursrc->Data->datasize; dest->Data->data=new char[dest->Data->datasize]; memcpy(dest->Data->data,cursrc->Data->data,cursrc->Data->datasize); if(cursrc->next()){ dest->_next=new AuthData(cursrc->Data->uuid); dest=dest->_next; } } } AuthData::~AuthData(){ delete Data; } AuthData *AuthData::next() const{ return _next; }; bool authdb::AuthData::empty(){ if(!Data->data) return true; return false; }; AuthData *AuthData::append(const AuthData &src){ AuthData *curec=this,*next=this; if(!curec->_next && curec->Data->datasize==0){ for(const AuthData *cursrc=&src; cursrc; cursrc=cursrc->next()){ next->append(*src.Data); if(cursrc->next()){ next->_next=new AuthData(Data->uuid); next=next->_next; } } return curec; } while(curec){ if(!curec->_next){ curec->_next=new AuthData(src); curec=curec->_next; break; } curec=curec->_next; }; return curec; } AuthData *AuthData::append(const AuthData::Record &src){ AuthData *curec=this; if(!curec->_next && curec->Data->datasize==0){ memcpy(curec->Data,&src,sizeof(AuthData::Record)); curec->Data->data=new char[curec->Data->datasize]; memcpy(curec->Data->data,src.data,curec->Data->datasize); return curec; } while(curec){ if(!curec->_next){ curec->_next=new AuthData(Data->uuid); curec=curec->_next; curec->append(src); break; } curec=curec->_next; }; return curec; } bool getRecord(authdb::AuthBackend &backend,AuthData &rec,int type){ bool found=false; int rd=sizeof(authdb::AuthHeader),end=backend.end(); AuthData *curec=&rec; while(rduuid) == 0 && cur.type == type){ cur.data=new char[cur.datasize]; backend.read((unsigned char*)cur.data,cur.datasize); rec.append(cur); delete[] cur.data; found=true; } } return found; } bool editRecord(AuthBackend &backend,AuthData &rec,int type){ AuthData old(rec.Data->uuid); std::vector changemap; //use fieldname; std::vector newmap; getRecord(backend,old,type); for(const AuthData *curdat=&rec; curdat; curdat=curdat->_next){ bool newentry=true; if(rec.Data->datasize==0) continue; for(const AuthData *olddat=&old; olddat; olddat=olddat->_next){ if(uuid_compare(olddat->Data->uuid,curdat->Data->uuid)==0 && strcmp(olddat->Data->fieldname,curdat->Data->fieldname)==0 ){ size_t end = olddat->Data->datasize; if(end!=curdat->Data->datasize){ changemap.push_back(curdat->Data); }else{ for(size_t i=0; iData->data[i]!=curdat->Data->data[i]){ changemap.push_back(curdat->Data); break; } } } newentry=false; } } if(newentry){ newmap.push_back(curdat->Data); } } for(auto newel : newmap){ backend.setPos(backend.end()); backend.write((unsigned char*)newel,sizeof(AuthData::Record));; backend.write((unsigned char*)newel->data,newel->datasize); } const unsigned char zero = 0; for(auto chel : changemap){ size_t rd=sizeof(authdb::AuthHeader),end=backend.end(); while(rduuid,rec.Data->uuid)==0 && strcmp(rdrec->fieldname,chel->fieldname)==0){ backend.setPos(backend.end()); backend.write((const unsigned char*)chel,sizeof(AuthData::Record)); backend.write((const unsigned char*)chel->data,chel->datasize); size_t dsize=rdrec->datasize; memset(rdrec,0,sizeof(AuthData::Record)); rdrec->start = 0xFE; rdrec->datasize=dsize; backend.setPos(rd); backend.write((const unsigned char*)rdrec,sizeof(AuthData::Record)); for(size_t i =0; idatasize; ++i){ backend.write(&zero,1); } rd=backend.getPos(); }else{ rd=backend.getPos()+rdrec->datasize; } delete rdrec; } } if(!changemap.empty() || !newmap.empty()) return true; return false; } void delRecord(AuthBackend &backend,const uuid_t uid,int type){ size_t end=backend.end(),rd=sizeof(AuthHeader); if(!uid) throw AuthBackendError("user info uid required!"); while(rddatasize; if(uuid_compare(uid,cur->uuid) == 0 && type == cur->type){ size_t dsize=cur->datasize; memset(cur,0,sizeof(AuthData::Record)); cur->start = 0xFE; cur->datasize=dsize; backend.setPos(wr); backend.write((unsigned char*)cur,sizeof(AuthData::Record)); const unsigned char zero=0; for(size_t i=0; igetValue()); authdb::AuthBackend backend(authdb::AuthBackendType::File, config.getValue(config.getKey("/AUTHDB/ADMINDB/PATH"),0), "admin.local" ); try { if(backend.end()<=sizeof(authdb::AuthHeader)){ authdb::initalized=false; } libhttppp::HttpD httpd( config.getValue(config.getKey("/AUTHDB/BIND"),0), config.getIntValue(config.getKey("/AUTHDB/PORT"),0), config.getIntValue(config.getKey("/AUTHDB/MAXCONN"),0), nullptr, nullptr ); authdb::AuthDB authdb(backend,httpd.getServerSocket()); authdb.runEventloop(); }catch(authdb::AuthBackendError &e){ std::cerr << e.what() << std::endl; } }