Esempio n. 1
0
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);
        }
      }
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
/**
 * 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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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);
}
Esempio n. 11
0
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);
      }
    }
Esempio n. 12
0
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);
}
Esempio n. 13
0
/**
 * 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;
}