static void http_callback(http_req_aux_t *req, void *opaque) { char errbuf[128]; tracker_torrent_t *tt = opaque; torrent_t *to = tt->tt_torrent; htsmsg_t *msg; net_addr_t na; assert(tt->tt_http_req != NULL); tt->tt_http_req = NULL; buf_t *b = http_req_get_result(req); tt->tt_interval = MIN(3600, tt->tt_interval * 2); if(b != NULL) { msg = bencode_deserialize(buf_cstr(b), buf_cstr(b) + buf_size(b), errbuf, sizeof(errbuf), NULL, NULL); if(msg != NULL) { const char *err = htsmsg_get_str(msg, "failure reason"); if(err != NULL) { tracker_trace(tt->tt_tracker, "%s for %s", err, to->to_title); goto done; } const char *trackerid = htsmsg_get_str(msg, "trackerid"); if(trackerid != NULL) mystrset(&tt->tt_trackerid, trackerid); tt->tt_interval = htsmsg_get_u32_or_default(msg, "min interval", htsmsg_get_u32_or_default(msg, "interval", 1800)); htsmsg_t *peers = htsmsg_get_list(msg, "peers"); if(peers != NULL) { htsmsg_field_t *f; HTSMSG_FOREACH(f, peers) { htsmsg_t *sub = htsmsg_get_map_by_field(f); if(sub == NULL) continue; const char *ip = htsmsg_get_str(sub, "ip"); if(ip == NULL) continue; if(net_resolve_numeric(ip, &na)) continue; na.na_port = htsmsg_get_u32_or_default(sub, "port", 0); if(na.na_port == 0) continue; peer_add(to, &na); } }
static int is_ttml(buf_t *buf) { if(buf_len(buf) < 30) return 0; if(memcmp(buf_cstr(buf), "<?xml", 5)) return 0; if(strstr(buf_cstr(buf), "http://www.w3.org/2006/10/ttaf1") == NULL) return 0; return 1; }
static int is_timedtext(buf_t *buf) { if(buf_len(buf) < 30) return 0; if(memcmp(buf_cstr(buf), "<?xml", 5)) return 0; if(strstr(buf_cstr(buf), "<transcript>") == NULL) return 0; return 1; }
/** * Load a view file and do lexographical parsing * * Returns pointer to last token, or NULL if an error occured. * If an error occured 'ei' will be filled with data */ token_t * glw_view_load1(glw_root_t *gr, rstr_t *url, errorinfo_t *ei, token_t *prev, int may_unlock) { token_t *last; char errbuf[256]; rstr_t *p = fa_absolute_path(url, prev->file); if(may_unlock) glw_unlock(gr); buf_t *b = fa_load(rstr_get(p), FA_LOAD_VPATHS(gr->gr_vpaths), FA_LOAD_ERRBUF(errbuf, sizeof(errbuf)), NULL); if(may_unlock) glw_lock(gr); if(b == NULL) { snprintf(ei->error, sizeof(ei->error), "Unable to open \"%s\" -- %s", rstr_get(p), errbuf); snprintf(ei->file, sizeof(ei->file), "%s", rstr_get(prev->file)); ei->line = prev->line; rstr_release(p); return NULL; } last = glw_view_lexer(gr, buf_cstr(b), ei, p, prev); buf_release(b); rstr_release(p); return last; }
static htsmsg_t * tmdb_load_movie_cast(const char *lookup_id) { char url[300]; char errbuf[256]; buf_t *result; snprintf(url, sizeof(url), "http://api.themoviedb.org/3/movie/%s/casts", lookup_id); retry: tmdb_check_rate_limit(); int http_response_code = 0; struct http_header_list response_headers; LIST_INIT(&response_headers); result = fa_load(url, FA_LOAD_ERRBUF(errbuf, sizeof(errbuf)), FA_LOAD_QUERY_ARG("api_key", TMDB_APIKEY), FA_LOAD_QUERY_ARG("language", getlang()), FA_LOAD_RESPONSE_HEADERS(&response_headers), FA_LOAD_PROTOCOL_CODE(&http_response_code), FA_LOAD_FLAGS(FA_COMPRESSION), NULL); if(result == NULL) { if(http_response_code == 429) { tmdb_handle_rate_limit(&response_headers); goto retry; } http_headers_free(&response_headers); TRACE(TRACE_INFO, "TMDB", "Load error %s", errbuf); return NULL; } http_headers_free(&response_headers); htsmsg_t *doc = htsmsg_json_deserialize2(buf_cstr(result), errbuf, sizeof(errbuf)); if(doc == NULL) { TRACE(TRACE_ERROR, "TMDB", "Got bad JSON from %s -- %s", url, errbuf); } buf_release(result); return doc; }
JSBool js_cache_get(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { buf_t *b; char stash[256]; char errbuf[256]; const char *key,*lstash; JSObject *o; js_plugin_t *jsp = JS_GetPrivate(cx, obj); if (!JS_ConvertArguments(cx, argc, argv, "ss", &lstash, &key)) return JS_FALSE; // fetch json from cache snprintf(stash, sizeof(stash), "plugin/%s/%s", jsp->jsp_id, lstash); b = blobcache_get(key, stash, 0, NULL, NULL, NULL); if(b == NULL) { *rval = OBJECT_TO_JSVAL(NULL); return JS_TRUE; } // deserialize into json object if(!JS_EnterLocalRootScope(cx)) return JS_FALSE; o = json_deserialize(buf_cstr(b), &json_to_jsapi, cx, errbuf, sizeof(errbuf)); buf_release(b); *rval = OBJECT_TO_JSVAL(o); JS_LeaveLocalRootScope(cx); if(o == NULL) { JS_ReportError(cx, "Invalid JSON stored in cache -- %s", errbuf); return JS_FALSE; } return JS_TRUE; }
static int tmdb_configure(void) { hts_mutex_lock(&tmdb_mutex); if(!tmdb_configured) { buf_t *result; char errbuf[256]; result = fa_load("http://api.themoviedb.org/3/configuration", FA_LOAD_ERRBUF(errbuf, sizeof(errbuf)), FA_LOAD_QUERY_ARG("api_key", TMDB_APIKEY), FA_LOAD_QUERY_ARG("language", getlang()), FA_LOAD_FLAGS(FA_COMPRESSION | FA_IMPORTANT), NULL); if(result == NULL) { TRACE(TRACE_INFO, "TMDB", "Unable to get configuration -- %s", errbuf); goto done; } htsmsg_t *doc = htsmsg_json_deserialize2(buf_cstr(result), errbuf, sizeof(errbuf)); buf_release(result); if(doc == NULL) { TRACE(TRACE_ERROR, "TMDB", "Got bad JSON from config -- %s", errbuf); goto done; } tmdb_parse_config(doc); htsmsg_release(doc); tmdb_configured = 1; } done: hts_mutex_unlock(&tmdb_mutex); return !tmdb_configured; }
static loaded_msg_t * htsmsg_store_obtain(const char *key, int create) { char errbuf[512]; htsmsg_t *r = NULL; loaded_msg_t *lm; LIST_FOREACH(lm, &loaded_msgs, lm_link) if(!strcmp(lm->lm_key, key)) return lm; buf_t *b = persistent_load("settings", key, errbuf, sizeof(errbuf)); if(b == NULL) { if(!create) { return NULL; } } else { r = htsmsg_json_deserialize(buf_cstr(b)); buf_release(b); if(r == NULL && !create) return NULL; } if(r == NULL) r = htsmsg_create_map(); lm = calloc(1, sizeof(loaded_msg_t)); atomic_set(&lm->lm_refcount, 1); lm->lm_key = strdup(key); LIST_INSERT_HEAD(&loaded_msgs, lm, lm_link); lm->lm_msg = r; callout_arm_managed(&lm->lm_timer, htsmsg_store_timer_cb, lm, SETTINGS_CACHE_DELAY, htsmsg_store_lockmgr); return lm; }
JSBool js_get_descriptor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { char pdesc[PATH_MAX]; char *pe; buf_t *b; char errbuf[128]; JSObject *o; js_plugin_t *jsp = JS_GetPrivate(cx, obj); snprintf(pdesc, sizeof(pdesc),"%s", jsp->jsp_url); pe = strrchr(pdesc, '/'); if (pe == NULL) return JS_FALSE; snprintf(pe + 1, sizeof(pdesc) - (pe - pdesc), "plugin.json"); b = fa_load(pdesc, FA_LOAD_ERRBUF(errbuf, sizeof(errbuf)), NULL); if (b == NULL) { TRACE(TRACE_ERROR, "JS", "Unable to read %s -- %s", pdesc, errbuf); return JS_FALSE; } if (!JS_EnterLocalRootScope(cx)) return JS_FALSE; o = json_deserialize(buf_cstr(b), &json_to_jsapi, cx, errbuf, sizeof(errbuf)); buf_release(b); *rval = OBJECT_TO_JSVAL(o); JS_LeaveLocalRootScope(cx); return JS_TRUE; }
static int hc_image(http_connection_t *hc, const char *remain, void *opaque, http_cmd_t method) { htsbuf_queue_t out; image_t *img; char errbuf[200]; const char *content; image_meta_t im = {0}; im.im_no_decoding = 1; rstr_t *url; const char *u = http_arg_get_req(hc, "url"); if(u != NULL) { url = rstr_alloc(u); url_deescape(rstr_data(url)); } else { if(remain == NULL) { return 404; } url = rstr_alloc(remain); } img = backend_imageloader(url, &im, NULL, errbuf, sizeof(errbuf), NULL, NULL); rstr_release(url); if(img == NULL) return http_error(hc, 404, "Unable to load image %s : %s", remain, errbuf); const image_component_t *ic = image_find_component(img, IMAGE_CODED); if(ic == NULL) { image_release(img); return http_error(hc, 404, "Unable to load image %s : Original data not available", remain); } const image_component_coded_t *icc = &ic->coded; htsbuf_queue_init(&out, 0); htsbuf_append(&out, buf_cstr(icc->icc_buf), buf_len(icc->icc_buf)); switch(icc->icc_type) { case IMAGE_JPEG: content = "image/jpeg"; break; case IMAGE_PNG: content = "image/png"; break; case IMAGE_GIF: content = "image/gif"; break; default: content = "image"; break; } image_release(img); return http_send_reply(hc, 0, content, NULL, NULL, 0, &out); }
void load_site_news(void) { #if ENABLE_WEBPOPUP struct http_header_list response_headers; buf_t *b; char errbuf[512]; b = fa_load("https://movian.tv/projects/movian/news.json", FA_LOAD_FLAGS(FA_DISABLE_AUTH | FA_COMPRESSION), FA_LOAD_RESPONSE_HEADERS(&response_headers), FA_LOAD_ERRBUF(errbuf, sizeof(errbuf)), NULL); if(b == NULL) { TRACE(TRACE_DEBUG, "News", "Unable to load news -- %s", errbuf); return; } const char *dateheader = http_header_get(&response_headers, "date"); if(dateheader == NULL) { buf_release(b); http_headers_free(&response_headers); return; } dateheader = mystrdupa(dateheader); http_headers_free(&response_headers); htsmsg_t *newsinfo = htsmsg_store_load("sitenews"); time_t no_news_before; if(newsinfo == NULL) newsinfo = htsmsg_create_map(); no_news_before = htsmsg_get_u32_or_default(newsinfo, "nothingbefore", 0); if(no_news_before == 0) { if(http_ctime(&no_news_before, dateheader)) { buf_release(b); htsmsg_release(newsinfo); return; } htsmsg_add_u32(newsinfo, "nothingbefore", no_news_before); htsmsg_store_save(newsinfo, "sitenews"); htsmsg_release(newsinfo); } htsmsg_t *doc = htsmsg_json_deserialize(buf_cstr(b)); buf_release(b); if(doc == NULL) { return; } hts_mutex_lock(&news_mutex); htsmsg_t *news = htsmsg_get_list(doc, "news"); if(news != NULL) { htsmsg_field_t *f; HTSMSG_FOREACH(f, news) { htsmsg_t *entry; if((entry = htsmsg_get_map_by_field(f)) == NULL) continue; const char *title = htsmsg_get_str(entry, "title"); const char *created_on = htsmsg_get_str(entry, "created_on"); int id = htsmsg_get_u32_or_default(entry, "id", 0); if(created_on == NULL || title == NULL || id == 0) continue; time_t t; if(parse_created_on_time(&t, created_on)) continue; if(t < no_news_before) continue; char idstr[64]; snprintf(idstr, sizeof(idstr), "sitenews:%d", id); prop_t *p = add_news_locked(idstr, title, NULL, "Read more", idstr); if(p != NULL) { prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, open_news, p, PROP_TAG_ROOT, prop_create(p, "eventSink"), PROP_TAG_MUTEX, &news_mutex, NULL); } }
static void screenshot_process(void *task) { pixmap_t *pm = task; if(pm == NULL) { screenshot_response(NULL, "Screenshot not supported on this platform"); return; } TRACE(TRACE_DEBUG, "Screenshot", "Processing image %d x %d", pm->pm_width, pm->pm_height); int codecid = AV_CODEC_ID_PNG; if(screenshot_connection) codecid = AV_CODEC_ID_MJPEG; buf_t *b = screenshot_compress(pm, codecid); pixmap_release(pm); if(b == NULL) { screenshot_response(NULL, "Unable to compress image"); return; } if(!screenshot_connection) { char path[512]; char errbuf[512]; snprintf(path, sizeof(path), "%s/screenshot.png", gconf.cache_path); fa_handle_t *fa = fa_open_ex(path, errbuf, sizeof(errbuf), FA_WRITE, NULL); if(fa == NULL) { TRACE(TRACE_ERROR, "SCREENSHOT", "Unable to open %s -- %s", path, errbuf); buf_release(b); return; } fa_write(fa, buf_data(b), buf_len(b)); fa_close(fa); TRACE(TRACE_INFO, "SCREENSHOT", "Written to %s", path); buf_release(b); return; } buf_t *result = NULL; htsbuf_queue_t hq; htsbuf_queue_init(&hq, 0); htsbuf_append(&hq, "image=", 6); htsbuf_append_and_escape_url_len(&hq, buf_cstr(b), buf_len(b)); char errbuf[256]; int ret = http_req("https://api.imgur.com/3/upload", HTTP_FLAGS(FA_CONTENT_ON_ERROR), HTTP_REQUEST_HEADER("Authorization", "Client-ID 7c79b311d4797ed"), HTTP_RESULT_PTR(&result), HTTP_POSTDATA(&hq, "application/x-www-form-urlencoded"), HTTP_ERRBUF(errbuf, sizeof(errbuf)), NULL); if(ret) { screenshot_response(NULL, errbuf); } else { htsmsg_t *response = htsmsg_json_deserialize(buf_cstr(result)); if(response == NULL) { screenshot_response(NULL, "Unable to parse imgur response"); } else { if(htsmsg_get_u32_or_default(response, "success", 0)) { const char *url = htsmsg_get_str_multi(response, "data", "link", NULL); screenshot_response(url, "No link in imgur response"); } else { const char *msg = htsmsg_get_str_multi(response, "data", "error", NULL); if(msg == NULL) { screenshot_response(NULL, "Unkown imgur error"); } else { snprintf(errbuf, sizeof(errbuf), "Imgur error: %s", msg); screenshot_response(NULL, errbuf); } } htsmsg_release(response); } buf_release(result); } buf_release(b); }
/** * Probe file by checking its header * * pb is guaranteed to point to at least 256 bytes of valid data */ static int fa_probe_header(metadata_t *md, const char *url, fa_handle_t *fh, const char *filename) { uint16_t flags; uint8_t buf[1025]; int l = fa_read(fh, buf, sizeof(buf) - 1); if(l < 8) return 0; buf[l] = 0; if(l >= 256 && !memcmp(buf, "SNES-SPC700 Sound File Data", 27)) { fa_probe_spc(md, buf, filename); md->md_contenttype = CONTENT_AUDIO; return 1; } if(l >= 256 && (!memcmp(buf, "PSID", 4) || !memcmp(buf, "RSID", 4))) { fa_probe_psid(md, buf); md->md_contenttype = CONTENT_ALBUM; metdata_set_redirect(md, "sidfile://%s/", url); return 1; } if(l >= 16 && buf[0] == 'R' && buf[1] == 'a' && buf[2] == 'r' && buf[3] == '!' && buf[4] == 0x1a && buf[5] == 0x07 && buf[6] == 0x0 && buf[9] == 0x73) { flags = buf[10] | buf[11] << 8; if((flags & 0x101) == 1) { /* Don't include slave volumes */ md->md_contenttype = CONTENT_UNKNOWN; return 1; } metdata_set_redirect(md, "rar://%s", url); md->md_contenttype = CONTENT_ARCHIVE; return 1; } if(buf[0] == 0x50 && buf[1] == 0x4b && buf[2] == 0x03 && buf[3] == 0x04) { char path[256]; buf_t *buf; snprintf(path, sizeof(path), "zip://%s/plugin.json", url); buf = fa_load(path, NULL, NULL, 0, NULL, 0, NULL, NULL); if(buf != NULL) { htsmsg_t *json = htsmsg_json_deserialize(buf_cstr(buf)); buf_release(buf); if(json != NULL) { const char *title = htsmsg_get_str(json, "title"); if(title != NULL && htsmsg_get_str(json, "id") != NULL && htsmsg_get_str(json, "type") != NULL) { md->md_title = rstr_alloc(title); md->md_contenttype = CONTENT_PLUGIN; htsmsg_destroy(json); return 1; } htsmsg_destroy(json); } } metdata_set_redirect(md, "zip://%s", url); md->md_contenttype = CONTENT_ARCHIVE; return 1; } #if 0 if(!strncasecmp((char *)buf, "[playlist]", 10)) { /* Playlist */ fa_probe_playlist(md, url, buf, sizeof(buf)); md->md_contenttype = CONTENT_PLAYLIST; return 1; } #endif if(l > 16 && ((buf[6] == 'J' && buf[7] == 'F' && buf[8] == 'I' && buf[9] == 'F') || (buf[6] == 'E' && buf[7] == 'x' && buf[8] == 'i' && buf[9] == 'f'))) { /* JPEG image */ md->md_contenttype = CONTENT_IMAGE; fa_probe_exif(md, url, buf, fh, l); // Try to get more info return 1; } if(!memcmp(buf, pngsig, 8)) { /* PNG */ md->md_contenttype = CONTENT_IMAGE; return 1; } if(!memcmp(buf, gifsig, sizeof(gifsig))) { /* GIF */ md->md_contenttype = CONTENT_IMAGE; return 1; } if(buf[0] == '%' && buf[1] == 'P' && buf[2] == 'D' && buf[3] == 'F') { md->md_contenttype = CONTENT_UNKNOWN; return 1; } if(!memcmp(buf, ttfsig, sizeof(ttfsig)) || !memcmp(buf, otfsig, sizeof(otfsig))) { /* TTF or OTF */ md->md_contenttype = CONTENT_FONT; return 1; } if(l > 16 && mystrbegins((const char *)buf, "#EXTM3U") && (strstr((const char *)buf, "#EXT-X-STREAM-INF:") || strstr((const char *)buf, "#EXT-X-TARGETDURATION:") || strstr((const char *)buf, "#EXT-X-MEDIA-SEQUENCE:"))) { md->md_contenttype = CONTENT_VIDEO; return 1; } return 0; }