]> www.vanbest.org Git - sasc-ng.git/commitdiff
save keys back to SoftCam.Key. ca.cache will die
authormirv <unknown>
Thu, 3 Jan 2008 14:12:52 +0000 (15:12 +0100)
committermirv <unknown>
Thu, 3 Jan 2008 14:12:52 +0000 (15:12 +0100)
cam.c
cam.h
data.c
data.h
sc.c
sc.h

diff --git a/cam.c b/cam.c
index fbe81db5dfdf47f4e5a9bb65d03484e9a4ff3ffd..047460382fe605a32fc5ef23d9d8b76399fd360b 100644 (file)
--- a/cam.c
+++ b/cam.c
@@ -1444,12 +1444,12 @@ char *cCam::CurrentKeyStr(int num)
   return 0;
 }
 
-bool cCam::Active(void)
+bool cCam::Active(bool log)
 {
   cMutexLock lock(this);
   for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler))
     if(!handler->IsIdle()) {
-      PRINTF(L_GEN_INFO,"handler %s on card %d is not idle",handler->Id(),cardNum);
+      if(log) PRINTF(L_GEN_INFO,"handler %s on card %d is not idle",handler->Id(),cardNum);
       return true;
       }
   return false;
diff --git a/cam.h b/cam.h
index 3471872d5d5cc30821b9be8f3903367669857ea0..18e6b88ac4e1dabd8df40c8acba5a3b91e9683d7 100644 (file)
--- a/cam.h
+++ b/cam.h
@@ -127,7 +127,7 @@ public:
   void AddHook(cLogHook *hook);
   bool TriggerHook(int id);
   // Plugin API
-  bool Active(void);
+  bool Active(bool log);
   void HouseKeeping(void);
   void Tune(const cChannel *channel);
   void PostTune(void);
diff --git a/data.c b/data.c
index 84cce8f3aab064190d2065e01ef8060d379e8344..2b6a7771431ddfa303ef21463b8dc13513026417 100644 (file)
--- a/data.c
+++ b/data.c
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
-#include <vdr/tools.h>
-
 #include "data.h"
 #include "misc.h"
 #include "scsetup.h"
@@ -142,6 +141,278 @@ cFileMap *cFileMaps::GetFileMap(const char *name, const char *domain, bool rw)
   return fm;  
 }
 
