From: Jaroslav Kysela Date: Fri, 21 Nov 2014 17:02:27 +0000 (+0100) Subject: channel enhancements (enabled), fixed min/max chnum handling (access) X-Git-Tag: v4.1~707 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=da3d9ecb48ab162faf0d7136eed25e7bb4cef92a;p=thirdparty%2Ftvheadend.git channel enhancements (enabled), fixed min/max chnum handling (access) --- diff --git a/src/access.c b/src/access.c index 45fd6af21..945390cf1 100644 --- a/src/access.c +++ b/src/access.c @@ -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 ?: "", a->aa_username ?: "", 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), diff --git a/src/access.h b/src/access.h index 536bf5c01..336b78d5a 100644 --- a/src/access.h +++ b/src/access.h @@ -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; diff --git a/src/api/api_channel.c b/src/api/api_channel.c index 58ffe6bb0..6cdbe34dc 100644 --- a/src/api/api_channel.c +++ b/src/api/api_channel.c @@ -25,21 +25,28 @@ #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 diff --git a/src/api/api_epg.c b/src/api/api_epg.c index 771414b5c..dac92579f 100644 --- a/src/api/api_epg.c +++ b/src/api/api_epg.c @@ -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); diff --git a/src/channels.c b/src/channels.c index 047d8aa31..77994e17f 100644 --- a/src/channels.c +++ b/src/channels.c @@ -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); diff --git a/src/channels.h b/src/channels.h index cc38bcd14..b6c947c99 100644 --- a/src/channels.h +++ b/src/channels.h @@ -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); diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 1dc3156d9..9e181c481 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -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); diff --git a/src/epg.c b/src/epg.c index 5d3783872..e29541ad1 100644 --- 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) { diff --git a/src/epg.h b/src/epg.h index c639bf472..28c5791ec 100644 --- a/src/epg.h +++ b/src/epg.h @@ -22,6 +22,7 @@ #include #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); /* ************************************************************************ diff --git a/src/htsp_server.c b/src/htsp_server.c index 2f3f6e163..4f42ca710 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -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(); diff --git a/src/http.c b/src/http.c index 53e166ac4..929c0f9df 100644 --- a/src/http.c +++ b/src/http.c @@ -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; } diff --git a/src/webui/simpleui.c b/src/webui/simpleui.c index 8f6d8b295..18191e066 100644 --- a/src/webui/simpleui.c +++ b/src/webui/simpleui.c @@ -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; diff --git a/src/webui/statedump.c b/src/webui/statedump.c index 863795214..d9bc05a13 100644 --- a/src/webui/statedump.c +++ b/src/webui/statedump.c @@ -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", diff --git a/src/webui/webui.c b/src/webui/webui.c index abd79b0d6..c7b336f78 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -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);