/** * ======================== legal notice ====================== * * File: Credentials.cc * Created: 3. Juli 2012, 14 * Author: Geronimo * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling * * CMP - compound media player * * is a client/server mediaplayer intended to play any media from any workstation * without the need to export or mount shares. cmps is an easy to use backend * with a (ready to use) HTML-interface. Additionally the backend supports * authentication via HTTP-digest authorization. * cmpc is a client with vdr-like osd-menues. * * Copyright (c) 2012 Reinhard Mantey, some rights reserved! * published under Creative Commons by-sa * For details see http://creativecommons.org/licenses/by-sa/3.0/ * * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp * * -------------------------------------------------------------- */ #include #include #include #include cCredentials Credentials; static const char *appRealm = NULL; cCredentials::cCredentials() { } cCredentials::~cCredentials() { Clear(); } void cCredentials::Clear() { iterator it = internalMap.begin(); while (it != internalMap.end()) { delete it->second; ++it; } } const char *cCredentials::ApplicationRealm() const { return appRealm; } const cPrincipal *cCredentials::FindPrincipal(const char* Name, const char* Realm) { std::string tmp = Name; cPrincipal *rv = internalMap[tmp]; if (!strcmp(rv->Name(), Name) && !strcmp(rv->Realm(), Realm)) return rv; return NULL; } void cCredentials::SetApplicationRealm(const char* ApplicationRealm) { appRealm = ApplicationRealm; } void cCredentials::Put(const char* Key, cPrincipal* p) { internalMap[Key] = p; } cPrincipal *cCredentials::Get(const char* Key) { iterator it = internalMap.find(Key); if (it != internalMap.end()) return it->second; return NULL; } int cCredentials::Load(const char *FileName) { char buf[256]; FILE *fp = fopen(FileName, "r"); cPrincipal *principal = NULL; char *chunk = buf; int principalsProcessed = 0; int bytesRead = 0; if (!fp) { //TODO: verbose message? return 0; } while ((bytesRead = fread(chunk, sizeof(char), sizeof(buf) - (chunk - buf), fp)) > 0) { char *endOfLine = index(buf, '\n'); while (chunk && endOfLine) { principal = parsePrincipal(chunk, endOfLine - chunk); if (!principal) break; std::string userid = principal->Name(); internalMap[userid] = principal; ++principalsProcessed; chunk = endOfLine < (buf + sizeof(buf)) ? endOfLine + 1 : NULL; endOfLine = index(chunk, '\n'); } // shift rest of buffer down and read a smaller chunk if (chunk && !endOfLine) { int rest = sizeof(buf) - (chunk - buf); memmove(buf, chunk, rest); chunk = buf + rest; } } fclose(fp); return principalsProcessed; } cPrincipal *cCredentials::parsePrincipal(char* buf, size_t bufSize) ///< format is: name:hash:age:extendedInfo { if (!buf || !*buf || bufSize < 30) return NULL; cPrincipal *rv = NULL; char *hash = index(buf, ':') + 1; char *age = index(hash, ':') + 1; char *xi = index(age, ':') + 1; if (hash == (char *)1 || !*hash) return NULL; if (age == (char *)1 || !*age) return NULL; if (xi == (char *)1 || !*xi) return NULL; *(hash - 1) = 0; *(age - 1) = 0; *(xi - 1) = 0; *(buf + bufSize - 1) = 0; rv = new cPrincipal(buf, ApplicationRealm()); if (rv) { rv->SetHash(hash); rv->SetAge(atoi(age)); rv->SetExtendedInfo(xi); } return rv; } int cCredentials::Store(const char* FileName) { FILE *fp = fopen(FileName, "w"); cPrincipal *p; int principalsProcessed = 0; if (!fp) { //TODO: verbose message? return 0; } cCredentials::const_iterator principals = begin(); while (principals != end()) { p = principals->second; fprintf(fp, "%s:%s:%d:%s\n", p->Name(), p->Hash(), p->Age(), p->ExtendedInfo() ? p->ExtendedInfo() : " "); ++principalsProcessed; ++principals; } fclose(fp); return principalsProcessed; }