+// -- cStructItem --------------------------------------------------------------
+
+cStructItem::cStructItem(void)
+{
+  comment=0; deleted=special=false;
+}
+
+cStructItem::~cStructItem()
+{
+  free(comment);
+}
+
+void cStructItem::SetComment(const char *com)
+{
+  free(comment);
+  comment=strdup(com);
+}
+
+bool cStructItem::Save(FILE *f)
+{
+  fprintf(f,"%s%s\n",*ToString(false),comment?comment:"");
+  return ferror(f)==0;
+}
+
+// -- cCommentItem -------------------------------------------------------------
+
+class cCommentItem : public cStructItem {
+public:
+  cCommentItem(void);
+  virtual cString ToString(bool hide=false) { return ""; }
+  };
+
+cCommentItem::cCommentItem(void)
+{
+  SetSpecial();
+}
+
+// -- cStructLoader ------------------------------------------------------------
+
+cStructLoader::cStructLoader(const char *Type, const char *Filename, bool rw, bool miok, bool wat, bool verb)
+:lock(true)
+{
+  path=0; mtime=0; modified=loaded=disabled=false;
+  type=Type; filename=Filename;
+  readwrite=rw; missingok=miok; watch=wat; verbose=verb;
+  cStructLoaders::Register(this);
+}
+
+cStructLoader::~cStructLoader()
+{
+  free(path);
+}
+
+void cStructLoader::AddItem(cStructItem *n, const char *com, cStructItem *ref)
+{
+  n->SetComment(com);
+  ListLock(true);
+  cStructItem *a=0;
+  if(ref) { // insert before reference
+    for(a=First(); a; a=Next(a))
+      if(Next(a)==ref) break;
+    }
+  if(!a) { // insert before first non-special
+    for(a=First(); a;) {
+      cStructItem *nn=Next(a);
+      if(nn && !nn->Special()) break;
+      a=nn;
+      }
+    }
+  Add(n,a);
+  Modified();
+  ListUnlock();
+}
+
+void cStructLoader::DelItem(cStructItem *d, bool keep)
+{
+  if(d) {
+    d->Delete();
+    if(keep) {
+      cStructItem *n=new cCommentItem;
+      n->SetComment(cString::sprintf(";%s%s",*d->ToString(false),d->Comment()?d->Comment():""));
+      Add(n,d);
+      }
+    Modified();
+    }
+}
+
+void cStructLoader::SetCfgDir(const char *cfgdir)
+{
+  free(path);
+  path=strdup(AddDirectory(cfgdir,filename));
+}
+
+time_t cStructLoader::MTime(void)
+{
+  struct stat64 st;
+  if(stat64(path,&st)!=0) {
+    PRINTF(L_GEN_ERROR,"failed fstat %s: %s",path,strerror(errno));
+    PRINTF(L_GEN_WARN,"automatic reload of %s disabled",path);
+    st.st_mtime=0;
+    }
+  return st.st_mtime;
+}
+
+bool cStructLoader::Load(bool reload)
+{
+  if(reload && !watch) return true;
+  FILE *f=fopen(path,"r");
+  if(f) {
+    int curr_mtime=MTime();
+    if(access(path,R_OK|W_OK)!=0) {
+      if(errno!=EACCES)
+        PRINTF(L_GEN_ERROR,"failed access %s: %s",path,strerror(errno));
+      PRINTF(L_GEN_WARN,"no write permission on %s. Changes will not be saved!",path);
+      readwrite=false;
+      }
+
+    loaded=true;
+    ListLock(true);
+    bool doload=false;
+    if(!reload) {
+      Clear(); Modified(false);
+      mtime=curr_mtime;
+      doload=true;
+      }
+    else if(mtime && mtime<curr_mtime) {
+      PRINTF(L_CORE_LOAD,"detected change of %s",path);
+      if(IsModified())
+        PRINTF(L_CORE_LOAD,"discarding in-memory changes");
+      for(cStructItem *a=First(); a; a=Next(a)) DelItem(a);
+      Modified(false);
+      mtime=curr_mtime;
+      doload=true;
+      }
+    if(doload) {
+      PRINTF(L_GEN_INFO,"loading %s from %s",type,path);
+      int lineNum=0, num=0;
+      char buff[4096];
+      while(fgets(buff,sizeof(buff),f)) {
+        lineNum++;
+        if(!index(buff,'\n') && !feof(f)) {
+          PRINTF(L_GEN_ERROR,"file %s readbuffer overflow line#%d",path,lineNum);
+          loaded=false;
+          break;
+          }
+        strreplace(buff,'\n',0); strreplace(buff,'\r',0); // chomp
+        bool hasContent=false;
+        char *ls;
+        for(ls=buff; *ls; ls++) {
+          if(*ls==';' || *ls=='#') {             // comment
+            if(hasContent)
+              while(ls>buff && ls[-1]<=' ') ls--; // search back to non-whitespace
+            break;
+            }
+          if(*ls>' ') hasContent=true;           // line contains something usefull
+          }
+        cStructItem *it=0;
+        if(hasContent) {
+          char save=*ls;
+          *ls=0; it=ParseLine(buff); *ls=save;
+          if(!it) {
+            PRINTF(L_GEN_ERROR,"file %s has error in line #%d",path,lineNum);
+            ls=buff;
+            }
+          else num++;
+          }
+        else ls=buff;
+        if(!it) it=new cCommentItem;
+        if(it) {
+          it->SetComment(ls);
+          Add(it);
+          }
+        else {
+          PRINTF(L_GEN_ERROR,"out of memory loading file %s",path);
+          loaded=false;
+          break;
+          }
+        }
+      PRINTF(L_CORE_LOAD,"loaded %d %s from %s",num,type,path);
+      PostLoad();
+      }
+    ListUnlock();
+
+    fclose(f);
+    }
+  else {
+    if(verbose) PRINTF(L_GEN_ERROR,"failed open %s: %s",path,strerror(errno));
+    loaded=missingok;
+    }
+  if(!loaded) PRINTF(L_CORE_LOAD,"loading %s terminated with error. Changes will not be saved!",path);
+  return loaded;
+}
+
+void cStructLoader::Purge(void)
+{
+  ListLock(true);
+  for(cStructItem *it=First(); it;) {
+    cStructItem *n=Next(it);
+    if(it->Deleted()) Del(it);
+    it=n;
+    }
+  ListUnlock();
+}
+
+void cStructLoader::Save(void)
+{
+  ListLock(false);
+  if(readwrite && loaded && IsModified()) {
+    cSafeFile f(path);
+    if(f.Open()) {
+      for(cStructItem *it=First(); it; it=Next(it))
+        if(!it->Deleted() && !it->Save(f)) break;
+      f.Close();
+      mtime=MTime();
+      PRINTF(L_CORE_LOAD,"saved %s to %s",type,path);
+      Modified(false);
+      }
+    }
+  ListUnlock();
+}
+
+// -- cStructLoaders -----------------------------------------------------------
+
+#define RELOAD_TIMEOUT  20000
+#define PURGE_TIMEOUT   60000
+#define SAVE_TIMEOUT     5000
+
+cStructLoader *cStructLoaders::first=0;
+cTimeMs cStructLoaders::lastReload;
+cTimeMs cStructLoaders::lastPurge;
+cTimeMs cStructLoaders::lastSave;
+
+void cStructLoaders::Register(cStructLoader *ld)
+{
+  PRINTF(L_CORE_DYN,"structloaders: registering loader %s",ld->type);
+  ld->next=first;
+  first=ld;
+}
+
+void cStructLoaders::SetCfgDir(const char *cfgdir)
+{
+  for(cStructLoader *ld=first; ld; ld=ld->next)
+    ld->SetCfgDir(cfgdir);
+}
+
+void cStructLoaders::Load(bool reload)
+{
+  if(!reload || lastReload.TimedOut()) {
+    for(cStructLoader *ld=first; ld; ld=ld->next)
+      if(!ld->disabled) ld->Load(reload);
+    lastReload.Set(RELOAD_TIMEOUT);
+    }
+}
+
+void cStructLoaders::Save(void)
+{
+  if(lastSave.TimedOut()) {
+    for(cStructLoader *ld=first; ld; ld=ld->next)
+      if(!ld->disabled) ld->Save();
+    lastSave.Set(SAVE_TIMEOUT);
+    }
+}
+
+void cStructLoaders::Purge(void)
+{
+  if(lastPurge.TimedOut()) {
+    for(cStructLoader *ld=first; ld; ld=ld->next)
+      if(!ld->disabled) ld->Purge();
+    lastPurge.Set(PURGE_TIMEOUT);
+    }
+}
+
 // -- cConfRead ----------------------------------------------------------------
 
 bool cConfRead::ConfRead(const char *type, const char *filename, bool missingok)
