Beispiel #1
0
static htsmsg_t *
hts_settings_load_one(const char *filename)
{
  ssize_t n;
  char *mem;
  fb_file *fp;
  htsmsg_t *r = NULL;

  /* Open */
  if (!(fp = fb_open(filename, 1, 0))) return NULL;
  
  /* Load data */
  mem    = malloc(fb_size(fp)+1);
  n      = fb_read(fp, mem, fb_size(fp));
  if (n >= 0) mem[n] = 0;

  /* Decode */
  if(n == fb_size(fp))
    r = htsmsg_json_deserialize(mem);

  /* Close */
  fb_close(fp);
  free(mem);

  return r;
}
Beispiel #2
0
static JSBool 
js_appendItem(JSContext *cx, JSObject *obj, uintN argc,
	      jsval *argv, jsval *rval)
{
  const char *url;
  const char *type = NULL;
  JSObject *metaobj = NULL;
  js_model_t *model = JS_GetPrivate(cx, obj);
  const char *canonical_url = NULL;
  htsmsg_t *m = NULL;
  JSBool r;

  if(!JS_ConvertArguments(cx, argc, argv, "s/so", &url, &type, &metaobj))
    return JS_FALSE;

  if(!strncmp(url, "videoparams:", strlen("videoparams:"))) {
    m = htsmsg_json_deserialize(url + strlen("videoparams:"));
    if(m != NULL) {
      canonical_url = htsmsg_get_str(m, "canonicalUrl");

      if(canonical_url == NULL) {
	htsmsg_t *sources;
	if((sources = htsmsg_get_list(m, "sources")) == NULL) {
	  htsmsg_field_t *f;
	  HTSMSG_FOREACH(f, sources) {
	    htsmsg_t *src = &f->hmf_msg;
	    canonical_url = htsmsg_get_str(src, "url");
	    if(canonical_url != NULL)
	      break;
	  }
Beispiel #3
0
int
cfg_load(const char *filename, const char *defconf)
{
  int err;
  static char *lastfilename;

  if(filename == NULL) {
    filename = lastfilename;

  } else {

    free(lastfilename);
    lastfilename = strdup(filename);
  }

  if(filename == NULL)
    filename = defconf;

  trace(LOG_NOTICE, "About to load config form %s", filename);

  char *cfgtxt = readfile(filename, &err, NULL);
  if(cfgtxt == NULL) {
    trace(LOG_ERR, "Unable to read file %s -- %s", filename, strerror(err));
    trace(LOG_ERR, "Config not updated");
    return -1;
  }

  char errbuf[256];
  htsmsg_t *m = htsmsg_json_deserialize(cfgtxt, errbuf, sizeof(errbuf));
  free(cfgtxt);
  if(m == NULL) {
    trace(LOG_ERR, "Unable to parse file %s -- %s", filename, errbuf);
    trace(LOG_ERR, "Config not updated");
    return -1;
  }

  pthread_mutex_lock(&cfg_mutex);
  if(cfgroot != NULL)
    htsmsg_release(cfgroot);

  cfgroot = m;
  htsmsg_retain(m);
  pthread_mutex_unlock(&cfg_mutex);
  trace(LOG_NOTICE, "Config updated");
  return 0;
}
Beispiel #4
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;
}
Beispiel #5
0
struct pixmap *
backend_imageloader(rstr_t *url0, const image_meta_t *im0,
		    const char **vpaths, char *errbuf, size_t errlen,
		    int *cache_control, cancellable_t *c)
{
  const char *url = rstr_get(url0);
  htsmsg_t *m = NULL;

  if(im0->im_req_width < -1 || im0->im_req_height < -1) {
    snprintf(errbuf, errlen, "Invalid dimensions");
    return NULL;
  }

  image_meta_t im = *im0;

  if(!strncmp(url, "thumb://", 8)) {
    url += 8;
    im.im_want_thumb = 1;
  }

  if(!strncmp(url, "imageset:", 9)) {

    m = htsmsg_json_deserialize(url+9);
    if(m == NULL) {
      snprintf(errbuf, errlen, "Invalid JSON");
      return NULL;
    }
    htsmsg_field_t *f;

    const char *best = NULL;
    int best_width = -1;
    int best_height = -1;

    HTSMSG_FOREACH(f, m) {
      htsmsg_t *img = htsmsg_get_map_by_field(f);
      if(img == NULL)
	continue;
      int w = htsmsg_get_u32_or_default(img, "width", 10000);
      int h = htsmsg_get_u32_or_default(img, "height", 10000);
      const char *u = htsmsg_get_str(img, "url");
      if(!u)
	continue;

      if(best != NULL) {

	if(im.im_req_width != -1) {
	  if(w >= im.im_req_width &&
	     (w < best_width || best_width < im.im_req_width))
	    goto gotone;
	  if(w < im.im_req_width && w > best_width)
	    goto gotone;

	} else if(im.im_req_height != -1) {
	  if(h >= im.im_req_height &&
	     (h < best_height || best_height < im.im_req_height))
	    goto gotone;
	  if(h < im.im_req_height && h > best_height)
	    goto gotone;
	} else {
	  if(w > best_width)
	    goto gotone;
	  if(h > best_height)
	    goto gotone;
	}
	continue;
      }
    gotone:
      best = u;
      best_width = w;
      best_height = h;

    }
Beispiel #6
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[256];

  if(fa_read(fh, buf, sizeof(buf)) != sizeof(buf))
    return 0;

  if(!memcmp(buf, "SNES-SPC700 Sound File Data", 27)) {
    fa_probe_spc(md, buf, filename);
    md->md_contenttype = CONTENT_AUDIO;
    return 1;
  }

  if(!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(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];
    char *buf;

    snprintf(path, sizeof(path), "zip://%s/plugin.json", url);
    buf = fa_load(path, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL);
    if(buf != NULL) {
      htsmsg_t *json = htsmsg_json_deserialize(buf);
      free(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((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); // Try to get more info
    return 1;
  }

  if(!memcmp(buf, "<showtimeplaylist", strlen("<showtimeplaylist"))) {
    /* Ugly playlist thing (see fa_video.c) */
    md->md_contenttype = CONTENT_VIDEO;
    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;
  }


  return 0;
}
Beispiel #7
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);
      }
    }
Beispiel #8
0
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);
    }
Beispiel #9
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);
}
Beispiel #10
0
static void
check_upgrade(int set_news)
{
  char url[1024];
  char *result;
  htsmsg_t *json;
  char errbuf[1024];

  if(inhibit_checks)
    return;

  if(upgrade_track == NULL) {
    prop_set_string(upgrade_error, "No release track specified");
    goto err;
  }

  prop_set_string(upgrade_status, "checking");

  TRACE(TRACE_DEBUG, "Upgrade", "Checking upgrades for %s-%s",
	upgrade_track, archname);

  snprintf(url, sizeof(url), "%s/%s-%s.json", ctrlbase, upgrade_track,
	   archname);

  result = fa_load(url, NULL, NULL, errbuf, sizeof(errbuf),
		   NULL, 0, NULL, NULL);
  if(result == NULL) {
    prop_set_string(upgrade_error, errbuf);
  err:
    prop_set_string(upgrade_status, "checkError");
    return;
  }
  
  json = htsmsg_json_deserialize(result);
  free(result);

  if(json == NULL) {
    prop_set_string(upgrade_error, "Malformed JSON in repository");
    goto err;
  }

  // Find an artifact for us

  const char *dlurl = NULL;
  const char *sha1 = NULL;
  int dlsize = 0;
  const char *ver;

  htsmsg_t *artifacts = htsmsg_get_list(json, "artifacts");
  if(artifacts != NULL) {
    htsmsg_field_t *f;
    HTSMSG_FOREACH(f, artifacts) {
      htsmsg_t *a;
      if((a = htsmsg_get_map_by_field(f)) == NULL)
	continue;

      const char *type = htsmsg_get_str(a, "type");

      if(type == NULL || strcmp(artifact_type, type))
	continue;

      dlurl = htsmsg_get_str(a, "url");
      sha1 = htsmsg_get_str(a, "sha1");
      dlsize = htsmsg_get_u32_or_default(a, "size", 0);
      break;
    }
Beispiel #11
0
static void
plugin_load(const char *url)
{
  char ctrlfile[URL_MAX];
  char *json;
  struct fa_stat fs;
  char errbuf[256];
  htsmsg_t *ctrl;

  snprintf(ctrlfile, sizeof(ctrlfile), "%s/plugin.json", url);

  json = fa_quickload(ctrlfile, &fs, NULL, errbuf, sizeof(errbuf));

  if(json == NULL) {
    TRACE(TRACE_ERROR, "plugins", "Unable to load plugin control file %s -- %s",
	  ctrlfile, errbuf);
    return;
  }
  
  ctrl = htsmsg_json_deserialize(json);

  if(ctrl != NULL) {

    const char *type = htsmsg_get_str(ctrl, "type");
    const char *file = htsmsg_get_str(ctrl, "file");
    const char *id   = htsmsg_get_str(ctrl, "id");

    if(type == NULL)
      TRACE(TRACE_ERROR, "plugins", 
	    "Missing \"type\" element in control file %s",
	    ctrlfile);
    
    if(file == NULL)
      TRACE(TRACE_ERROR, "plugins", 
	    "Missing \"file\" element in control file %s",
	    ctrlfile);

    if(id == NULL)
      TRACE(TRACE_ERROR, "plugins", 
	    "Missing \"id\" element in control file %s",
	    ctrlfile);

    if(type && file && id) {
      char fullpath[URL_MAX];

      snprintf(fullpath, sizeof(fullpath), "%s/%s", url, file);

      if(!strcmp(type, "javascript")) {

	plugin_load_js(id, fullpath);

      } else {
	TRACE(TRACE_ERROR, "plugins", "Unknown type \"%s\" in control file %s",
	      type, ctrlfile);
      }

    }

    htsmsg_destroy(ctrl);

  } else {

    TRACE(TRACE_ERROR, "plugins", "Unable parse JSON control file %s",
	  ctrlfile);
  }
  free(json);
}