コード例 #1
0
ファイル: rpc-test.c プロジェクト: neverlee/Transmission
static int
test_list (void)
{
  size_t len;
  int64_t i;
  const char * str;
  tr_variant top;

  tr_rpc_parse_list_str (&top, "12", -1);
  check (tr_variantIsInt (&top));
  check (tr_variantGetInt (&top, &i));
  check_int_eq (12, i);
  tr_variantFree (&top);

  tr_rpc_parse_list_str (&top, "12", 1);
  check (tr_variantIsInt (&top));
  check (tr_variantGetInt (&top, &i));
  check_int_eq (1, i);
  tr_variantFree (&top);

  tr_rpc_parse_list_str (&top, "6,7", -1);
  check (tr_variantIsList (&top));
  check (tr_variantListSize (&top) == 2);
  check (tr_variantGetInt (tr_variantListChild (&top, 0), &i));
  check_int_eq (6, i);
  check (tr_variantGetInt (tr_variantListChild (&top, 1), &i));
  check_int_eq (7, i);
  tr_variantFree (&top);

  tr_rpc_parse_list_str (&top, "asdf", -1);
  check (tr_variantIsString (&top));
  check (tr_variantGetStr (&top, &str, &len));
  check_int_eq (4, len);
  check_streq ("asdf", str);
  tr_variantFree (&top);

  tr_rpc_parse_list_str (&top, "1,3-5", -1);
  check (tr_variantIsList (&top));
  check (tr_variantListSize (&top) == 4);
  check (tr_variantGetInt (tr_variantListChild (&top, 0), &i));
  check_int_eq (1, i);
  check (tr_variantGetInt (tr_variantListChild (&top, 1), &i));
  check_int_eq (3, i);
  check (tr_variantGetInt (tr_variantListChild (&top, 2), &i));
  check_int_eq (4, i);
  check (tr_variantGetInt (tr_variantListChild (&top, 3), &i));
  check_int_eq (5, i);
  tr_variantFree (&top);

  return 0;
}
コード例 #2
0
ファイル: variant-benc.c プロジェクト: JanX2/transmission
static tr_variant*
get_node (tr_ptrArray * stack, tr_quark * key, tr_variant * top, int * err)
{
  tr_variant * node = NULL;

  if (tr_ptrArrayEmpty (stack))
    {
      node = top;
    }
  else
    {
      tr_variant * parent = tr_ptrArrayBack (stack);

      if (tr_variantIsList (parent))
        {
          node = tr_variantListAdd (parent);
        }
      else if (*key && tr_variantIsDict (parent))
        {
          node = tr_variantDictAdd (parent, *key);
          *key = 0;
        }
      else
        {
          *err = EILSEQ;
        }
    }

  return node;
}
コード例 #3
0
ファイル: variant-json.c プロジェクト: pelegrin/Transmission
static tr_variant*
get_node (struct jsonsl_st * jsn)
{
  tr_variant * parent;
  tr_variant * node = NULL;
  struct json_wrapper_data * data = jsn->data;

  parent = tr_ptrArrayEmpty (&data->stack)
         ? NULL
         : tr_ptrArrayBack (&data->stack);

  if (!parent)
    {
      node = data->top;
    }
  else if (tr_variantIsList (parent))
    {
      node = tr_variantListAdd (parent);
    }
  else if (tr_variantIsDict (parent) && (data->key!=NULL))
    {
      node = tr_variantDictAdd (parent, tr_quark_new (data->key, data->keylen));

      data->key = NULL;
      data->keylen = 0;
    }

  return node;
}
コード例 #4
0
static const char*
parseFiles (tr_info * inf, tr_variant * files, const tr_variant * length)
{
  int64_t len;

  inf->totalSize = 0;

  if (tr_variantIsList (files)) /* multi-file mode */
    {
      tr_file_index_t i;
      struct evbuffer * buf = evbuffer_new ();

      inf->isMultifile = 1;
      inf->fileCount = tr_variantListSize (files);
      inf->files = tr_new0 (tr_file, inf->fileCount);

      for (i=0; i<inf->fileCount; i++)
        {
          tr_variant * file;
          tr_variant * path;

          file = tr_variantListChild (files, i);
          if (!tr_variantIsDict (file))
            return "files";

          if (!tr_variantDictFindList (file, TR_KEY_path_utf_8, &path))
            if (!tr_variantDictFindList (file, TR_KEY_path, &path))
              return "path";

          if (!getfile (&inf->files[i].name, inf->name, path, buf))
            return "path";

          if (!tr_variantDictFindInt (file, TR_KEY_length, &len))
            return "length";

          inf->files[i].length = len;
          inf->totalSize      += len;
        }

      evbuffer_free (buf);
    }
  else if (tr_variantGetInt (length, &len)) /* single-file mode */
    {
      if (path_is_suspicious (inf->name))
        return "path";

      inf->isMultifile      = 0;
      inf->fileCount        = 1;
      inf->files            = tr_new0 (tr_file, 1);
      inf->files[0].name    = tr_strdup (inf->name);
      inf->files[0].length  = len;
      inf->totalSize       += len;
    }
  else
    {
      return "length";
    }

  return NULL;
}
コード例 #5
0
ファイル: metainfo.c プロジェクト: JanX2/transmission
static bool
getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer * buf)
{
  bool success = false;
  size_t root_len = 0;

  *setme = NULL;

  /* root's already been checked by caller */
  assert (!path_component_is_suspicious (root));

  if (tr_variantIsList (path))
    {
      int i;
      const int n = tr_variantListSize (path);

      success = true;
      evbuffer_drain (buf, evbuffer_get_length (buf));
      root_len = strlen (root);
      evbuffer_add (buf, root, root_len);

      for (i=0; i<n; i++)
        {
          size_t len;
          const char * str;

          if (!tr_variantGetStr (tr_variantListChild (path, i), &str, &len) ||
              path_component_is_suspicious (str))
            {
              success = false;
              break;
            }

          if (!*str)
            continue;

          evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
          evbuffer_add (buf, str, len);
        }
    }

  if (success && (evbuffer_get_length (buf) <= root_len))
    {
      success = false;
    }

  if (success)
    {
      *setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
      /*fprintf (stderr, "[%s]\n", *setme);*/
    }

  return success;
}
コード例 #6
0
ファイル: json-test.c プロジェクト: camellan/torrential
static int test1(void)
{
    char const* in =
        "{\n"
        "    \"headers\": {\n"
        "        \"type\": \"request\",\n"
        "        \"tag\": 666\n"
        "    },\n"
        "    \"body\": {\n"
        "        \"name\": \"torrent-info\",\n"
        "        \"arguments\": {\n"
        "            \"ids\": [ 7, 10 ]\n"
        "        }\n"
        "    }\n"
        "}\n";
    tr_variant top;
    tr_variant* headers;
    tr_variant* body;
    tr_variant* args;
    tr_variant* ids;
    char const* str;
    int64_t i;
    int const err = tr_variantFromJson(&top, in, strlen(in));

    check_int(err, ==, 0);
    check(tr_variantIsDict(&top));
    check_ptr((headers = tr_variantDictFind(&top, tr_quark_new("headers", 7))), !=, NULL);
    check(tr_variantIsDict(headers));
    check(tr_variantDictFindStr(headers, tr_quark_new("type", 4), &str, NULL));
    check_str(str, ==, "request");
    check(tr_variantDictFindInt(headers, TR_KEY_tag, &i));
    check_int(i, ==, 666);
    check_ptr((body = tr_variantDictFind(&top, tr_quark_new("body", 4))), !=, NULL);
    check(tr_variantDictFindStr(body, TR_KEY_name, &str, NULL));
    check_str(str, ==, "torrent-info");
    check_ptr((args = tr_variantDictFind(body, tr_quark_new("arguments", 9))), !=, NULL);
    check(tr_variantIsDict(args));
    check_ptr((ids = tr_variantDictFind(args, TR_KEY_ids)), !=, NULL);
    check(tr_variantIsList(ids));
    check_uint(tr_variantListSize(ids), ==, 2);
    check(tr_variantGetInt(tr_variantListChild(ids, 0), &i));
    check_int(i, ==, 7);
    check(tr_variantGetInt(tr_variantListChild(ids, 1), &i));
    check_int(i, ==, 10);

    tr_variantFree(&top);
    return 0;
}
コード例 #7
0
ファイル: json-test.c プロジェクト: Javierortizc/transmission
static int
test1 (void)
{
    const char * in =
        "{\n"
        "    \"headers\": {\n"
        "        \"type\": \"request\",\n"
        "        \"tag\": 666\n"
        "    },\n"
        "    \"body\": {\n"
        "        \"name\": \"torrent-info\",\n"
        "        \"arguments\": {\n"
        "            \"ids\": [ 7, 10 ]\n"
        "        }\n"
        "    }\n"
        "}\n";
    tr_variant      top, *headers, *body, *args, *ids;
    const char * str;
    int64_t      i;
    const int    err = tr_variantFromJson (&top, in, strlen(in));

    check (!err);
    check (tr_variantIsDict (&top));
    check ((headers = tr_variantDictFind (&top, tr_quark_new("headers",7))));
    check (tr_variantIsDict (headers));
    check (tr_variantDictFindStr (headers, tr_quark_new("type",4), &str, NULL));
    check_streq ("request", str);
    check (tr_variantDictFindInt (headers, TR_KEY_tag, &i));
    check_int_eq (666, i);
    check ((body = tr_variantDictFind (&top, tr_quark_new("body",4))));
    check (tr_variantDictFindStr (body, TR_KEY_name, &str, NULL));
    check_streq ("torrent-info", str);
    check ((args = tr_variantDictFind (body, tr_quark_new("arguments",9))));
    check (tr_variantIsDict (args));
    check ((ids = tr_variantDictFind (args, TR_KEY_ids)));
    check (tr_variantIsList (ids));
    check_int_eq (2, tr_variantListSize (ids));
    check (tr_variantGetInt (tr_variantListChild (ids, 0), &i));
    check_int_eq (7, i);
    check (tr_variantGetInt (tr_variantListChild (ids, 1), &i));
    check_int_eq (10, i);

    tr_variantFree (&top);
    return 0;
}
コード例 #8
0
static bool
getfile (char ** setme, const char * root, tr_variant * path, struct evbuffer * buf)
{
  bool success = false;

  if (tr_variantIsList (path))
    {
      int i;
      const int n = tr_variantListSize (path);

      evbuffer_drain (buf, evbuffer_get_length (buf));
      evbuffer_add (buf, root, strlen (root));
      for (i=0; i<n; i++)
        {
          size_t len;
          const char * str;

          if (tr_variantGetStr (tr_variantListChild (path, i), &str, &len))
            {
              evbuffer_add (buf, TR_PATH_DELIMITER_STR, 1);
              evbuffer_add (buf, str, len);
            }
        }

      *setme = tr_utf8clean ((char*)evbuffer_pullup (buf, -1), evbuffer_get_length (buf));
      /* fprintf (stderr, "[%s]\n", *setme); */
      success = true;
    }

  if ((*setme != NULL) && path_is_suspicious (*setme))
    {
      tr_free (*setme);
      *setme = NULL;
      success = false;
    }

  return success;
}
コード例 #9
0
ファイル: metainfo.c プロジェクト: Mikayex/transmission
static char const* parseFiles(tr_info* inf, tr_variant* files, tr_variant const* length)
{
    int64_t len;

    inf->totalSize = 0;

    if (tr_variantIsList(files)) /* multi-file mode */
    {
        struct evbuffer* buf;
        char const* result;

        if (path_component_is_suspicious(inf->name))
        {
            return "path";
        }

        buf = evbuffer_new();
        result = NULL;

        inf->isFolder = true;
        inf->fileCount = tr_variantListSize(files);
        inf->files = tr_new0(tr_file, inf->fileCount);

        for (tr_file_index_t i = 0; i < inf->fileCount; i++)
        {
            tr_variant* file;
            tr_variant* path;

            file = tr_variantListChild(files, i);

            if (!tr_variantIsDict(file))
            {
                result = "files";
                break;
            }

            if (!tr_variantDictFindList(file, TR_KEY_path_utf_8, &path))
            {
                if (!tr_variantDictFindList(file, TR_KEY_path, &path))
                {
                    result = "path";
                    break;
                }
            }

            if (!getfile(&inf->files[i].name, inf->name, path, buf))
            {
                result = "path";
                break;
            }

            if (!tr_variantDictFindInt(file, TR_KEY_length, &len))
            {
                result = "length";
                break;
            }

            inf->files[i].length = len;
            inf->totalSize += len;
        }

        evbuffer_free(buf);
        return result;
    }
    else if (tr_variantGetInt(length, &len)) /* single-file mode */
    {
        if (path_component_is_suspicious(inf->name))
        {
            return "path";
        }

        inf->isFolder = false;
        inf->fileCount = 1;
        inf->files = tr_new0(tr_file, 1);
        inf->files[0].name = tr_strdup(inf->name);
        inf->files[0].length = len;
        inf->totalSize += len;
    }
    else
    {
        return "length";
    }

    return NULL;
}
コード例 #10
0
ファイル: resume.c プロジェクト: xzcvczx/transmission
static uint64_t loadProgress(tr_variant* dict, tr_torrent* tor)
{
    uint64_t ret = 0;
    tr_variant* prog;
    tr_info const* inf = tr_torrentInfo(tor);

    for (size_t i = 0; i < inf->pieceCount; ++i)
    {
        inf->pieces[i].timeChecked = 0;
    }

    if (tr_variantDictFindDict(dict, TR_KEY_progress, &prog))
    {
        char const* err;
        char const* str;
        uint8_t const* raw;
        size_t rawlen;
        tr_variant* l;
        tr_variant* b;
        struct tr_bitfield blocks = TR_BITFIELD_INIT;

        if (tr_variantDictFindList(prog, TR_KEY_time_checked, &l))
        {
            /* per-piece timestamps were added in 2.20.

               If some of a file's pieces have been checked more recently than
               the file's mtime, and some lest recently, then that file will
               have a list containing timestamps for each piece.

               However, the most common use case is that the file doesn't change
               after it's downloaded. To reduce overhead in the .resume file,
               only a single timestamp is saved for the file if *all* or *none*
               of the pieces were tested more recently than the file's mtime. */

            for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
            {
                tr_variant* b = tr_variantListChild(l, fi);
                tr_file const* f = &inf->files[fi];

                if (tr_variantIsInt(b))
                {
                    int64_t t;
                    tr_variantGetInt(b, &t);

                    for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
                    {
                        inf->pieces[i].timeChecked = (time_t)t;
                    }
                }
                else if (tr_variantIsList(b))
                {
                    int64_t offset = 0;
                    int const pieces = f->lastPiece + 1 - f->firstPiece;

                    tr_variantGetInt(tr_variantListChild(b, 0), &offset);

                    for (int i = 0; i < pieces; ++i)
                    {
                        int64_t t = 0;
                        tr_variantGetInt(tr_variantListChild(b, i + 1), &t);
                        inf->pieces[f->firstPiece + i].timeChecked = (time_t)(t != 0 ? t + offset : 0);
                    }
                }
            }
        }
        else if (tr_variantDictFindList(prog, TR_KEY_mtimes, &l))
        {
            /* Before 2.20, we stored the files' mtimes in the .resume file.
               When loading the .resume file, a torrent's file would be flagged
               as untested if its stored mtime didn't match its real mtime. */

            for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
            {
                int64_t t;

                if (tr_variantGetInt(tr_variantListChild(l, fi), &t))
                {
                    tr_file const* f = &inf->files[fi];
                    time_t const mtime = tr_torrentGetFileMTime(tor, fi);
                    time_t const timeChecked = mtime == t ? mtime : 0;

                    for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
                    {
                        inf->pieces[i].timeChecked = timeChecked;
                    }
                }
            }
        }

        err = NULL;
        tr_bitfieldConstruct(&blocks, tor->blockCount);

        if ((b = tr_variantDictFind(prog, TR_KEY_blocks)) != NULL)
        {
            size_t buflen;
            uint8_t const* buf;

            if (!tr_variantGetRaw(b, &buf, &buflen))
            {
                err = "Invalid value for \"blocks\"";
            }
            else if (buflen == 3 && memcmp(buf, "all", 3) == 0)
            {
                tr_bitfieldSetHasAll(&blocks);
            }
            else if (buflen == 4 && memcmp(buf, "none", 4) == 0)
            {
                tr_bitfieldSetHasNone(&blocks);
            }
            else
            {
                tr_bitfieldSetRaw(&blocks, buf, buflen, true);
            }
        }
        else if (tr_variantDictFindStr(prog, TR_KEY_have, &str, NULL))
        {
            if (strcmp(str, "all") == 0)
            {
                tr_bitfieldSetHasAll(&blocks);
            }
            else
            {
                err = "Invalid value for HAVE";
            }
        }
        else if (tr_variantDictFindRaw(prog, TR_KEY_bitfield, &raw, &rawlen))
        {
            tr_bitfieldSetRaw(&blocks, raw, rawlen, true);
        }
        else
        {
            err = "Couldn't find 'pieces' or 'have' or 'bitfield'";
        }

        if (err != NULL)
        {
            tr_logAddTorDbg(tor, "Torrent needs to be verified - %s", err);
        }
        else
        {
            tr_cpBlockInit(&tor->completion, &blocks);
        }

        tr_bitfieldDestruct(&blocks);
        ret = TR_FR_PROGRESS;
    }

    return ret;
}