@@ -460,7 +731,6 @@ void cEcmInfo::SetName(const char *Name)
 
 cPlainKey::cPlainKey(bool CanSupersede)
 {
-  au=del=false;
   super=CanSupersede;
 }
 
@@ -480,12 +750,6 @@ int cPlainKey::IdSize(void)
   return id>0xFF ? (id>0xFFFF ? 6 : 4) : 2;
 }
 
-bool cPlainKey::Save(FILE *f)
-{
-  fprintf(f,"%s\n",*ToString(false));
-  return ferror(f)==0;
-}
-
 cString cPlainKey::ToString(bool hide)
 {
   return cString::sprintf(hide ? "%c %.*X %s %.4s..." : "%c %.*X %s %s",type,IdSize(),id,*PrintKeyNr(),*Print());
@@ -654,11 +918,8 @@ cPlainKeys keys;
 cPlainKeyType *cPlainKeys::first=0;
 
 cPlainKeys::cPlainKeys(void)
-:cLoader("KEY")
-//,cThread("ExternalAU")
-{
-  mark=0;
-}
+:cStructList<cPlainKey>("keys",KEY_FILE,true,true,true,true)
+{}
 
 void cPlainKeys::Register(cPlainKeyType *pkt, bool Super)
 {
@@ -683,81 +944,91 @@ cPlainKey *cPlainKeys::FindKey(int Type, int Id, int Keynr, int Size, cPlainKey
 
 cPlainKey *cPlainKeys::FindKeyNoTrig(int Type, int Id, int Keynr, int Size, cPlainKey *key)
 {
-  Lock();
-  if(key) key=Next(key); else key=First();
-  while(key) {
-    if(!key->IsInvalid() && key->type==Type && key->id==Id && key->keynr==Keynr && (Size<0 || key->Size()==Size)) break;
-    key=Next(key);
-    }
-  Unlock();
+  ListLock(false);
+  for(key=key?Next(key):First(); key; key=Next(key))
+    if(key->Valid() && key->type==Type && key->id==Id && key->keynr==Keynr && (Size<0 || key->Size()==Size))
+      break;
+  ListUnlock();
   return key;
 }
 
-bool cPlainKeys::NewKey(int Type, int Id, int Keynr, void *Key, int Keylen)
+cPlainKey *cPlainKeys::NewFromType(int type)
+{
+  cPlainKeyType *pkt;
+  for(pkt=first; pkt; pkt=pkt->next)
+    if(pkt->type==type) return pkt->Create();
+  PRINTF(L_CORE_LOAD,"unknown key type '%c', adding dummy",type);
+  pkt=new cPlainKeyTypeDummy(type);
+  return pkt->Create();
+}
+
+bool cPlainKeys::AddNewKey(cPlainKey *nk, const char *reason)
 {
-  cPlainKey *k=0;
-  while((k=FindKeyNoTrig(Type,Id,Keynr,-1,k)))
-    if(k->Cmp(Key,Keylen)) return false;
+  cPlainKey *k;
+  for(k=0; (k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k)); )
+    if(k->Cmp(nk)) return false;
 
+  cPlainKey *ref=0;
+  PRINTF(L_GEN_INFO,"key update for ID %s",*nk->ToString(true));
+  for(k=0; (k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,nk->Size(),k)); ) {
+    if(nk->CanSupersede()) {
+      PRINTF(L_GEN_INFO,"supersedes key: %s",*k->ToString(true));
+      DelItem(k,true);
+      }
+    if(!ref) ref=k;
+    }
+  char stamp[32], com[256];
+  time_t tt=time(0);
+  struct tm tm_r;
+  strftime(stamp,sizeof(stamp),"%d.%m.%Y %T",localtime_r(&tt,&tm_r));
+  snprintf(com,sizeof(com)," ; %s %s",reason,stamp);
+  AddItem(nk,com,ref);
+  return true;
+}
+
+bool cPlainKeys::NewKey(int Type, int Id, int Keynr, void *Key, int Keylen)
+{
   cPlainKey *nk=NewFromType(Type);
   if(nk) {
     nk->Set(Type,Id,Keynr,Key,Keylen);
-    AddNewKey(nk,2,true);
-    return true;
+    return AddNewKey(nk,"from AU");
     }
-  else PRINTF(L_GEN_ERROR,"no memory for new key ID %c %.2x!",Type,Id);
   return false;
 }
 
-void cPlainKeys::AddNewKey(cPlainKey *nk, int mode, bool log)
+bool cPlainKeys::NewKeyParse(char *line, const char *reason)
 {
-  if(mode>=1) {
-    nk->SetAuto();
-    if(log) PRINTF(L_GEN_INFO,"key update for ID %s",*nk->ToString(true));
-    if(nk->CanSupersede()) {
-      cPlainKey *k=0;
-      while((k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,nk->Size(),k))) {
-        if(!k->IsInvalid()) {
-          k->SetInvalid();
-          if(k->IsAuto()) Modified();
-          if(log) PRINTF(L_GEN_INFO,"supersedes key: %s%s",*k->ToString(true),k->IsAuto()?" (auto)":"");
-          }
-        }
-      }
-    }
-  Lock();
-  switch(mode) {
-    case 0: Add(nk); break;
-    case 1: if(!mark) Ins(nk); else Add(nk,mark);
-            mark=nk;
-            break;
-    case 2: Ins(nk); Modified(); break;
-    }
-  Unlock();
-}
-
-bool cPlainKeys::Load(const char *cfgdir)
-{
-  Lock();
-  Clear(); mark=0;
-  cString cname=AddDirectory(cfgdir,KEY_FILE);
-  ConfRead("keys",cname);
-  int n=Count();
-  PRINTF(L_CORE_LOAD,"loaded %d keys from %s",n,*cname);
-  if(n && LOG(L_CORE_KEYS)) {
-    cPlainKey *dat=First();
-    while(dat) {
-      if(!dat->IsInvalid()) PRINTF(L_CORE_KEYS,"keys %s",*dat->ToString(false));
-      dat=Next(dat);
-      }
+  cPlainKey *nk=ParseLine(line);
+  return nk && AddNewKey(nk,reason);
+}
+
+cPlainKey *cPlainKeys::ParseLine(char *line)
+{
+  char *s=skipspace(line);
+  cPlainKey *k=NewFromType(toupper(*s));
+  if(k && !k->Parse(line)) { delete k; k=0; }
+  return k;
+}
+
+cString cPlainKeys::KeyString(int Type, int Id, int Keynr)
+{
+  cPlainKey *pk=NewFromType(Type);
+  if(pk) {
+    pk->type=Type; pk->id=Id; pk->keynr=Keynr;
+    return cString::sprintf("%c %.*X %s",Type,pk->IdSize(),Id,*pk->PrintKeyNr());
     }
-  Unlock();
-  return (n!=0);
+  return "unknown";
+}
+
+void cPlainKeys::PostLoad(void)
+{
+  if(Count() && LOG(L_CORE_KEYS))
+    for(cPlainKey *dat=First(); dat; dat=Next(dat))
+      if(dat->Valid()) PRINTF(L_CORE_KEYS,"keys %s",*dat->ToString(false));
 }
 
 void cPlainKeys::HouseKeeping(void)
 {
-  cLoaders::SaveCache();
   if(trigger.TimedOut()) {
     trigger.Set(EXT_AU_INT);
     if(externalAU) PRINTF(L_CORE_AUEXTERN,"triggered from housekeeping");
@@ -779,21 +1050,6 @@ void cPlainKeys::ExternalUpdate(void)
     }
 }
 
-bool cPlainKeys::NewKeyParse(const char *line)
-{
-  cPlainKey *nk=NewFromType(toupper(line[0]));
-  if(nk && nk->Parse(line)) {
-    cPlainKey *k=0;
-    while((k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k)))
-      if(k->Cmp(nk)) break;
-    if(!k) {
-      AddNewKey(nk,2,true);
-      return true;
-      }
-    }
-  return false;
-}
-
 void cPlainKeys::Action(void)
 {
   last.Set(EXT_AU_MIN);
@@ -805,59 +1061,9 @@ void cPlainKeys::Action(void)
     while(fgets(buff,sizeof(buff),pipe)) {
       char *line=skipspace(stripspace(buff));
       if(line[0]==0 || line[0]==';' || line[0]=='#') continue;
-      NewKeyParse(line);
+      NewKeyParse(line,"from ExtAU");
       }
     }
   pipe.Close();
   PRINTF(L_CORE_AUEXTERN,"done (elapsed %d)",(int)start.Elapsed());
 }
-
-cPlainKey *cPlainKeys::NewFromType(int type)
-{
-  cPlainKeyType *pkt=first;
-  while(pkt) {
-    if(pkt->type==type) return pkt->Create();
-    pkt=pkt->next;
-    }
-  PRINTF(L_CORE_LOAD,"unknown key type '%c', adding dummy",type);
-  pkt=new cPlainKeyTypeDummy(type);
-  return pkt->Create();
-}
-
-cString cPlainKeys::KeyString(int Type, int Id, int Keynr)
-{
-  cPlainKey *pk=NewFromType(Type);
-  if(pk) {
-    pk->type=Type; pk->id=Id; pk->keynr=Keynr;
-    return cString::sprintf("%c %.*X %s",Type,pk->IdSize(),Id,*pk->PrintKeyNr());
-    }
-  return "unknown";
-}
-
-bool cPlainKeys::ParseLine(const char *line, bool fromCache)
-{
-  char *s=skipspace(line);
-  cPlainKey *k=NewFromType(toupper(*s));
-  if(k) {
-    if(k->Parse((char *)line)) AddNewKey(k,fromCache?1:0,false);
-    else delete k;
-    return true;
-    }
-  return false;
-}
-
-bool cPlainKeys::Save(FILE *f)
-{
-  bool res=true;
-  Lock();
-  cPlainKey *dat=First();
-  while(dat) {
-    if(dat->IsAuto() && !dat->IsInvalid()) {
-      if(!dat->Save(f)) { res=false; break; }
-      }
-    dat=Next(dat);
-    }
-  Modified(!res);
-  Unlock();
-  return res;
-}
diff --git a/data.h b/data.h
index 34bc84a272f106d2cceb872308bdaa4337f79c5c..1dbaadb81fd8b3d05bb332eb54a6ed5a98a26b3b 100644 (file)
--- a/data.h
+++ b/data.h
 
 #include <vdr/thread.h>
 #include <vdr/tools.h>
+
 #include "misc.h"
 
+class cStructLoaders;
 class cLoaders;
 class cPidFilter;
 class cPlainKeys;
@@ -65,6 +67,88 @@ public:
 
 extern cFileMaps filemaps;
 
+//--------------------------------------------------------------
+
+class cStructItem : public cSimpleItem {
+private:
+  char *comment;
+  bool deleted, special;
+protected:
+  void SetSpecial(void) { special=true; }
+public:
+  cStructItem(void);
+  virtual ~cStructItem();
+  virtual cString ToString(bool hide=false)=0;
+  bool Save(FILE *f);
+  //
+  void SetComment(const char *com);
+  const char *Comment(void) const { return comment; }
+  void Delete(void) { deleted=true; }
+  bool Deleted(void) const { return deleted; }
+  bool Special(void) const { return special; }
+  bool Valid(void) const { return !deleted && !special; }
+  };
+
+//--------------------------------------------------------------
+
+class cStructLoader : public cSimpleList<cStructItem> {
+friend class cStructLoaders;
+private:
+  cStructLoader *next;
+  //
+  cRwLock lock;
+  const char *type, *filename;
+  char *path;
+  time_t mtime;
+  bool modified, readwrite, missingok, loaded, disabled, watch, verbose;
+  //
+  time_t MTime(void);
+protected:
+  virtual cStructItem *ParseLine(char *line)=0;
+  void Modified(bool mod=true) { modified=mod; }
+  bool IsModified(void) const { return modified; }
+  void ListLock(bool rw) { lock.Lock(rw); }
+  void ListUnlock(void) { lock.Unlock(); }
+  virtual void PostLoad(void) {}
+public:
+  cStructLoader(const char *Type, const char *Filename, bool rw, bool miok, bool wat, bool verb);
+  virtual ~cStructLoader();
+  void AddItem(cStructItem *n, const char *com, cStructItem *ref);
+  void DelItem(cStructItem *d, bool keep=false);
+  //
+  void SetCfgDir(const char *cfgdir);
+  bool Load(bool reload);
+  void Save(void);
+  void Purge(void);
+  void Disable(void) { disabled=true; }
+  };
+
+//--------------------------------------------------------------
+
+template<class T> class cStructList : public cStructLoader {
+public:
+  cStructList<T>(const char *Type, const char *Filename, bool rw, bool miok, bool wat, bool verb):cStructLoader(Type,Filename,rw,miok,wat,verb) {}
+  T *First(void) const { return (T *)cStructLoader::First(); }
+  T *Last(void) const { return (T *)cStructLoader::Last(); }
+  T *Next(const T *item) const { return (T *)cStructLoader::Next(item); }
+  };
+
+//--------------------------------------------------------------
+
+class cStructLoaders {
+friend class cStructLoader;
+private:
+  static cStructLoader *first;
+  static cTimeMs lastReload, lastPurge, lastSave;
+  //
+  static void Register(cStructLoader *ld);
+public:
+  static void SetCfgDir(const char *cfgdir);
+  static void Load(bool reload);
+  static void Save(void);
+  static void Purge(void);
+  };
+
 // ----------------------------------------------------------------
 
 class cConfRead {
@@ -166,16 +250,12 @@ public:
 
 class cMutableKey;
 
-class cPlainKey : public cSimpleItem {
+class cPlainKey : public cStructItem {
 friend class cPlainKeys;
 friend class cMutableKey;
 private:
-  bool au, del, super;
+  bool super;
 protected:
-  void SetInvalid(void) { del=true; }
-  void SetAuto(void) { au=true; }
-  bool IsAuto(void) const { return au; }
-  bool IsInvalid(void) const { return del; }
   void SetSupersede(bool val) { super=val; }
   bool CanSupersede(void) const { return super; }
   virtual int IdSize(void);
@@ -187,8 +267,7 @@ public:
   //
   cPlainKey(bool CanSupersede);
   virtual bool Parse(const char *line)=0;
-  bool Save(FILE *f);
-  cString ToString(bool hide=false);
+  virtual cString ToString(bool hide=false);
   virtual bool Cmp(void *Key, int Keylen)=0;
   virtual bool Cmp(cPlainKey *k)=0;
   virtual void Get(void *mem)=0;
@@ -252,31 +331,29 @@ public:
 
 extern const char *externalAU;
 
-class cPlainKeys : public cLoader, private cConfRead, private cThread, public cSimpleList<cPlainKey> {
+class cPlainKeys : private cThread, public cStructList<cPlainKey> {
 friend class cPlainKeyType;
 private:
   static cPlainKeyType *first;
-  cPlainKey *mark;
   cTimeMs trigger, last;
   cLastKey lastkey;
   //
   static void Register(cPlainKeyType *pkt, bool Super);
   cPlainKey *NewFromType(int type);
-  void AddNewKey(cPlainKey *nk, int mode, bool log);
+  bool AddNewKey(cPlainKey *nk, const char *reason);
   void ExternalUpdate(void);
 protected:
   virtual void Action(void);
+  virtual void PostLoad(void);
 public:
   cPlainKeys(void);
-  bool Load(const char *cfgdir);
-  virtual bool Save(FILE *f);
-  virtual bool ParseLine(const char *line, bool Au);
+  virtual cPlainKey *ParseLine(char *line);
   cPlainKey *FindKey(int Type, int Id, int Keynr, int Size, cPlainKey *key=0);
   cPlainKey *FindKeyNoTrig(int Type, int Id, int Keynr, int Size, cPlainKey *key=0);
   void Trigger(int Type, int Id, int Keynr);
   cString KeyString(int Type, int Id, int Keynr);
   bool NewKey(int Type, int Id, int Keynr, void *Key, int Keylen);
-  bool NewKeyParse(const char *line);
+  bool NewKeyParse(char *line, const char *reason);
   void HouseKeeping(void);
   };
 
diff --git a/sc.c b/sc.c
index 890939499ea43075f2b2772cd2ae62c05784d463..d2c0a07da93e6f82daa6be6376743eaa9de2efe3 100644 (file)
--- a/sc.c
+++ b/sc.c
@@ -911,7 +911,7 @@ eOSState cMenuSetupSc::ProcessKey(eKeys Key)
 
     case osUser9:
       state=osContinue;
-      if(!cSoftCAM::Active()) {
+      if(!cSoftCAM::Active(true)) {
         if(Interface->Confirm(tr("Really reload files?"))) {
           Store();
           cSoftCAM::Load(cfgdir);
@@ -1007,8 +1007,11 @@ bool cScSetup::Ignore(unsigned short caid)
 bool cSoftCAM::Load(const char *cfgdir)
 {
   ecmcache.Load();
-  if(Feature.KeyFile() && !keys.Load(cfgdir)) 
+  if(!Feature.KeyFile()) keys.Disable();
+  cStructLoaders::Load(false);
+  if(Feature.KeyFile() && keys.Count()<1)
     PRINTF(L_GEN_ERROR,"no keys loaded for softcam!");
+
   if(!cSystems::Init(cfgdir)) return false;
   if(Feature.SmartCard()) smartcards.LoadData(cfgdir);
   cLoaders::LoadCache(cfgdir);
@@ -1016,6 +1019,15 @@ bool cSoftCAM::Load(const char *cfgdir)
   return true;
 }
 
+void cSoftCAM::HouseKeeping(void)
+{
+  cLoaders::SaveCache();
+  if(Feature.KeyFile()) keys.HouseKeeping();
+  if(!Active(false)) cStructLoaders::Purge();
+  cStructLoaders::Load(true);
+  cStructLoaders::Save();
+}
+
 void cSoftCAM::Shutdown(void)
 {
   cSystems::Clean();
@@ -1034,11 +1046,11 @@ char *cSoftCAM::CurrKeyStr(int CardNum, int num)
   return str;
 }
 
-bool cSoftCAM::Active(void)
+bool cSoftCAM::Active(bool log)
 {
   for(int n=cDevice::NumDevices(); --n>=0;) {
     cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
-    if(dev && dev->Cam() && dev->Cam()->Active()) return true;
+    if(dev && dev->Cam() && dev->Cam()->Active(log)) return true;
     }
   return false;
 }
@@ -1247,9 +1259,11 @@ bool cScPlugin::Start(void)
 #if APIVERSNUM < 10507
   RegisterI18n(ScPhrases);
 #endif
-  filemaps.SetCfgDir(ConfigDirectory(cfgsub));
+  const char *cfgdir=ConfigDirectory(cfgsub);
+  filemaps.SetCfgDir(cfgdir);
+  cStructLoaders::SetCfgDir(cfgdir);
   ScSetup.Check();
-  if(!cSoftCAM::Load(ConfigDirectory(cfgsub))) return false;
+  if(!cSoftCAM::Load(cfgdir)) return false;
   if(Feature.SmartCard()) {
 #ifdef DEFAULT_PORT
     smartcards.AddPort(DEFAULT_PORT);
@@ -1359,7 +1373,7 @@ void cScPlugin::Housekeeping(void)
     cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
     if(dev && dev->Cam()) dev->Cam()->HouseKeeping();
     }
-  if(Feature.KeyFile()) keys.HouseKeeping();
+  cSoftCAM::HouseKeeping();
 }
 
 const char **cScPlugin::SVDRPHelpPages(void)
@@ -1383,7 +1397,7 @@ const char **cScPlugin::SVDRPHelpPages(void)
 cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
 {
   if(!strcasecmp(Command,"RELOAD")) {
-    if(cSoftCAM::Active()) {
+    if(cSoftCAM::Active(true)) {
       ReplyCode=550;
       return "Softcam active. Can't reload files now";
       }
@@ -1398,7 +1412,7 @@ cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &Re
     }
   else if(!strcasecmp(Command,"KEY")) {
     if(Option && *Option) {
-      if(keys.NewKeyParse(skipspace(Option)))
+      if(keys.NewKeyParse(skipspace(Option),"from SVDR"))
         return "Key update successfull";
       else {
         ReplyCode=901;
diff --git a/sc.h b/sc.h
index dcdcf4dea6e867c2af018b69e0f165f277db8ae0..da6f86283cf4f685743f89603e24c8e57b4761a8 100644 (file)
--- a/sc.h
+++ b/sc.h
@@ -28,9 +28,10 @@ class cLogHook;
 class cSoftCAM {
 public:
   static bool Load(const char *cfgdir);
+  static void HouseKeeping(void);
   static void Shutdown(void);
   //
-  static bool Active(void);
+  static bool Active(bool log);
   static char *CurrKeyStr(int CardNum, int num);
   static void SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on);
   static void AddHook(int CardNum, cLogHook *hook);