void EventsResponder::reply(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{
  if ( request.method() == "OPTIONS" ) {
      reply.addHeader("Allow", "GET, POST");
      reply.httpReturn(200, "OK");
      return;
  }

  QueryHandler::addHeader(reply);
  if ( (int)request.url().find("/events/image/") == 0 ) {
     replyImage(out, request, reply);
  } else if ( (int)request.url().find("/events/search") == 0 ){
     replySearchResult(out, request, reply);
  }

  else if ( (int)request.url().find("/events/contentdescriptors") == 0 ){
      replyContentDescriptors(out, request, reply);
  }

  else {
     replyEvents(out, request, reply);
  }
}
Example #2
0
void TimersResponder::createOrUpdateTimer(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply, bool update)
{
  QueryHandler q("/timers", request);

  if ( Timers.BeingEdited() ) {
     reply.httpReturn(502, "Timers are being edited - try again later");
     return;
  }

  int error = false;
  string error_values = "";
  static TimerValues v;

  int flags = v.ConvertFlags(q.getBodyAsString("flags"));
  string aux = v.ConvertAux(q.getBodyAsString("aux"));
  string file = v.ConvertFile(q.getBodyAsString("file"));
  int lifetime = v.ConvertLifetime(q.getBodyAsString("lifetime"));
  int priority = v.ConvertPriority(q.getBodyAsString("priority"));
  int stop = v.ConvertStop(q.getBodyAsString("stop"));
  int start = v.ConvertStart(q.getBodyAsString("start"));
  string weekdays = q.getBodyAsString("weekdays");
  string day = v.ConvertDay(q.getBodyAsString("day"));
  cChannel* chan = v.ConvertChannel(q.getBodyAsString("channel"));
  cTimer* timer_orig = v.ConvertTimer(q.getBodyAsString("timer_id"));
  
  if ( update == false ) { //create
     int eventid = q.getBodyAsInt("eventid");
     int minpre = q.getBodyAsInt("minpre");
     int minpost = q.getBodyAsInt("minpost");
     if (eventid >= 0 && chan != NULL) {
        cEvent* event = VdrExtension::GetEventById((tEventID)eventid, chan);
      
        if (event == NULL) {
           reply.httpReturn(407, "eventid invalid");
           return;
        } else {
           if (minpre < 0) minpre = 0;
           if (minpost < 0) minpost = 0;
           if (!v.IsFlagsValid(flags)) flags = 1;
           if (!v.IsFileValid(file)) file = (string)event->Title();
           if (!v.IsWeekdaysValid(weekdays)) weekdays = "-------";
           if (!v.IsLifetimeValid(lifetime)) lifetime = 50;
           if (!v.IsPriorityValid(priority)) priority = 99;
           chan = VdrExtension::getChannel((const char*)event->ChannelID().ToString());
           if (!v.IsStartValid(start) || !v.IsStopValid(stop) || !v.IsDayValid(day)) {
              time_t estart = event->StartTime();
              time_t estop = event->EndTime();
              struct tm *starttime = localtime(&estart);
            
              ostringstream daystream;
              daystream << StringExtension::addZeros((starttime->tm_year + 1900), 4) << "-"
                        << StringExtension::addZeros((starttime->tm_mon + 1), 2) << "-"
                        << StringExtension::addZeros((starttime->tm_mday), 2);
              day = daystream.str();
 
              start = starttime->tm_hour * 100 + starttime->tm_min - ((int)(minpre/60))*100 - minpre%60;

              struct tm *stoptime = localtime(&estop);
              stop = stoptime->tm_hour * 100 + stoptime->tm_min + ((int)(minpost/60))*100 + minpost%60;
           }
        }
     } else {
        if ( !v.IsFlagsValid(flags) ) { flags = 1; }
        if ( !v.IsFileValid(file) ) { error = true; error_values += "file, "; }
        if ( !v.IsLifetimeValid(lifetime) ) { lifetime = 50; }
        if ( !v.IsPriorityValid(priority) ) { priority = 99; }
        if ( !v.IsStopValid(stop) ) { error = true; error_values += "stop, "; }
        if ( !v.IsStartValid(start) ) { error = true; error_values += "start, "; }
        if ( !v.IsWeekdaysValid(weekdays) ) { error = true; error_values += "weekdays, "; }
        if ( !v.IsDayValid(day)&& !day.empty() ) { error = true; error_values += "day, "; }
        if ( chan == NULL ) { error = true; error_values += "channel, "; }
     }
  } else { //update
     if ( timer_orig == NULL ) { error = true; error_values += "timer_id, "; }
     if ( !error ) {
        if ( !v.IsFlagsValid(flags) ) { flags = timer_orig->Flags(); }
        if ( !v.IsFileValid(file) ) { file = (string)timer_orig->File(); }
        if ( !v.IsLifetimeValid(lifetime) ) { lifetime = timer_orig->Lifetime(); }
        if ( !v.IsPriorityValid(priority) ) { priority = timer_orig->Priority(); }
        if ( !v.IsStopValid(stop) ) { stop = timer_orig->Stop(); }
        if ( !v.IsStartValid(start) ) { start = timer_orig->Start(); }
        if ( !v.IsWeekdaysValid(weekdays) ) { weekdays = v.ConvertWeekdays(timer_orig->WeekDays()); }
        if ( !v.IsDayValid(day) ) { day = v.ConvertDay(timer_orig->Day()); }
        if ( chan == NULL ) { chan = (cChannel*)timer_orig->Channel(); }
     }
  }

  if (error) {
     string error_message = (string)"The following parameters aren't valid: " + error_values.substr(0, error_values.length()-2) + (string)"!";
     reply.httpReturn(403, error_message);
     return;
  }
 
  ostringstream builder;
  builder << flags << ":"
          << (const char*)chan->GetChannelID().ToString() << ":"
	  << ( weekdays != "-------" ? weekdays : "" )
          << ( weekdays == "-------" || day.empty() ? "" : "@" ) << day << ":"
          << start << ":"
          << stop << ":"
          << priority << ":"
          << lifetime << ":"
          << file << ":" 
          << aux;

  dsyslog("restfulapi: /%s/ ", builder.str().c_str());
  chan = NULL;
  if ( update == false ) { // create timer
     cTimer* timer = new cTimer();
     if ( timer->Parse(builder.str().c_str()) ) { 
        cTimer* checkTimer = Timers.GetTimer(timer);
        if ( checkTimer != NULL ) {
           delete timer;
           reply.httpReturn(403, "Timer already defined!"); 
           esyslog("restfulapi: Timer already defined!");
        } else {
           replyCreatedId(timer, request, reply, out);
           timer->SetEventFromSchedule();
           Timers.Add(timer);
           Timers.SetModified();
           esyslog("restfulapi: timer created!");
        }
     } else {
        reply.httpReturn(403, "Creating timer failed!");
        esyslog("restfulapi: timer creation failed!");
     }
  } else {
     if ( timer_orig->Parse(builder.str().c_str()) ) {
        timer_orig->SetEventFromSchedule();
        Timers.SetModified();
        replyCreatedId(timer_orig, request, reply, out);
        esyslog("restfulapi: updating timer successful!");
     } else { 
        reply.httpReturn(403, "updating timer failed!");
        esyslog("restfulapi: updating timer failed!");
     }
  }
}
void RecordingsResponder::reply(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{
  QueryHandler::addHeader(reply);
  bool found = false;

  if (request.method() == "OPTIONS") {
     return;
  }

  if ((int)request.url().find("/recordings/play") == 0 ) {
     if ( request.method() == "GET" ) {
        playRecording(out, request, reply);
        reply.addHeader("Content-Type", "text/plain; charset=utf-8");
     } else if (request.method() == "POST") {
        rewindRecording(out, request, reply);
        reply.addHeader("Content-Type", "text/plain; charset=utf-8");
     } else {
        reply.httpReturn(501, "Only GET and POST method is supported by the /recordings/play service.");
     }
     found = true;
  }

  else if ((int)request.url().find("/recordings/cut") == 0 ) {
     if ( request.method() == "GET" ) {
        showCutterStatus(out, request, reply);
     } else if (request.method() == "POST") {
        cutRecording(out, request, reply); 
     } else {
        reply.httpReturn(501, "Only GET and POST methods are supported by the /recordings/cut service.");
     }
     found = true;
  }

  else if ((int)request.url().find("/recordings/marks") == 0 ) {
     if ( request.method() == "DELETE" ) {
        deleteMarks(out, request, reply);
     } else if (request.method() == "POST" ) {
        saveMarks(out, request, reply);
     } else {
        reply.httpReturn(501, "Only DELETE and POST methods are supported by the /recordings/marks service.");
     }
     found = true;
  }

  // original /recordings service
  else if ((int) request.url().find("/recordings") == 0 ) {
        if ( request.method() == "GET" ) {
        showRecordings(out, request, reply);
        found = true;
     } else if (request.method() == "DELETE" ) {
        deleteRecording(out, request,reply);
        found = true;
     } else {
        reply.httpReturn(501, "Only GET and DELETE methods are supported by the /recordings service.");
     }
     found = true;
  }

  if (!found) {
     reply.httpReturn(403, "Service not found");
  }
}
Example #4
0
void TimersResponder::replyBulkdelete(std::ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply) {

  QueryHandler q("/timers/bulkdelete", request);

#if APIVERSNUM > 20300
    LOCK_TIMERS_WRITE;
    cTimers& timers = *Timers;
#else
    cTimers& timers = Timers;

	if ( timers.BeingEdited() ) {
		reply.httpReturn(502, "Timers are being edited - try again later");
		return;
	}
#endif

  TimerDeletedList* list;

  if ( q.isFormat(".json") ) {
     reply.addHeader("Content-Type", "application/json; charset=utf-8");
     list = (TimerDeletedList*)new JsonTimerDeletedList(&out);
  } else if ( q.isFormat(".html") ) {
     reply.addHeader("Content-Type", "text/html; charset=utf-8");
     list = (TimerDeletedList*)new HtmlTimerDeletedList(&out);
  } else if ( q.isFormat(".xml") ) {
     reply.addHeader("Content-Type", "text/xml; charset=utf-8");
     list = (TimerDeletedList*)new XmlTimerDeletedList(&out);
  } else {
     reply.httpReturn(404, "Resources are not available for the selected format. (Use: .json, .html or .xml)");
     return;
  }

  TimerValues v;
  cTimer* timer;

  vector< string > deleteTimers = q.getBodyAsStringArray("timers");
  vector< SerBulkDeleted > results;
  SerBulkDeleted result;

  size_t i;

  list->init();

  for ( i = 0; i < deleteTimers.size(); i++ ) {
    timer = v.ConvertTimer(deleteTimers[i]);
    result.id = deleteTimers[i];
    if ( timer == NULL ) {
	result.deleted = false;
    } else {
      if ( timer->Recording() ) {
	timer->Skip();
#if APIVERSNUM > 20300
        cRecordControls::Process(Timers, time(NULL));
#else
        cRecordControls::Process(time(NULL));
#endif
      }
      timers.Del(timer);
      timers.SetModified();
      result.deleted = true;
    }
    list->addDeleted(result);
  }
  list->setTotal((int)deleteTimers.size());
  list->finish();
  delete list;

};
void EventsResponder::replyContentDescriptors(std::ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply) {

  QueryHandler q("/events/contentdescriptors", request);

  if ( request.method() != "GET") {
     reply.httpReturn(403, "To retrieve content descriptors use the POST method!");
     return;
  }

  StreamExtension se(&out);

  ContentDescriptorList* list;

  if ( q.isFormat(".json") ) {
     reply.addHeader("Content-Type", "application/json; charset=utf-8");
     list = (ContentDescriptorList*)new JsonContentDescriptorList(&out);
  } else if ( q.isFormat(".html") ) {
     reply.addHeader("Content-Type", "text/html; charset=utf-8");
     list = (ContentDescriptorList*)new HtmlContentDescriptorList(&out);
  } else if ( q.isFormat(".xml") ) {
     reply.addHeader("Content-Type", "text/xml; charset=utf-8");
     list = (ContentDescriptorList*)new XmlContentDescriptorList(&out);
  } else {
     reply.httpReturn(403, "Resources are not available for the selected format. (Use: .json, .xml or .html)");
     return;
  }

  list->init();
  int total = 0;
  std::set<std::string> contentStrings;

  for(unsigned int i=0; i<CONTENT_DESCRIPTOR_MAX;i++) {

    const string contentDescr = cEvent::ContentToString(i);
    SerContentDescriptor cDescr;
    if (!contentDescr.empty() && contentStrings.find(contentDescr) == contentStrings.end()) {

	contentStrings.insert(contentDescr);
	cDescr.name = StringExtension::UTF8Decode(contentDescr);
	std::stringstream stream;
	stream << std::hex << i;
	std::string result( stream.str() );

	switch (i) {
	  case ecgArtsCulture:
	  case ecgChildrenYouth:
	  case ecgEducationalScience:
	  case ecgLeisureHobbies:
	  case ecgMovieDrama:
	  case ecgMusicBalletDance:
	  case ecgNewsCurrentAffairs:
	  case ecgShow:
	  case ecgSocialPoliticalEconomics:
	  case ecgSpecial:
	  case ecgSports:
	  case ecgUserDefined:
	      cDescr.isGroup = true;
	      break;
	  default:
	      cDescr.isGroup = false;
	}

	cDescr.id = result;
	list->addDescr(cDescr);
	total++;
    }
  }

  list->setTotal(total);
  list->finish();
  delete list;
};
void EventsResponder::replyEvents(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{
  QueryHandler q("/events", request);

  if ( request.method() != "GET") {

     reply.httpReturn(403, "To retrieve information use the GET method!");
     return;
  }


  EventList* eventList;

  if ( q.isFormat(".json") ) {
     reply.addHeader("Content-Type", "application/json; charset=utf-8");
     eventList = (EventList*)new JsonEventList(&out);
  } else if ( q.isFormat(".html") ) {
     reply.addHeader("Content-Type", "text/html; charset=utf-8");
     eventList = (EventList*)new HtmlEventList(&out);
  } else if ( q.isFormat(".xml") ) {
     reply.addHeader("Content-Type", "text/xml; charset=utf-8");
     eventList = (EventList*)new XmlEventList(&out);
  } else {
     reply.httpReturn(403, "Resources are not available for the selected format. (Use: .json or .html)");
     return;
  }

  string channel_id = q.getParamAsString(0);
  int timespan = q.getOptionAsInt("timespan");//q.getParamAsInt(1);
  int from = q.getOptionAsInt("from");//q.getParamAsInt(2);

  int start_filter = q.getOptionAsInt("start");
  int limit_filter = q.getOptionAsInt("limit");
  
  int event_id = q.getParamAsInt(1);//q.getOptionAsInt("eventid");

  string onlyCount = q.getOptionAsString("only_count");

#if APIVERSNUM > 20300
    LOCK_CHANNELS_READ;
    const cChannels& channels = *Channels;
#else
    cChannels& channels = Channels;
#endif

  const cChannel* channel = VdrExtension::getChannel(channel_id);
  if ( channel == NULL ) { 
     /*reply.addHeader("Content-Type", "application/octet-stream");
     string error_message = (string)"Could not find channel with id: " + channel_id + (string)"!";
     reply.httpReturn(404, error_message); 
     return;*/
  }

  int channel_limit = q.getOptionAsInt("chevents");
  if ( channel_limit <= -1 ) channel_limit = 0; // default channel events is 0 -> all
  
  int channel_from = q.getOptionAsInt("chfrom");
  if ( channel_from <= -1 || channel != NULL ) channel_from = 0; // default channel number is 0
  
  int channel_to = q.getOptionAsInt("chto");
  if ( channel_to <= 0 || channel != NULL ) channel_to = channels.Count();
 
  if ( from <= -1 ) from = time(NULL); // default time is now
  if ( timespan <= -1 ) timespan = 0; // default timespan is 0, which means all entries will be returned
  int to = from + timespan;

#if APIVERSNUM > 20300
	LOCK_SCHEDULES_READ;
#else
	cSchedulesLock MutexLock;
	const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
#endif

  if( !Schedules ) {
     reply.httpReturn(404, "Could not find schedules!");
     return;
  }


  if ( start_filter >= 0 && limit_filter >= 1 ) {
     eventList->activateLimit(start_filter, limit_filter);
  }

  bool initialized = false;
  int total = 0;
  for(int i=0; i<channels.Count(); i++) {
     const cSchedule *Schedule = Schedules->GetSchedule(channels.Get(i)->GetChannelID());
     
     if ((channel == NULL || strcmp(channel->GetChannelID().ToString(), channels.Get(i)->GetChannelID().ToString()) == 0) && (i >= channel_from && i <= channel_to)) {
        if (!Schedule) {
           if (channel != NULL) {
              reply.httpReturn(404, "Could not find schedule!");
              return;
           }
        } else {
           if (!initialized) {
              eventList->init();
              initialized = true;
           }

           int old = 0;
           int channel_events = 0;
           for(const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event)) {
              int ts = event->StartTime();
              int te = ts + event->Duration();
              if ((ts <= to && te > from) || (te > from && timespan == 0)) {
                 if (channel_limit == 0 || channel_limit > channel_events) {
                    if ((event_id < 0 || event_id == (int)event->EventID()) && onlyCount != "true") {
                       eventList->addEvent(event);
                       channel_events++;
                    }
                 }
              } else {
                 if (ts > to) break;
                 if (te <= from) old++;
              }
           }
           total += (Schedule->Events()->Count() - old);
        }
     }
  }
  eventList->setTotal(total);
  eventList->finish();
  delete eventList;
}
void EventsResponder::replySearchResult(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{

  QueryHandler q("/events/search", request);

  if ( request.method() != "POST") {
     reply.httpReturn(403, "To search for information use the POST method!");
     return;
  }

  StreamExtension se(&out);

  string query = q.getBodyAsString("query");
  string search = q.getBodyAsString("search");

  if ( query.length() == 0 && search.length() == 0 ) {
     reply.httpReturn(402, "Query required");
     return;
  }

  EventList* eventList;

  if ( q.isFormat(".json") ) {
     reply.addHeader("Content-Type", "application/json; charset=utf-8");
     eventList = (EventList*)new JsonEventList(&out);
  } else if ( q.isFormat(".html") ) {
     reply.addHeader("Content-Type", "text/html; charset=utf-8");
     eventList = (EventList*)new HtmlEventList(&out);
  } else if ( q.isFormat(".xml") ) {
     reply.addHeader("Content-Type", "text/xml; charset=utf-8");
     eventList = (EventList*)new XmlEventList(&out);
  } else {
     reply.httpReturn(403, "Resources are not available for the selected format. (Use: .json or .html)");
     return;
  }
  eventList->init();
  int start_filter = q.getOptionAsInt("start");
  int limit_filter = q.getOptionAsInt("limit");
  int date_filter = q.getOptionAsInt("date_limit");
  if ( start_filter >= 0 && limit_filter >= 1 ) {
     eventList->activateLimit(start_filter, limit_filter);
  }
  if ( date_filter >= 0  ) {
     eventList->activateDateLimit(date_filter);
  }
  
  int total = 0;
  if ( search.length() > 0 ) {

      vdrlive::SearchTimer* searchtimer = new vdrlive::SearchTimer;
      searchtimer->SetId(0);
      string result = searchtimer->LoadCommonFromQuery(q);

      if (result.length() > 0) {
           reply.httpReturn(406, result.c_str());
           return;
      }

      string query = searchtimer->ToText();
      vdrlive::SearchResults* results = new vdrlive::SearchResults;
      results->GetByQuery(query);

      for (vdrlive::SearchResults::iterator result = results->begin(); result != results->end(); ++result) {

          eventList->addEvent(((cEvent*)result->GetEvent()));
          total++;
      }
      delete searchtimer;
      delete results;

  } else {

      int mode = q.getBodyAsInt("mode");// search mode (0=phrase, 1=and, 2=or, 3=exact, 4=regular expression, 5=fuzzy)
      string channelid = q.getBodyAsString("channelid"); //id !!
      bool use_title = q.getBodyAsString("use_title") == "true";
      bool use_subtitle = q.getBodyAsString("use_subtitle") == "true";
      bool use_description = q.getBodyAsString("use_description") == "true";

      int channel = 0;
      const cChannel* channelInstance = VdrExtension::getChannel(channelid);
      if (channelInstance != NULL) {
         channel = channelInstance->Number();
      }

#if APIVERSNUM > 20300
    LOCK_CHANNELS_READ;
    const cChannels& channels = *Channels;
#else
    cChannels& channels = Channels;
#endif

      if (!use_title && !use_subtitle && !use_description)
         use_title = true;
      if (mode < 0 || mode > 5)
         mode = 0;
      if (channel < 0 || channel > channels.Count())
         channel = 0;
      if (query.length() > 100)
         query = query.substr(0,100); //don't allow more than 100 characters, NOTE: maybe I should add a limitation to the Responderclass?

      struct Epgsearch_searchresults_v1_0* epgquery = new struct Epgsearch_searchresults_v1_0;
      epgquery->query = (char*)query.c_str();
      epgquery->mode = mode;
      epgquery->channelNr = channel;
      epgquery->useTitle = use_title;
      epgquery->useSubTitle = use_subtitle;
      epgquery->useDescription = use_description;

      cPlugin *Plugin = cPluginManager::GetPlugin("epgsearch");
      if (Plugin) {
         if (Plugin->Service("Epgsearch-searchresults-v1.0", NULL)) {
            if (Plugin->Service("Epgsearch-searchresults-v1.0", epgquery)) {
               cList< Epgsearch_searchresults_v1_0::cServiceSearchResult>* result = epgquery->pResultList;
               Epgsearch_searchresults_v1_0::cServiceSearchResult* item = NULL;
               if (result != NULL) {
                  for(int i=0;i<result->Count();i++) {
                     item = result->Get(i);
                     eventList->addEvent(((cEvent*)item->event));
                     total++;
                  }
               }
            } else {
               reply.httpReturn(406, "Internal (epgsearch) error, check parameters.");
            }
         } else {
            reply.httpReturn(405, "Plugin-service not available.");
         }
      } else {
         reply.httpReturn(404, "Plugin not installed!");
      }
      delete epgquery;

  }
  eventList->setTotal(total);
  eventList->finish();
  delete eventList;
}
bool KeyPairList::hitKey(cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{ 
  
  if ( (int)request.url().find("/remote/kbd") != -1) {
    QueryHandler q("/remote/kbd", request);
    cxxtools::String kbd = StringExtension::UTF8Decode(q.getBodyAsString("kbd"));
    if ( kbd == StringExtension::UTF8Decode("") ) {
	reply.httpReturn(400, "Key is empty.");
    }
    std::size_t n = 0;
    while (kbd[n]) {
      cRemote::Put(KBDKEY(kbd[n]));
      ++n;
    }
    return true;

  } else if ( (int)request.url().find("/remote/seq") != -1) {
    QueryHandler q("/remote/seq", request);
    JsonArray* seq = q.getBodyAsArray("seq");

    if ( seq == NULL ) {
	reply.httpReturn(400, "Sequence is empty.");
        return false;
    }

    for (int i = 0; i < seq->CountItem(); i++) {
      JsonBase* jsonBase = seq->GetItem(i);
      if (jsonBase->IsBasicValue()) {
	JsonBasicValue* jsonBasicValue = (JsonBasicValue*)jsonBase;
	if (jsonBasicValue->IsString()) {
          string key = jsonBasicValue->ValueAsString();
          for (int n=0;n<(int)key.length();n++ ) {
            key[n] = tolower(key[n]);
          }
	  for (int x=0;x<(int)keys.size();x++) {
	    if (string(keys[x].str) == key) {
		cRemote::Put(keys[x].key);
	    }
	  }
	}
      }
    }

    return true;

  } else {
    QueryHandler q("/remote", request);
    string key = q.getParamAsString(0);

    if (key.length() == 0) {
       reply.httpReturn(404, "Please add a key to the parameter list, see API-file for more details.");
       return false;
    }

    for (int i=0;i<(int)key.length();i++) {
      key[i] = tolower(key[i]);
    }

    for (int i=0;i<(int)keys.size();i++)
    {
      if (string(keys[i].str) == key) {
        cRemote::Put(keys[i].key);
        return true;
      }
    }
  }



  return false;
}
Example #9
0
void ChannelsResponder::replyChannels(std::ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{
  QueryHandler q("/channels", request);
  
  ChannelList* channelList;

  if ( q.isFormat(".json") ) {
    reply.addHeader("Content-Type", "application/json; charset=utf-8");
    channelList = (ChannelList*)new JsonChannelList(&out);
  } else if ( q.isFormat(".html") ) {
    reply.addHeader("Content-Type", "text/html; charset=utf-8");
    channelList = (ChannelList*)new HtmlChannelList(&out);
  } else if ( q.isFormat(".xml") ) {
    reply.addHeader("Content-Type", "text/xml; charset=utf-8");
    channelList = (ChannelList*)new XmlChannelList(&out);
  } else {
    reply.httpReturn(403, "Resources are not available for the selected format. (Use: .json, .html or .xml)");
    return;
  }

  std::string channel_details = q.getParamAsString(0);
  int start_filter = q.getOptionAsInt("start");
  int limit_filter = q.getOptionAsInt("limit");
  std::string group_filter = q.getOptionAsString("group");

  if (channel_details.length() > 0) {
     cChannel* channel = VdrExtension::getChannel(channel_details);
     if (channel == NULL || channel->GroupSep()) {
        reply.httpReturn(403, "The requested channel is not available.");
        delete channelList;
        return;        
     } else {
        channelList->init();
        
        std::string group = "";
        int total = 0;
        for (cChannel *channelIt = Channels.First(); channelIt; channelIt = Channels.Next(channelIt))
        { 
           if (!channelIt->GroupSep()) 
              total++; 
           else
              if ( total < channel->Number())
                 group = channelIt->Name();
        }
        channelList->setTotal(total);
        std::string image = FileCaches::get()->searchChannelLogo(channel);
        channelList->addChannel(channel, group, image.length() == 0);
     }
  } else {
     if ( start_filter >= 0 && limit_filter >= 1 ) {
        channelList->activateLimit(start_filter, limit_filter);
     }
     channelList->init();
     int total = 0;
     std::string group = "";
     for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
     {
       if (!channel->GroupSep()) {
          if ( group_filter.length() == 0 || group == group_filter ) {
             std::string image = FileCaches::get()->searchChannelLogo(channel);
             channelList->addChannel(channel, group, image.length() != 0);
             total++;
          }
       } else {
         group = channel->Name();
       }
     }
     channelList->setTotal(total);
  }

  channelList->finish();
  delete channelList;
}
/* move or copy recording */
void RecordingsResponder::moveRecording(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply)
{
   QueryHandler q("/recordings/move", request);
   string source = q.getBodyAsString("source");
   string target = q.getBodyAsString("target");
   bool copy_only = q.getBodyAsBool("copy_only");


#if APIVERSNUM > 20300
    LOCK_RECORDINGS_WRITE;
    cRecordings& recordings = *Recordings;
#else
    cThreadLock RecordingsLock(&Recordings);
    cRecordings& recordings = Recordings;
#endif

   if (source.length() <= 0 || target.length() <= 0) {
      reply.httpReturn(404, "Missing file name!");
      return;
   } else if (access(source.c_str(), F_OK) != 0) {
      reply.httpReturn(504, "Path is invalid!");
      return;
   }

   const cRecording* recording = recordings.GetByName(source.c_str());
   if (!recording) {
      reply.httpReturn(504, "Recording not found!");
      return;
   }

   //string newname = VdrExtension::MoveRecording(recording, VdrExtension::FileSystemExchangeChars(target.c_str(), true), copy_only);
    
   string oldname = recording->FileName();
   size_t found = oldname.find_last_of("/");
    
   if (found == string::npos) {
      LOG_ERROR_STR(source.c_str());
      reply.httpReturn(503, "File copy failed!");
      return;
   }
    
#if APIVERSNUM > 20101
   string newname = string(cVideoDirectory::Name()) + "/" + VdrExtension::FileSystemExchangeChars(target.c_str(), true) + oldname.substr(found);
#else
   string newname = string(VideoDirectory) + "/" + VdrExtension::FileSystemExchangeChars(target.c_str(), true) + oldname.substr(found);
#endif
   if (!VdrExtension::MoveDirectory(oldname.c_str(), newname.c_str(), copy_only)) {
      esyslog("[Restfulapi]: renaming failed from '%s' to '%s'", oldname.c_str(), newname.c_str());
      reply.httpReturn(503, "File copy failed!");
      return;
   }
    
   if (!copy_only)
      recordings.DelByName(oldname.c_str());
   recordings.AddByName(newname.c_str());
   cRecordingUserCommand::InvokeCommand(*cString::sprintf("rename \"%s\"", *strescape(oldname.c_str(), "\\\"$'")), newname.c_str());

   const cRecording* new_recording = recordings.GetByName(newname.c_str());
   if (!new_recording) {
      LOG_ERROR_STR(newname.c_str());
      reply.httpReturn(504, "Recording not found, after moving!");
      return;
   }


   esyslog("restfulapi: %s, %d", new_recording->FileName(), new_recording->Index());

   RecordingList* recordingList = getRecordingList(out, q, reply);
   if (recordingList == NULL) {
      return;
   }
   recordingList->addRecording(new_recording, new_recording->Index(), NULL, "");
   recordingList->setTotal(recordings.Count());
   recordingList->finish();
   delete recordingList;
}