diff options
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 384 |
1 files changed, 271 insertions, 113 deletions
@@ -9,19 +9,18 @@ * */ -#include <getopt.h> #include <vdr/plugin.h> +#include <vdr/menu.h> #include "status.h" -#include "event.h" #include "setup.h" -#include "config.h" -#include "i18n.h" #include "control.h" -#include "common.h" -#include <vdr/interface.h> -static const char *VERSION = "0.0.4+201008090412"; +#include <fstream> +using namespace std; + + +static const char *VERSION = "0.1.0"; static const char *DESCRIPTION = trNOOP("Block unwanted shows by EPG title"); static const char *MAINMENUENTRY = trNOOP("(De)Block broadcast"); @@ -56,7 +55,7 @@ cPluginBlock::cPluginBlock(void): cPlugin(), mStatus(NULL) { - cEventBlock::LastTitle=(char*)"block_dummy_title1"; + cEventBlock::LastTitle=(char*)"vdr plugin block started"; } cPluginBlock::~cPluginBlock() @@ -66,7 +65,88 @@ cPluginBlock::~cPluginBlock() bool cPluginBlock::Initialize(void) { - return EventsBlock.Load(AddDirectory(cPlugin::ConfigDirectory(), "block.conf"), true, false); + char* blacklist_path=NULL; + int io_result=-1; + asprintf(&blacklist_path,"%s/%s",cPlugin::ConfigDirectory(),"block"); + io_result=mkdir (blacklist_path, S_IRWXU); + + if (errno==EEXIST) dsyslog("plugin-block: path '%s' seems to exist...ok.",blacklist_path); + else if (errno==EPERM) dsyslog("plugin-block: ERROR: Permission denied accessing '%s'",blacklist_path); + else if (io_result==0) dsyslog("plugin-block: path '%s' was created...ok.",blacklist_path); + else dsyslog("plugin-block: ERROR: Accessing '%s'! Doesn't seem to exist though permissions seem to be ok.",blacklist_path); + + char* blacklist_file=NULL; + + asprintf(&blacklist_file,"%s/block.conf",blacklist_path); //block.conf in new place (config/block/block.conf) ? + io_result=access(blacklist_file,F_OK); + + if (io_result==-1) //not there lets check the old places + { + dsyslog("plugin-block: '%s' doesn't exist. Checking old paths.",blacklist_file); + char* source_file=NULL; + asprintf(&source_file,"%s/block.conf",cPlugin::ConfigDirectory()); + io_result=access(source_file,F_OK); + if (io_result==-1) //also no file config/block.conf (old path) + { + dsyslog("plugin-block: '%s' doesn't exist. Looking for taste.conf.",source_file); + source_file=NULL; + asprintf(&source_file,"%s/taste.conf",cPlugin::ConfigDirectory()); + io_result=access(source_file,F_OK); + if (io_result==-1) // config/taste.conf also does not exist (very old path) + { + dsyslog("plugin-block: '%s' doesn't exist. Giving up.",source_file); + dsyslog("plugin-block: WARNING: No block.conf or taste.conf found!"); + source_file=NULL; + } + } + if (source_file!=NULL) + { + dsyslog("plugin-block: source %s, dest %s",source_file,blacklist_file); + ifstream infile(source_file); + ofstream outfile(blacklist_file); + outfile<<infile.rdbuf(); + infile.close(); + outfile.close(); + } + } + + char* backup_file=NULL; + asprintf(&backup_file,"%s.safe-pre0.1.0",blacklist_file); + + if (access(backup_file,F_OK)==-1) //backup not found + { + if (access(blacklist_file,F_OK)==0) //ok, now that we have a block.conf file in the right path do the backup + { + ifstream infile(blacklist_file); + ofstream outfile(backup_file); + outfile<<infile.rdbuf(); + infile.close(); + outfile.close(); + } + } + + bool b = EventsBlock.Load(AddDirectory(cPlugin::ConfigDirectory(), "block/block.conf"), true, false); + EventsBlock.Sort(); + cEventBlock* listptr=EventsBlock.First(); + while (listptr!=NULL) + { + if (listptr->Next()==NULL) break; + const char* src=cEventBlock::duptolower(listptr->Pattern()); + const char* cmp=cEventBlock::duptolower(((cEventBlock*)listptr->Next())->Pattern()); +#ifdef LOGGING + dsyslog("plugin-block: Checking for duplicates (case insensitive): '%s' and '%s'",src,cmp); +#endif + if (strcmp(src,cmp)==0) + { + dsyslog("plugin-block: WARNING - import taste|block.conf: deleting duplicate entry %s",cmp); + EventsBlock.Del(listptr->Next(),true); + continue; + } + listptr=EventsBlock.Next(listptr); + } + + cSetupBlock::LastcChannel=Channels.GetByNumber(cDevice::CurrentChannel()); + return b; } bool cPluginBlock::Start(void) @@ -78,85 +158,121 @@ bool cPluginBlock::Start(void) return true; } + cOsdObject *cPluginBlock::MainMenuAction(void) { const cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel()); - if (channel != NULL && !channel->GroupSep()) { + const char* current_title=NULL; + if (channel != NULL && !channel->GroupSep()) + { cSchedulesLock schedLock; const cSchedules *scheds = cSchedules::Schedules(schedLock); - if (scheds == NULL) - return NULL; + if (scheds != NULL) + { + const cSchedule *sched = scheds->GetSchedule(channel->GetChannelID()); + if (sched != NULL) + { + const cEvent *present = sched->GetPresentEvent(); + if (present != NULL) + current_title=present->Title(); + } + } + } + if (current_title==NULL) current_title=""; + + bool acceptable=EventsBlock.Acceptable(current_title); - const cSchedule *sched = scheds->GetSchedule(channel->GetChannelID()); - if (sched == NULL) - return NULL; - const cEvent *present = sched->GetPresentEvent(); - - if (EventsBlock.Acceptable(present->Title())) + + if (!acceptable && cSetupBlock::ParentalGuidance)//TODO check if works { - EventsBlock.Add(new cEventBlock(present->Title())); - EventsBlock.Sort(); - EventsBlock.Save(); + dsyslog("plugin-block: Parental Guidance: Attempt to deblock '%s' from main menu! Permission denied!",current_title); + cSkinDisplayChannel* mOsd = Skins.Current()->DisplayChannel(true); + mOsd->SetMessage(mtError, tr("Permission denied!")); + mOsd->Flush(); + return NULL; } - else + cEventBlock* stringmatch=NULL; + stringmatch=EventsBlock.hasStringMatch(current_title,true); + if (stringmatch!=NULL) { - int index=0; - const cEventBlock* blockeventpointer = EventsBlock.First(); - while (blockeventpointer != NULL) - { - if (strcmp(blockeventpointer->Pattern(),present->Title())==0) - break; - index+=1; - blockeventpointer=EventsBlock.Next(blockeventpointer); - } - cEventBlock *event=EventsBlock.Get(index); - if (event!=NULL) + bool case_insensitive_match=strcmp(stringmatch->Pattern(),current_title); + if (case_insensitive_match) { - if (Interface->Confirm(tr("Delete keyword?"))) - EventsBlock.Del(event); - EventsBlock.Save(); + stringmatch->setIgnoreCase(true); } + stringmatch->setWhitelisted(!acceptable); + EventsBlock.Save(); + cEventBlock::LastTitle="force recheck from main menu"; } - - cEventBlock::LastTitle="block_dummy_title2"; - } + else //create a new enrty + { + cEventBlock *new_entry=new cEventBlock(current_title); + new_entry->setWhitelisted(!acceptable); + EventsBlock.Add(new_entry); + EventsBlock.Sort(); + EventsBlock.Save(); + cEventBlock::LastTitle="force recheck from main menu"; + + } + return NULL; -} +} + cMenuSetupPage *cPluginBlock::SetupMenu(void) { return new cMenuSetupBlock(); } + bool cPluginBlock::SetupParse(const char *Name, const char *Value) { return SetupBlock.Parse(Name, Value); } + void cPluginBlock::MainThreadHook() { - if (cSetupBlock::DetectionMethod!=1) { -#ifdef LOGGING - dsyslog("plugin-block: MainThreadHook returned because other detection method active in setup"); -#endif - return;//other detection method active in setup +// +// commented out cause spams the syslog: +// +// #ifdef LOGGING +// dsyslog("plugin-block: MainThreadHook returned because other detection method active in setup"); +// #endif + return;//other detection method active in setup } if (cEventBlock::ReplayingRecording) //no block events on the underlying channel processed - user watches recording { -#ifdef LOGGING + #ifdef LOGGING if (!temp_replaying_recording) { temp_replaying_recording=true; + #endif + if (cSetupBlock::ParentalGuidance==1) + { + while (cSetupBlock::ReplayingName==NULL); + if (!EventsBlock.Acceptable(cSetupBlock::ReplayingName)) + { + dsyslog("plugin-block: Parental Guidance detected attempt to replay recording with blocked title '%s'! Permission denied!",cSetupBlock::ReplayingName); + int destination=cSetupBlock::LastAcceptableChannel; + if (destination==0) destination=cDevice::CurrentChannel(); + cDevice::PrimaryDevice()->SwitchChannel(Channels.GetByNumber(destination),true); + Skins.Message(mtError, tr("Permission denied!")); + cEventBlock::LastTitle=(char*)"parental guidance event"; + return; + } + } + #ifdef LOGGING dsyslog("plugin-block: doing nothing because user watches recording"); } -#endif + #endif return; } -#ifdef LOGGING + #ifdef LOGGING else { if (temp_replaying_recording) @@ -165,99 +281,141 @@ void cPluginBlock::MainThreadHook() dsyslog("plugin-block: replay of recording ended. Resuming detection mode."); } } -#endif - - channelnumber=cDevice::PrimaryDevice()->CurrentChannel(); - if (channelnumber==0) + #endif + channelnumber=cDevice::CurrentChannel(); + if (channelnumber==0) //TODO last check revealed this possibly would never be true because ChannelSwitch handles it? { -#ifdef LOGGING + #ifdef LOGGING dsyslog("plugin-block: Channel number is 0 => Channel switch on primary device"); -#endif + #endif return; //switch in progress } - const cChannel *channel=Channels.GetByNumber(channelnumber); - + + if (cSetupBlock::LastcChannel!=channel)//necessary cause otherwise switching from one channel to another with both having + //the same blocked EPG title would result in the second channel not being + //blocked (more precise: until a different EPG title is analysed) + { + cEventBlock::LastTitle=(char*)"assuming Channelswitch"; + #ifdef LOGGING + if (cSetupBlock::LastcChannel!=NULL && channel!=NULL) dsyslog("plugin-block: current channel changed (%i->%i)- switching? using dummy for LastTitle: %s",cSetupBlock::LastcChannel->Number(), channel->Number(),cEventBlock::LastTitle); + #endif + } + const char* title=NULL; + const cEvent *present=NULL; + const cEvent *follow=NULL; if (channel != NULL && !channel->GroupSep()) { -#ifdef LOGGING - char *temp_string; - asprintf(&temp_string,"channel: %d channel->GroupSep(): %d", channel->Number(), channel->GroupSep()); - if (strcmp(temp_string,channel_groupsep_string)!=0) - { - dsyslog("plugin-block: %s",temp_string); - channel_groupsep_string=temp_string; - } -#endif - cSchedulesLock schedLock; - const cSchedules *scheds = cSchedules::Schedules(schedLock); - - if (scheds == NULL) - { - char *dummy=cEventBlock::getTimeStamp(); - dsyslog("plugin-block: no EPG data (scheds==NULL) - using dummy for LastTitle: %s",dummy); - cEventBlock::LastTitle=(char*)dummy; - return; - } - + /*//only for debugging purposes: + #ifdef LOGGING + char *temp_string; + asprintf(&temp_string,"channel: %d channel->GroupSep(): %d", channel->Number(), channel->GroupSep()); + if (strcmp(temp_string,channel_groupsep_string)!=0) + { + dsyslog("plugin-block: %s",temp_string); + channel_groupsep_string=temp_string; + } + #endif + */ + + + + + cSchedulesLock schedLock; + const cSchedules *scheds = cSchedules::Schedules(schedLock); + + if (scheds != NULL) + { const cSchedule *sched = scheds->GetSchedule(channel->GetChannelID()); - if (sched == NULL) + if (sched != NULL) { - char *dummy=cEventBlock::getTimeStamp(); - dsyslog("plugin-block: no EPG data (sched==NULL) - using dummy for LastTitle: %s",dummy); - cEventBlock::LastTitle=(char*)dummy; - return; + present = sched->GetPresentEvent(); + follow = sched->GetFollowingEvent(); + if (present!=NULL) + title=present->Title(); } - - const cEvent *present = sched->GetPresentEvent(); - const cEvent *follow = sched->GetFollowingEvent(); - - if (present == NULL) - { - char *dummy=cEventBlock::getTimeStamp(); - dsyslog("plugin-block: no EPG title (present==NULL) - using dummy for LastTitle: %s",dummy); - cEventBlock::LastTitle=(char*)dummy; - return; - } - - //TODO: check if isrequested is still necessary -// if (!cControlBlock::IsRequested() && !EventsBlock.Acceptable(present->Title())) - const char* title=present->Title(); - if (strcmp(title,"")==0) //dunno if this could ever be reached (most likely any of the above would be NULL before) - { - char *dummy=cEventBlock::getTimeStamp(); - dsyslog("plugin-block: no EPG title ("") - using dummy for LastTitle: %s",dummy); - cEventBlock::LastTitle=(char*)dummy; - return; - } - + } + } + if (title==NULL) title=""; + if (strcmp(title,cEventBlock::LastTitle)==0) { -#ifdef LOGGING + #ifdef LOGGING char *temp_string; asprintf(&temp_string, "'%s' has already been checked",title); if (strcmp(temp_string,has_been_checked_string)!=0) { - dsyslog("plugin-block: %s",temp_string); - has_been_checked_string=temp_string; + dsyslog("plugin-block: %s",temp_string); //outputs: 'bla' has already been checked + has_been_checked_string=temp_string; //TODO a bool may increase performance } -#endif + #endif return; //current show has already been checked } -#ifdef LOGGING + + cSetupBlock::LastcChannel=(cChannel*)channel; + + + + #ifdef LOGGING dsyslog("plugin-block: new EPG title detected: '%s' - comparing with '%s'",title, cEventBlock::LastTitle); -#endif + #endif cEventBlock::LastTitle=(char*)title; if (!EventsBlock.Acceptable(title)) { - isyslog("plugin-block: channel %d blocked", channelnumber); - cControl::Launch(new cControlBlock(channel, present, follow)); + dsyslog("plugin-block: channel %i blocked", channelnumber); + + if (cOsd::IsOpen() && !cDisplayChannel::IsOpen()) + { +#ifdef LOGGING + dsyslog("plugin-block: OSD is open (%i)",channelnumber); +#endif + int lastchannel=cSetupBlock::LastAcceptableChannel; + int direction = cDevice::CurrentChannel() - lastchannel; + if (direction == 0) + direction = 1; + int switch_result=cDevice::SwitchChannel(direction); + if (switch_result) + { + cEventBlock::LastTitle="force recheck from OSD workaround"; + //in case the EPG title changes while the block message is displayed + //AND the the former and the current title are equal + //(AND maybe other conditions like the plugin is already coming from a + //blocked channel etc.) this code block is reached and only in this + //case we have to force a recheck! Maybe this is an ugly workaround + //but it seems to work... + } + else + { + if (lastchannel != 0) + { + dsyslog("plugin-block: main thread switching to last channel %i (fallback)",lastchannel); + Channels.SwitchTo(lastchannel); + } + } + } + else + { +#ifdef LOGGING + dsyslog("plugin-block: launching cControl for %i",channelnumber); +#endif + cControl::Launch(new cControlBlock(channel, present, follow)); + } + + } + else + { + cSetupBlock::LastAcceptableChannel=cDevice::CurrentChannel(); + cSetupBlock::user_direction=0; + cSetupBlock::LastcChannel=Channels.GetByNumber(cDevice::CurrentChannel()); } + } -} + + + /* bool cPluginBlock::ProcessArgs (int argc, char *argv[]) |