📄 system.c
字号:
/* * Softcam plugin to VDR (C++) * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */#include <stdlib.h>#include <string.h>#include <unistd.h>#include <vdr/tools.h>#include <vdr/i18n.h>#include "sc.h"#include "scsetup.h"#include "system.h"#include "data.h"#include "opts.h"#include "log-core.h"// --- cFeature ----------------------------------------------------------------#define MAX_PHRASES 10cFeature Feature;bool cFeature::keyfile=false;bool cFeature::smartcard=false;bool cFeature::network=false;int cFeature::pcount=0;const tI18nPhrase *cFeature::phrases[MAX_PHRASES];void cFeature::AddPhrases(const tI18nPhrase * const Phrases){ if(pcount<MAX_PHRASES) phrases[pcount++]=Phrases; else PRINTF(L_GEN_ERROR,"feature: too many phrases");}tI18nPhrase *cFeature::GetPhrases(void){ int num=1; for(int i=0; i<pcount; i++) { const tI18nPhrase *p=phrases[i]; for(; **p; p++) num++; } tI18nPhrase *all=MALLOC(tI18nPhrase,num); if(all) { tI18nPhrase *a=all; for(int i=0; i<pcount; i++) { const tI18nPhrase *p=phrases[i]; while(**p) { memcpy(a,p,sizeof(tI18nPhrase)); a++; p++; } } memset(a,0,sizeof(tI18nPhrase)); } return all;}void cFeature::NeedsKeyFile(void){ if(!keyfile) PRINTF(L_CORE_DYN,"feature: using feature KEYFILE"); keyfile=true;}void cFeature::NeedsSmartCard(void){ if(!smartcard) PRINTF(L_CORE_DYN,"feature: using feature SMARTCARD"); smartcard=true;}// -- cKeySnoop ----------------------------------------------------------------cKeySnoop::cKeySnoop(cSystem *Sys, int Type, int Id, int Keynr){ ok=false; sys=Sys; type=Type; id=Id; keynr=Keynr;}cKeySnoop::~cKeySnoop(){ if(!ok) sys->KeyFail(type,id,keynr);}void cKeySnoop::OK(cPlainKey *pk){ sys->KeyOK(pk); ok=true;}// -- cLogHook -----------------------------------------------------------------cLogHook::cLogHook(int Id, const char *Name){ id=Id; name=Name; bailOut=false;}// -- cSystem ------------------------------------------------------------------#define MAX_CHID 10struct EcmCheck { union { struct { bool startFlag; int current, chids[MAX_CHID]; } sys06; } caid; };int cSystem::foundKeys=0;int cSystem::newKeys=0;cSystem::cSystem(const char *Name, int Pri){ name=Name; pri=Pri; lastType=0; currentKeyStr[0]=0; doLog=true; cardNum=-1; logecm=0; check=new struct EcmCheck; memset(check,0,sizeof(struct EcmCheck)); // default config maxEcmTry=2; // try to get a key X times from the same ECM pid (default) hasLogger=false; needsLogger=false; local=true; needsDescrData=false; constant=false;}cSystem::~cSystem(){ delete check; if(logecm) cSoftCAM::SetLogStatus(cardNum,logecm,false); delete logecm;}void cSystem::StartLog(const cEcmInfo *ecm, int caid){ if(!logecm || logecm->caId!=caid) { if(logecm) cSoftCAM::SetLogStatus(cardNum,logecm,false); delete logecm; logecm=new cEcmInfo(ecm); logecm->caId=caid; logecm->emmCaId=0; cSoftCAM::SetLogStatus(cardNum,logecm,true); }}void cSystem::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned short sysId, const unsigned char *data, int len){ const int pid=WORD(data,2,0x1FFF); switch(sysId>>8) { case 0x01: // Seca style for(int p=2; p<len; p+=15) { cEcmInfo *n=new cEcmInfo(name,WORD(data,p,0x1FFF),sysId,WORD(data,p+2,0xFFFF)); if(data[p+4]==0xFF) n->AddData(&data[p+5],10); ecms->Add(n); } break; case 0x05: // Viaccess style for(int p=4; p<len; p+=2+data[p+1]) if(data[p]==0x14) ecms->Add(new cEcmInfo(name,pid,sysId,(data[p+2]<<16)|(data[p+3]<<8)|(data[p+4]&0xF0))); break; default: // default style { cEcmInfo *n=new cEcmInfo(name,pid,sysId,0); if(sysId==0x1234) { // BEV n->ecm_table=0x8e; n->emmCaId=0x1801; } ecms->Add(n); break; } }}void cSystem::ParseCAT(cPids *pids, const unsigned char *buffer){ if(buffer[0]==0x09) { int caid=WORD(buffer,2,0xFFFF); int pid=WORD(buffer,4,0x1FFF); switch(caid>>8) { case 0x01: // Seca style (82/84) if(buffer[1]>4) { pids->AddPid(pid,0x82,0xFF); // Unique updates for(int i=7, nn=buffer[6] ; nn ; nn--,i+=4) pids->AddPid(WORD(buffer,i,0x1FFF),0x84,0xFF); // Shared updates } break; case 0x05: // Viaccess style (88/8c/8d/8e) pids->AddPid(pid,0x8B,0xFE,0x07); // mismatching 89/8f break; case 0x0d: // Cryptoworks style (82/84/86/88/89) pids->AddPid(pid,0x80,0xFF,0x06); pids->AddPid(pid,0x88,0xFE); break; case 0x18: // Nagra style, Nagra1(82) Nagra2(82/83) pids->AddPid(pid,0x82,caid==0x1801 ? 0xFE:0xFF); break; default: // default style (82) pids->AddPid(pid,0x82,0xFF); break; } }}int cSystem::CheckECM(const cEcmInfo *ecm, const unsigned char *data, bool sync){ switch(ecm->caId>>8) { case 0x06: // Irdeto { const int cur=data[4]; const int max=data[5]; const int chid=WORD(data,6,0xFFFF); // if multiple channel id's, use current one only if(sync && ecm->caId==0x0604 && check->caid.sys06.current>0 && chid!=check->caid.sys06.current) { PRINTF(L_CORE_ECMPROC,"ecmcheck(%s): chid %04x != current %04x",name,chid,check->caid.sys06.current); return 2; } // search for fake channel id's on Stream if(!sync && max>0 && max<MAX_CHID) { if(cur==0) check->caid.sys06.startFlag=true; if(check->caid.sys06.startFlag) { if(cur<=max) check->caid.sys06.chids[cur]=chid; if(cur==max) { for(int i=0 ; i<max ; i++) { if(check->caid.sys06.chids[i]==0) { check->caid.sys06.startFlag=false; PRINTF(L_CORE_ECMPROC,"ecmcheck(%s): zero chid",name); return 1; } for(int j=i+1 ; j<=max ; j++) { if(check->caid.sys06.chids[i]==check->caid.sys06.chids[j]) { check->caid.sys06.startFlag=false; PRINTF(L_CORE_ECMPROC,"ecmcheck(%s): duplicate chid %04x",name,check->caid.sys06.chids[i]); return 1; } } } } } } break; } } return 0;}void cSystem::CheckECMResult(const cEcmInfo *ecm, const unsigned char *data, bool result){ switch(ecm->caId>>8) { case 0x06: // Irdeto check->caid.sys06.current=result ? WORD(data,6,0xFFFF) : 0; break; }}void cSystem::KeyOK(cPlainKey *pk){ if(pk->type!=lastType || pk->id!=lastId || pk->keynr!=lastKeynr) { lastType=pk->type; lastId=pk->id; lastKeynr=pk->keynr; strn0cpy(currentKeyStr,pk->ToString(),sizeof(currentKeyStr)); PRINTF(L_CORE_ECM,"system: using key %s",*pk->ToString(true)); doLog=true; }}void cSystem::KeyOK(const char *txt){ snprintf(currentKeyStr,sizeof(currentKeyStr),"%s (%s)\n",txt?txt:name,tr("undisclosed key")); doLog=true;}void cSystem::KeyFail(int type, int id, int keynr){ if(type!=lastType || id!=lastId || keynr!=lastKeynr) { lastType=type; lastId=id; lastKeynr=keynr; if(doLog) PRINTF(L_CORE_ECM,"system: no key found for %c %.2x %.2x",lastType,lastId,lastKeynr); }}// -- cSystemLink --------------------------------------------------------------cSystemLink::cSystemLink(const char *Name, int Pri){ name=Name; pri=Pri; opts=0; noFF=false; cSystems::Register(this);}cSystemLink::~cSystemLink(){ delete opts;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -