]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
channel enhancements (enabled), fixed min/max chnum handling (access)
authorJaroslav Kysela <perex@perex.cz>
Fri, 21 Nov 2014 17:02:27 +0000 (18:02 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 21 Nov 2014 17:02:27 +0000 (18:02 +0100)
14 files changed:
src/access.c
src/access.h
src/api/api_channel.c
src/api/api_epg.c
src/channels.c
src/channels.h
src/dvr/dvr_autorec.c
src/epg.c
src/epg.h
src/htsp_server.c
src/http.c
src/webui/simpleui.c
src/webui/statedump.c
src/webui/webui.c

index 45fd6af214065284db3c8cef906ba7d0eba09c03..945390cf1552722380d1fc3928bb0b40d01cc4fb 100644 (file)
@@ -348,7 +348,7 @@ access_dump_a(access_t *a)
   int first;
 
   snprintf(buf, sizeof(buf),
-    "%s:%s [%s%s%s%s%s], conn=%u, chmin=%u, chmax=%u%s",
+    "%s:%s [%s%s%s%s%s], conn=%u, chmin=%llu, chmax=%llu%s",
     a->aa_representative ?: "<no-id>",
     a->aa_username ?: "<no-user>",
     a->aa_rights & ACCESS_STREAMING          ? "S" : "",
@@ -357,7 +357,7 @@ access_dump_a(access_t *a)
     a->aa_rights & ACCESS_RECORDER           ? "R" : "",
     a->aa_rights & ACCESS_ADMIN              ? "*" : "",
     a->aa_conn_limit,
-    a->aa_chmin, a->aa_chmax,
+    (long long)a->aa_chmin, (long long)a->aa_chmax,
     a->aa_match ? ", matched" : "");
 
   if (a->aa_profiles) {
@@ -1295,13 +1295,15 @@ const idclass_t access_entry_class = {
       .off      = offsetof(access_entry_t, ae_conn_limit),
     },
     {
-      .type     = PT_U32,
+      .type     = PT_S64,
+      .intsplit = CHANNEL_SPLIT,
       .id       = "channel_min",
       .name     = "Min Channel Num",
       .off      = offsetof(access_entry_t, ae_chmin),
     },
     {
-      .type     = PT_U32,
+      .type     = PT_S64,
+      .intsplit = CHANNEL_SPLIT,
       .id       = "channel_max",
       .name     = "Max Channel Num",
       .off      = offsetof(access_entry_t, ae_chmax),
index 536bf5c01dd3e980b368d0aea0f0fdd359aebdac..336b78d5a15d9ffb019d7836153a529ca1d674b7 100644 (file)
@@ -70,8 +70,8 @@ typedef struct access_entry {
   int ae_webui;
   int ae_admin;
 
-  uint32_t ae_chmin;
-  uint32_t ae_chmax;
+  uint64_t ae_chmin;
+  uint64_t ae_chmax;
 
   struct channel_tag *ae_chtag;
   LIST_ENTRY(access_entry) ae_channel_tag_link;
@@ -89,8 +89,8 @@ typedef struct access {
   uint32_t  aa_rights;
   htsmsg_t *aa_profiles;
   htsmsg_t *aa_dvrcfgs;
-  uint32_t  aa_chmin;
-  uint32_t  aa_chmax;
+  uint64_t  aa_chmin;
+  uint64_t  aa_chmax;
   htsmsg_t *aa_chtags;
   int       aa_match;
   uint32_t  aa_conn_limit;
index 58ffe6bb0b3f7ae69f519233f847ceeb9a257d0a..6cdbe34dc4dcdb97a25c41322a58df14e13f1954 100644 (file)
 #include "access.h"
 #include "api.h"
 
+static void
+api_channel_key_val(htsmsg_t *dst, const char *key, const char *val)
+{
+  htsmsg_t *e = htsmsg_create_map();
+  htsmsg_add_str(e, "key", key);
+  htsmsg_add_str(e, "val", val ?: "");
+  htsmsg_add_msg(dst, NULL, e);
+}
+
 // TODO: this will need converting to an idnode system
 static int
 api_channel_list
   ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
   channel_t *ch;
-  htsmsg_t *l, *e;
+  htsmsg_t *l;
 
   l = htsmsg_create_list();
   pthread_mutex_lock(&global_lock);
   CHANNEL_FOREACH(ch) {
-    e = htsmsg_create_map();
-    htsmsg_add_str(e, "key", idnode_uuid_as_str(&ch->ch_id));
-    htsmsg_add_str(e, "val", channel_get_name(ch));
-    htsmsg_add_msg(l, NULL, e);
+    if (!channel_access(ch, perm, 0)) continue;
+    api_channel_key_val(l, idnode_uuid_as_str(&ch->ch_id), channel_get_name(ch));
   }
   pthread_mutex_unlock(&global_lock);
   *resp = htsmsg_create_map();
@@ -55,7 +62,8 @@ api_channel_grid
   channel_t *ch;
 
   CHANNEL_FOREACH(ch)
-    idnode_set_add(ins, (idnode_t*)ch, &conf->filter);
+    if (channel_access(ch, perm, 1))
+      idnode_set_add(ins, (idnode_t*)ch, &conf->filter);
 }
 
 static int
@@ -82,14 +90,19 @@ api_channel_tag_list
   ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
 {
   channel_tag_t *ct;
-  htsmsg_t *l, *e;
+  htsmsg_t *l;
   
   l = htsmsg_create_list();
-  TAILQ_FOREACH(ct, &channel_tags, ct_link) {
-    e = htsmsg_create_map();
-    htsmsg_add_str(e, "key", idnode_uuid_as_str(&ct->ct_id));
-    htsmsg_add_str(e, "val", ct->ct_name);
-    htsmsg_add_msg(l, NULL, e);
+  if (perm->aa_chtags) {
+    htsmsg_field_t *f;
+    HTSMSG_FOREACH(f, perm->aa_chtags) {
+      ct = channel_tag_find_by_uuid(htsmsg_field_get_str(f) ?: "");
+      if (ct)
+        api_channel_key_val(l, idnode_uuid_as_str(&ct->ct_id), ct->ct_name);
+    }
+  } else {
+    TAILQ_FOREACH(ct, &channel_tags, ct_link)
+      api_channel_key_val(l, idnode_uuid_as_str(&ct->ct_id), ct->ct_name);
   }
   *resp = htsmsg_create_map();
   htsmsg_add_msg(*resp, "entries", l);
@@ -102,8 +115,17 @@ api_channel_tag_grid
 {
   channel_tag_t *ct;
 
-  TAILQ_FOREACH(ct, &channel_tags, ct_link)
-    idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
+  if (perm->aa_chtags) {
+    htsmsg_field_t *f;
+    HTSMSG_FOREACH(f, perm->aa_chtags) {
+      ct = channel_tag_find_by_uuid(htsmsg_field_get_str(f) ?: "");
+      if (ct)
+        idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
+    }
+  } else {
+    TAILQ_FOREACH(ct, &channel_tags, ct_link)
+      idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
+  }
 }
 
 static int
index 771414b5c245714dad163ba5d4a7817b83197147..dac92579fadb59350e03774907ed3428f3632780 100644 (file)
@@ -422,7 +422,7 @@ api_epg_grid
 
   /* Query the EPG */
   pthread_mutex_lock(&global_lock); 
-  epg_query(&eq);
+  epg_query(&eq, perm);
 
   /* Build response */
   start = MIN(eq.entries, start);
index 047d8aa31dd2a3ed36a8ea5cbcb4148b9db7c10d..77994e17f21565ea8ac90f5d83a6aed6d277504d 100644 (file)
@@ -309,14 +309,12 @@ const idclass_t channel_class = {
   .ic_get_title  = channel_class_get_title,
   .ic_delete     = channel_class_delete,
   .ic_properties = (const property_t[]){
-#if 0
     {
       .type     = PT_BOOL,
       .id       = "enabled",
       .name     = "Enabled",
       .off      = offsetof(channel_t, ch_enabled),
     },
-#endif
     {
       .type     = PT_STR,
       .id       = "name",
@@ -417,7 +415,7 @@ channel_find_by_name ( const char *name )
   if (name == NULL)
     return NULL;
   CHANNEL_FOREACH(ch)
-    if (!strcmp(channel_get_name(ch), name))
+    if (ch->ch_enabled && !strcmp(channel_get_name(ch), name))
       break;
   return ch;
 }
@@ -457,17 +455,23 @@ channel_find_by_number ( const char *no )
  * Check if user can access the channel
  */
 int
-channel_access(channel_t *ch, access_t *a, const char *username)
+channel_access(channel_t *ch, access_t *a, int disabled)
 {
+  if (!ch)
+    return 0;
+
+  if (!disabled && !ch->ch_enabled)
+    return 0;
+
   /* Channel number check */
-  if (ch && (a->aa_chmin || a->aa_chmax)) {
-    int chnum = channel_get_number(ch);
+  if (a->aa_chmin || a->aa_chmax) {
+    int64_t chnum = channel_get_number(ch);
     if (chnum < a->aa_chmin || chnum > a->aa_chmax)
       return 0;
   }
 
   /* Channel tag check */
-  if (ch && a->aa_chtags) {
+  if (a->aa_chtags) {
     channel_tag_mapping_t *ctm;
     htsmsg_field_t *f;
     HTSMSG_FOREACH(f, a->aa_chtags) {
@@ -722,6 +726,9 @@ channel_create0
     abort();
   }
 
+  /* Defaults */
+  ch->ch_enabled = 1;
+
   if (conf) {
     ch->ch_load = 1;
     idnode_load(&ch->ch_id, conf);
index cc38bcd143037166f765c1176718aaecb615b64a..b6c947c99cae04eeff0ac7a6fb3a13d333896037 100644 (file)
@@ -43,12 +43,13 @@ typedef struct channel
   idnode_t ch_id;
 
   RB_ENTRY(channel)   ch_link;
-  
+
   int ch_refcount;
   int ch_zombie;
   int ch_load;
 
   /* Channel info */
+  int     ch_enabled;
   char   *ch_name; // Note: do not access directly!
   int64_t ch_number;
   char   *ch_icon;
@@ -176,7 +177,7 @@ htsmsg_t * channel_tag_class_get_list(void *o);
 
 const char * channel_tag_get_icon(channel_tag_t *ct);
 
-int channel_access(channel_t *ch, struct access *a, const char *username);
+int channel_access(channel_t *ch, struct access *a, int disabled);
 
 int channel_tag_map(channel_t *ch, channel_tag_t *ct);
 void channel_tag_unmap(channel_t *ch, channel_tag_t *ct);
index 1dc3156d9afd5aedff5ada4792efe48f951f81ec..9e181c481022b4907ed91b66a4bccaedcedc33b3 100644 (file)
@@ -1047,6 +1047,7 @@ dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge)
     dvr_autorec_purge_spawns(dae, 1);
 
   CHANNEL_FOREACH(ch) {
+    if (!ch->ch_enabled) continue;
     RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
       if(autorec_cmp(dae, e))
         dvr_entry_create_by_autorec(e, dae);
index 5d37838724095e5f68c014abdadb5750855887c6..e29541ad1c163e9fa8d912bc0bccb7bb803d8bfb 100644 (file)
--- a/src/epg.c
+++ b/src/epg.c
@@ -2517,7 +2517,7 @@ static int _epg_sort_genre_descending ( const void *a, const void *b, void *eq )
 }
 
 epg_broadcast_t **
-epg_query ( epg_query_t *eq )
+epg_query ( epg_query_t *eq, access_t *perm )
 {
   channel_t *channel;
   channel_tag_t *tag;
@@ -2542,20 +2542,25 @@ epg_query ( epg_query_t *eq )
 
   /* Single channel */
   if (channel && tag == NULL) {
-    _eq_add_channel(eq, channel);
+    if (channel_access(channel, perm, 0))
+      _eq_add_channel(eq, channel);
   
   /* Tag based */
   } else if (tag) {
     channel_tag_mapping_t *ctm;
+    channel_t *ch2;
     LIST_FOREACH(ctm, &tag->ct_ctms, ctm_tag_link) {
-      if(channel == NULL || ctm->ctm_channel == channel)
-        _eq_add_channel(eq, ctm->ctm_channel);
+      ch2 = ctm->ctm_channel;
+      if(ch2 == channel || channel == NULL)
+        if (channel_access(channel, perm, 0))
+          _eq_add_channel(eq, ch2);
     }
 
   /* All channels */
   } else {
     CHANNEL_FOREACH(channel)
-      _eq_add_channel(eq, channel);
+      if (channel_access(channel, perm, 0))
+        _eq_add_channel(eq, channel);
   }
 
   switch (eq->sort_dir) {
index c639bf4726941e64715fa8e6f8b89306941859ee..28c5791eca000deb20eeec246df67bf2f6be9a44 100644 (file)
--- a/src/epg.h
+++ b/src/epg.h
@@ -22,6 +22,7 @@
 #include <regex.h>
 #include "settings.h"
 #include "lang_str.h"
+#include "access.h"
 
 /*
  * External forward decls
@@ -609,7 +610,7 @@ typedef struct epg_query {
   uint32_t          allocated;
 } epg_query_t;
 
-epg_broadcast_t  **epg_query(epg_query_t *eq);
+epg_broadcast_t  **epg_query(epg_query_t *eq, access_t *perm);
 void epg_query_free(epg_query_t *eq);
 
 /* ************************************************************************
index 2f3f6e163a8b8d0c2b9fa2697ad2e91fe1b393aa..4f42ca7102936034faf127426fa1107dfbc71551 100644 (file)
@@ -435,7 +435,7 @@ htsp_generate_challenge(htsp_connection_t *htsp)
 static inline int
 htsp_user_access_channel(htsp_connection_t *htsp, channel_t *ch)
 {
-  return channel_access(ch, htsp->htsp_granted_access, htsp->htsp_username);
+  return channel_access(ch, htsp->htsp_granted_access, 0);
 }
 
 #define HTSP_CHECK_CHANNEL_ACCESS(htsp, ch)\
@@ -1189,7 +1189,7 @@ htsp_method_epgQuery(htsp_connection_t *htsp, htsmsg_t *in)
     return htsp_error("User does not have access");
 
   /* Query */
-  epg_query(&eq);
+  epg_query(&eq, htsp->htsp_granted_access);
 
   /* Create Reply */
   out = htsmsg_create_map();
index 53e166ac4fe8359e148e35cf12107f7c6c42ac22..929c0f9dfc7d0030b40cf8a62d2a0fcce49523a0 100644 (file)
@@ -467,7 +467,7 @@ http_access_verify_channel(http_connection_t *hc, int mask,
   if (access_verify2(hc->hc_access, mask))
     return -1;
 
-  if (channel_access(ch, hc->hc_access, hc->hc_username))
+  if (channel_access(ch, hc->hc_access, 0))
     res = 0;
   return res;
 }
index 8f6d8b295713f1a0f9645ca4f1aaeb6204566211..18191e066a5f207f26430094133a85ea1dc628ab 100644 (file)
@@ -189,7 +189,7 @@ page_simple(http_connection_t *hc,
     eq.lang = strdup(lang);
 
     //Note: force min/max durations for this interface to 0 and INT_MAX seconds respectively
-    epg_query(&eq);
+    epg_query(&eq, hc->hc_access);
 
     c = eq.entries;
 
index 8637952144713842cab0e0d1bbd70f0586244a03..d9bc05a13770a55ca7769982aabed6b8d125437d 100644 (file)
@@ -59,7 +59,8 @@ dumpchannels(htsbuf_queue_t *hq)
 
   CHANNEL_FOREACH(ch) {
     
-    htsbuf_qprintf(hq, "%s (%d)\n", channel_get_name(ch), channel_get_id(ch));
+    htsbuf_qprintf(hq, "%s%s (%d)\n", !ch->ch_enabled ? "[DISABLED] " : "",
+                                      channel_get_name(ch), channel_get_id(ch));
     chnum = channel_get_number(ch);
     if (channel_get_minor(chnum))
       snprintf(chbuf, sizeof(chbuf), "%u.%u",
index abd79b0d6aca14a5f78085edd36c7ccdeeb2f5bf..c7b336f78a401c40f5ac71b1f58c0cfab0cdd74f 100644 (file)
@@ -512,12 +512,14 @@ http_channel_list_playlist(http_connection_t *hc)
   profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile"));
 
   CHANNEL_FOREACH(ch)
-    count++;
+    if (ch->ch_enabled)
+      count++;
 
   chlist = malloc(count * sizeof(channel_t *));
 
   CHANNEL_FOREACH(ch)
-    chlist[idx++] = ch;
+    if (ch->ch_enabled)
+      chlist[idx++] = ch;
 
   assert(idx == count);