static int vimeo_callback(http_connection_t *hc, const char *remain, void *opaque) { state_entry_t *vce; static state_entry_t *skel; const char *referer = http_arg_get(&hc->hc_args, "referer"); if(referer == NULL || strcmp(referer, "https://movian.tv/")) return 403; const char *state = http_arg_get(&hc->hc_req_args, "state"); const char *code = http_arg_get(&hc->hc_req_args, "code"); if(state == NULL || code == NULL) return 400; if(skel == NULL) skel = calloc(1, sizeof(state_entry_t)); skel->se_state = strdup(state); skel->se_code = strdup(code); pthread_mutex_lock(&state_mutex); vce = RB_INSERT_SORTED(&state_entries, skel, se_entry, state_entry_cmp); if (vce != NULL) vce->se_code = strdup(code); else skel = NULL; pthread_mutex_unlock(&state_mutex); return 200; }
/* * Complete data */ static int iptv_http_complete ( http_client_t *hc ) { iptv_mux_t *im = hc->hc_aux; char *url, *url2, *s, *p; url_t u; int r; if (im->im_m3u_header) { im->im_m3u_header = 0; sbuf_append(&im->mm_iptv_buffer, "", 1); url = iptv_http_m3u((char *)im->mm_iptv_buffer.sb_data); sbuf_reset(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (url == NULL) { tvherror("iptv", "m3u contents parsing failed"); return 0; } urlinit(&u); if (url[0] == '/') { s = strdupa(im->mm_iptv_url_raw); if ((p = strchr(s, '/')) != NULL) *p = '\0'; if (!urlparse(s, &u)) goto invalid; url2 = malloc(512); url2[0] = '\0'; if ((p = http_arg_get(&hc->hc_args, "Host")) != NULL) { snprintf(url2, 512, "%s://%s%s", hc->hc_ssl ? "https" : "http", p, url); } else if (im->mm_iptv_url_raw) { snprintf(url2, 512, "%s%s", s, url); } free(url); url = url2; urlinit(&u); } if (!urlparse(url, &u)) { hc->hc_keepalive = 0; r = http_client_simple_reconnect(hc, &u, HTTP_VERSION_1_1); if (r < 0) tvherror("iptv", "cannot reopen http client: %d'", r); } else { invalid: tvherror("iptv", "m3u url invalid '%s'", url); } urlreset(&u); free(url); return 0; } return 0; }
static int vimeo_code(http_connection_t *hc, const char *remain, void *opaque) { state_entry_t *vce; static state_entry_t *skel; const char *referer = http_arg_get(&hc->hc_args, "referer"); if(referer == NULL || strcmp(referer, "https://movian.tv/")) return 403; const char *state = http_arg_get(&hc->hc_req_args, "state"); if(state == NULL) return 400; if(skel == NULL) skel = calloc(1, sizeof(state_entry_t)); skel->se_state = (char *)state; pthread_mutex_lock(&state_mutex); vce = RB_FIND(&state_entries, skel, se_entry, state_entry_cmp); pthread_mutex_unlock(&state_mutex); if (vce == NULL) return 404; char *code = vce->se_code; htsmsg_t *msg = htsmsg_create_map(); htsmsg_add_str(msg, "code", code); char *out = htsmsg_json_serialize_to_str(msg, 0); htsbuf_append(&hc->hc_reply, out, strlen(out)); free(out); return http_send_reply(hc, 200, "application/json", NULL, NULL, 0); }
int rtsp_options_decode( http_client_t *hc ) { char *argv[32], *p; int i, n, what = 0; p = http_arg_get(&hc->hc_args, "Public"); if (p == NULL) return -EIO; n = http_tokenize(p, argv, 32, ','); for (i = 1; i < n; i++) { if (strcmp(argv[i], "DESCRIBE") == 0) what |= 1; else if (strcmp(argv[i], "SETUP") == 0) what |= 2; else if (strcmp(argv[i], "PLAY") == 0) what |= 4; else if (strcmp(argv[i], "TEARDOWN") == 0) what |= 8; } return (hc->hc_code != 200 && what != 0x0f) ? -EIO : HTTP_CON_OK; }
/* * Connected */ static int iptv_http_header ( http_client_t *hc ) { iptv_mux_t *im = hc->hc_aux; char *argv[3], *s; int n; if (hc->hc_aux == NULL) return 0; /* multiple headers for redirections */ if (hc->hc_code != HTTP_STATUS_OK) return 0; s = http_arg_get(&hc->hc_args, "Content-Type"); if (s) { n = http_tokenize(s, argv, ARRAY_SIZE(argv), ';'); if (n > 0 && (strcasecmp(s, "audio/mpegurl") == 0 || strcasecmp(s, "audio/x-mpegurl") == 0 || strcasecmp(s, "application/x-mpegurl") == 0 || strcasecmp(s, "application/apple.vnd.mpegurl") == 0 || strcasecmp(s, "application/vnd.apple.mpegurl") == 0)) { if (im->im_m3u_header > 10) { im->im_m3u_header = 0; return 0; } im->im_m3u_header++; return 0; } } im->im_m3u_header = 0; pthread_mutex_lock(&global_lock); iptv_input_mux_started(hc->hc_aux); pthread_mutex_unlock(&global_lock); return 0; }
int rtsp_setup_decode( http_client_t *hc, int satip ) { char *argv[32], *argv2[2], *p; int i, n, j; #if 0 { http_arg_t *ra; TAILQ_FOREACH(ra, &hc->hc_args, link) printf(" %s: %s\n", ra->key, ra->val); } #endif rtsp_clear_session(hc); if (hc->hc_code != 200) return -EIO; p = http_arg_get(&hc->hc_args, "Session"); if (p == NULL) return -EIO; n = http_tokenize(p, argv, 32, ';'); if (n < 1) return -EIO; hc->hc_rtsp_session = strdup(argv[0]); for (i = 1; i < n; i++) { if (strncasecmp(argv[i], "timeout=", 8) == 0) { hc->hc_rtp_timeout = atoi(argv[i] + 8); if (hc->hc_rtp_timeout < 20 || hc->hc_rtp_timeout > 3600) { tvhwarn(LS_RTSP, "timeout value out of range 20-3600 (%i)", hc->hc_rtp_timeout); return -EIO; } } } if (satip) { p = http_arg_get(&hc->hc_args, "com.ses.streamID"); if (p == NULL) return -EIO; /* zero is valid stream id per specification */ while (*p && ((*p == '0' && *(p + 1) == '0') || *p < ' ')) p++; if (p[0] == '0' && p[1] == '\0') { hc->hc_rtsp_stream_id = 0; } else { hc->hc_rtsp_stream_id = atoll(p); if (hc->hc_rtsp_stream_id <= 0) return -EIO; } } p = http_arg_get(&hc->hc_args, "Transport"); if (p == NULL) return -EIO; n = http_tokenize(p, argv, 32, ';'); if (n < 2) return -EIO; hc->hc_rtp_tcp = -1; hc->hc_rtcp_tcp = -1; hc->hc_rtp_port = -1; hc->hc_rtcp_port = -1; if (!strcasecmp(argv[0], "RTP/AVP/TCP")) { for (i = 1; i < n; i++) { if (strncmp(argv[i], "interleaved=", 12) == 0) { j = http_tokenize(argv[i] + 12, argv2, 2, '-'); if (j > 0) { hc->hc_rtp_tcp = atoi(argv2[0]); if (hc->hc_rtp_tcp < 0) return -EIO; if (j > 1) { hc->hc_rtcp_tcp = atoi(argv2[1]); if (hc->hc_rtcp_tcp < 0) return -EIO; } } else { return -EIO; } } } } else if (!strcasecmp(argv[0], "RTP/AVP") || !strcasecmp(argv[0], "RTP/AVP/UDP")) { if (n < 3) return -EIO; hc->hc_rtp_multicast = strcasecmp(argv[1], "multicast") == 0; if (strcasecmp(argv[1], "unicast") && !hc->hc_rtp_multicast) return -EIO; for (i = 2; i < n; i++) { if (strncmp(argv[i], "destination=", 12) == 0) hc->hc_rtp_dest = strdup(argv[i] + 12); else if (strncmp(argv[i], "client_port=", 12) == 0) { j = http_tokenize(argv[i] + 12, argv2, 2, '-'); if (j > 0) { hc->hc_rtp_port = atoi(argv2[0]); if (hc->hc_rtp_port <= 0) return -EIO; if (j > 1) { hc->hc_rtcp_port = atoi(argv2[1]); if (hc->hc_rtcp_port <= 0) return -EIO; } } else { return -EIO; } } else if (strncmp(argv[i], "server_port=", 12) == 0) { j = http_tokenize(argv[i] + 12, argv2, 2, '-'); if (j > 1) { hc->hc_rtcp_server_port = atoi(argv2[1]); if (hc->hc_rtcp_server_port <= 0) return -EIO; } else { return -EIO; } } } } else { return -EIO; } return HTTP_CON_OK; }
static void satip_discovery_http_closed(http_client_t *hc, int errn) { satip_discovery_t *d = hc->hc_aux; char *s; htsmsg_t *xml = NULL, *tags, *root, *device; const char *friendlyname, *manufacturer, *manufacturerURL, *modeldesc; const char *modelname, *modelnum, *serialnum; const char *presentation, *tunercfg, *udn, *uuid; const char *cs, *arg; satip_device_info_t info; char errbuf[100]; char *argv[10]; int i, n; s = http_arg_get(&hc->hc_args, "Content-Type"); if (s) { n = http_tokenize(s, argv, ARRAY_SIZE(argv), ';'); if (n <= 0 || strcasecmp(s, "text/xml")) { errn = ENOENT; s = NULL; } } if (errn != 0 || s == NULL || hc->hc_code != 200 || hc->hc_data_size == 0 || hc->hc_data == NULL) { tvhlog(LOG_ERR, "satip", "Cannot get %s: %s", d->location, strerror(errn)); return; } if (tvhtrace_enabled()) { tvhtrace("satip", "received XML description from %s", hc->hc_host); tvhlog_hexdump("satip", hc->hc_data, hc->hc_data_size); } if (d->myaddr == NULL || d->myaddr[0] == '\0') { struct sockaddr_storage ip; socklen_t addrlen = sizeof(ip); errbuf[0] = '\0'; getsockname(hc->hc_fd, (struct sockaddr *)&ip, &addrlen); inet_ntop(ip.ss_family, IP_IN_ADDR(ip), errbuf, sizeof(errbuf)); free(d->myaddr); d->myaddr = strdup(errbuf); } s = hc->hc_data + hc->hc_data_size - 1; while (s != hc->hc_data && *s != '/') s--; if (s != hc->hc_data) s--; if (strncmp(s, "</root>", 7)) return; /* Parse */ xml = htsmsg_xml_deserialize(hc->hc_data, errbuf, sizeof(errbuf)); hc->hc_data = NULL; if (!xml) { tvhlog(LOG_ERR, "satip_discovery_desc", "htsmsg_xml_deserialize error %s", errbuf); goto finish; } if ((tags = htsmsg_get_map(xml, "tags")) == NULL) goto finish; if ((root = htsmsg_get_map(tags, "root")) == NULL) goto finish; if ((device = htsmsg_get_map(root, "tags")) == NULL) goto finish; if ((device = htsmsg_get_map(device, "device")) == NULL) goto finish; if ((device = htsmsg_get_map(device, "tags")) == NULL) goto finish; if ((cs = htsmsg_xml_get_cdata_str(device, "deviceType")) == NULL) goto finish; if (strcmp(cs, "urn:ses-com:device:SatIPServer:1")) goto finish; if ((friendlyname = htsmsg_xml_get_cdata_str(device, "friendlyName")) == NULL) goto finish; if ((manufacturer = htsmsg_xml_get_cdata_str(device, "manufacturer")) == NULL) goto finish; if ((manufacturerURL = htsmsg_xml_get_cdata_str(device, "manufacturerURL")) == NULL) manufacturerURL = ""; if ((modeldesc = htsmsg_xml_get_cdata_str(device, "modelDescription")) == NULL) modeldesc = ""; if ((modelname = htsmsg_xml_get_cdata_str(device, "modelName")) == NULL) goto finish; if ((modelnum = htsmsg_xml_get_cdata_str(device, "modelNumber")) == NULL) modelnum = ""; if ((serialnum = htsmsg_xml_get_cdata_str(device, "serialNumber")) == NULL) serialnum = ""; if ((presentation = htsmsg_xml_get_cdata_str(device, "presentationURL")) == NULL) presentation = ""; if ((udn = htsmsg_xml_get_cdata_str(device, "UDN")) == NULL) goto finish; if ((tunercfg = htsmsg_xml_get_cdata_str(device, "urn:ses-com:satipX_SATIPCAP")) == NULL) tunercfg = ""; uuid = NULL; n = http_tokenize((char *)udn, argv, ARRAY_SIZE(argv), ':'); for (i = 0; i < n+1; i++) if (argv[i] && strcmp(argv[i], "uuid") == 0) { uuid = argv[++i]; break; } if (uuid == NULL || (d->uuid[0] && strcmp(uuid, d->uuid))) goto finish; info.rtsp_port = 554; info.srcs = 4; arg = http_arg_get(&hc->hc_args, "X-SATIP-RTSP-Port"); if (arg) { i = atoi(arg); if (i > 0 && i < 65535) info.rtsp_port = i; } arg = http_arg_get(&hc->hc_args, "X-SATIP-Sources"); if (arg) { i = atoi(arg); if (i > 0 && i < 128) info.srcs = i; } info.myaddr = strdup(d->myaddr); info.addr = strdup(d->url.host); info.uuid = strdup(uuid); info.bootid = strdup(d->bootid); info.configid = strdup(d->configid); info.deviceid = strdup(d->deviceid); info.location = strdup(d->location); info.server = strdup(d->server); info.friendlyname = strdup(friendlyname); info.manufacturer = strdup(manufacturer); info.manufacturerURL = strdup(manufacturerURL); info.modeldesc = strdup(modeldesc); info.modelname = strdup(modelname); info.modelnum = strdup(modelnum); info.serialnum = strdup(serialnum); info.presentation = strdup(presentation); info.tunercfg = strdup(tunercfg); htsmsg_destroy(xml); xml = NULL; pthread_mutex_lock(&global_lock); if (!satip_device_find(info.uuid)) satip_device_create(&info); pthread_mutex_unlock(&global_lock); free(info.myaddr); free(info.location); free(info.server); free(info.addr); free(info.uuid); free(info.bootid); free(info.configid); free(info.deviceid); free(info.friendlyname); free(info.manufacturer); free(info.manufacturerURL); free(info.modeldesc); free(info.modelname); free(info.modelnum); free(info.serialnum); free(info.presentation); free(info.tunercfg); finish: htsmsg_destroy(xml); }
/** * Root page, we direct the client to different pages depending * on if it is a full blown browser or just some mobile app */ static int page_simple(http_connection_t *hc, const char *remain, void *opaque) { htsbuf_queue_t *hq = &hc->hc_reply; const char *s = http_arg_get(&hc->hc_req_args, "s"); epg_broadcast_t *e; int c, k, i; struct tm a, b, day; dvr_entry_t *de; dvr_query_result_t dqr; const char *rstatus = NULL; epg_query_result_t eqr; const char *lang = http_arg_get(&hc->hc_args, "Accept-Language"); htsbuf_qprintf(hq, "<html>"); htsbuf_qprintf(hq, "<body>"); htsbuf_qprintf(hq, "<form>"); htsbuf_qprintf(hq, "Event: <input type=\"text\" "); if(s != NULL) htsbuf_qprintf(hq, "value=\"%s\" ", s); htsbuf_qprintf(hq, "name=\"s\">"); htsbuf_qprintf(hq, "<input type=\"submit\" value=\"Search\">"); htsbuf_qprintf(hq, "</form><hr>"); pthread_mutex_lock(&global_lock); if(s != NULL) { //Note: force min/max durations for this interface to 0 and INT_MAX seconds respectively epg_query(&eqr, NULL, NULL, NULL, s, lang, 0, INT_MAX); epg_query_sort(&eqr); c = eqr.eqr_entries; if(eqr.eqr_entries == 0) { htsbuf_qprintf(hq, "<b>No matching entries found</b>"); } else { htsbuf_qprintf(hq, "<b>%d entries found", c); if(c > 25) { c = 25; htsbuf_qprintf(hq, ", %d entries shown", c); } htsbuf_qprintf(hq, "</b>"); memset(&day, -1, sizeof(struct tm)); for(k = 0; k < c; k++) { e = eqr.eqr_array[k]; localtime_r(&e->start, &a); localtime_r(&e->stop, &b); if(a.tm_wday != day.tm_wday || a.tm_mday != day.tm_mday || a.tm_mon != day.tm_mon || a.tm_year != day.tm_year) { memcpy(&day, &a, sizeof(struct tm)); htsbuf_qprintf(hq, "<br><i>%s, %d/%d</i><br>", days[day.tm_wday], day.tm_mday, day.tm_mon + 1); } de = dvr_entry_find_by_event(e); rstatus = de != NULL ? val2str(de->de_sched_state, recstatustxt) : NULL; s = epg_broadcast_get_title(e, lang); htsbuf_qprintf(hq, "<a href=\"/eventinfo/%u\">" "%02d:%02d-%02d:%02d %s%s%s</a><br>", e->id, a.tm_hour, a.tm_min, b.tm_hour, b.tm_min, s ?: "", rstatus ? " " : "", rstatus ?: ""); } } htsbuf_qprintf(hq, "<hr>"); epg_query_free(&eqr); }
static int http_github(http_connection_t *hc, const char *remain, void *opaque) { const char *pid = http_arg_get(&hc->hc_req_args, "project"); const char *key = http_arg_get(&hc->hc_req_args, "key"); if(pid == NULL) { trace(LOG_WARNING, "github: Missing 'project' in request"); return 400; } if(key == NULL) { trace(LOG_WARNING, "github: Missing 'key' in request"); return 400; } project_cfg(pc, pid); if(pc == NULL) { trace(LOG_DEBUG, "github: Project '%s' not configured", pid); return 404; } const char *mykey = cfg_get_str(pc, CFG("github", "key"), ""); if(strcmp(mykey, key)) { trace(LOG_WARNING, "github: Invalid key received (%s) for project %s", key, pid); return 403; } project_t *p = project_get(pid); const char *json = http_arg_get(&hc->hc_req_args, "payload"); if(json == NULL) { plog(p, "github", "github: Missing payload in request"); return 400; } char errbuf[256]; htsmsg_t *msg = htsmsg_json_deserialize(json, errbuf, sizeof(errbuf)); if(msg == NULL) { plog(p, "github", "github: Malformed JSON in github request -- %s", errbuf); return 400; } const char *ref = htsmsg_get_str(msg, "ref"); if(ref != NULL && !strncmp(ref, "refs/heads/", strlen("refs/heads/"))) ref += strlen("refs/heads/"); htsmsg_t *list = htsmsg_get_list(msg, "commits"); if(ref != NULL && list != NULL) { htsmsg_field_t *f; HTSMSG_FOREACH(f, list) { htsmsg_t *c = htsmsg_get_map_by_field(f); if(c == NULL) continue; const char *url = htsmsg_get_str(c, "url"); const char *msg = htsmsg_get_str(c, "message"); htsmsg_t *a = htsmsg_get_map(c, "author"); const char *author = a ? htsmsg_get_str(a, "name") : NULL; int added = count_list(c, "added"); int removed = count_list(c, "removed"); int modified = count_list(c, "modified"); int len; char buf[512]; char ctx[128]; url = url ? urlshorten(url) : NULL; snprintf(ctx, sizeof(ctx), "changes/%s", ref); len = snprintf(buf, sizeof(buf), "Commit in '"COLOR_BLUE"%s"COLOR_OFF"' by "COLOR_PURPLE"%s"COLOR_OFF" [", ref, author ?: "???"); if(added) len += snprintf(buf + len, sizeof(buf) - len, COLOR_GREEN "%d file%s added", added, added == 1 ? "" : "s"); if(modified) len += snprintf(buf + len, sizeof(buf) - len, COLOR_YELLOW "%s%d file%s modified", added ? ", " : "", modified, modified == 1 ? "" : "s"); if(removed) len += snprintf(buf + len, sizeof(buf) - len, COLOR_RED "%s%d file%s removed", added || modified ? ", " : "", removed, removed == 1 ? "" : "s"); snprintf(buf + len, sizeof(buf) - len, COLOR_OFF"]%s%s", url ? " " : "", url ?: ""); plog(p, ctx, "%s", buf); plog(p, ctx, "%s", msg); }