summaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'block.c')
-rw-r--r--block.c384
1 files changed, 271 insertions, 113 deletions
diff --git a/block.c b/block.c
index c424575..0269839 100644
--- a/block.c
+++ b/block.c
@@ -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[])