コード例 #1
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;
}
コード例 #2
0
ファイル: resume.c プロジェクト: xzcvczx/transmission
static uint64_t loadFilenames(tr_variant* dict, tr_torrent* tor)
{
    tr_variant* list;
    uint64_t ret = 0;

    if (tr_variantDictFindList(dict, TR_KEY_files, &list))
    {
        size_t const n = tr_variantListSize(list);
        tr_file* files = tor->info.files;

        for (size_t i = 0; i < tor->info.fileCount && i < n; ++i)
        {
            char const* str;
            size_t str_len;

            if (tr_variantGetStr(tr_variantListChild(list, i), &str, &str_len) && str != NULL && str_len != 0)
            {
                tr_free(files[i].name);
                files[i].name = tr_strndup(str, str_len);
                files[i].is_renamed = true;
            }
        }

        ret = TR_FR_FILENAMES;
    }

    return ret;
}
コード例 #3
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;
}
コード例 #4
0
ファイル: edit.c プロジェクト: Kengi/Transmission
static bool
announce_list_has_url (tr_variant * announce_list, const char * url)
{
  tr_variant * tier;
  int tierCount = 0;
  while ((tier = tr_variantListChild (announce_list, tierCount++)))
    {
      tr_variant * node;
      const char * str;
      int nodeCount = 0;
      while ((node = tr_variantListChild (tier, nodeCount++)))
        if (tr_variantGetStr (node, &str, NULL) && !strcmp (str, url))
          return true;
    }

  return false;
}
コード例 #5
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;
}
コード例 #6
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;
}
コード例 #7
0
ファイル: edit.c プロジェクト: Kengi/Transmission
static bool
replaceURL (tr_variant * metainfo, const char * in, const char * out)
{
  const char * str;
  tr_variant * announce_list;
  bool changed = false;

  if (tr_variantDictFindStr (metainfo, TR_KEY_announce, &str, NULL) && strstr (str, in))
    {
      char * newstr = replaceSubstr (str, in, out);
      printf ("\tReplaced in \"announce\": \"%s\" --> \"%s\"\n", str, newstr);
      tr_variantDictAddStr (metainfo, TR_KEY_announce, newstr);
      tr_free (newstr);
      changed = true;
    }

  if (tr_variantDictFindList (metainfo, TR_KEY_announce_list, &announce_list))
    {
      tr_variant * tier;
      int tierCount = 0;
      while ((tier = tr_variantListChild (announce_list, tierCount++)))
        {
          tr_variant * node;
          int nodeCount = 0;
          while ((node = tr_variantListChild (tier, nodeCount++)))
            {
              if (tr_variantGetStr (node, &str, NULL) && strstr (str, in))
                {
                  char * newstr = replaceSubstr (str, in, out);
                  printf ("\tReplaced in \"announce-list\" tier %d: \"%s\" --> \"%s\"\n", tierCount, str, newstr);
                  tr_variantFree (node);
                  tr_variantInitStr (node, newstr, -1);
                  tr_free (newstr);
                  changed = true;
                }
            }
        }
    }

  return changed;
}
コード例 #8
0
ファイル: resume.c プロジェクト: DerFlatulator/transmission
static uint64_t
loadDND (tr_variant * dict, tr_torrent * tor)
{
    uint64_t ret = 0;
    tr_variant * list = NULL;
    const tr_file_index_t n = tor->info.fileCount;

    if (tr_variantDictFindList (dict, TR_KEY_dnd, &list)
      && (tr_variantListSize (list) == n))
    {
        int64_t           tmp;
        tr_file_index_t * dl = tr_new (tr_file_index_t, n);
        tr_file_index_t * dnd = tr_new (tr_file_index_t, n);
        tr_file_index_t   i, dlCount = 0, dndCount = 0;

        for (i=0; i<n; ++i)
        {
            if (tr_variantGetInt (tr_variantListChild (list, i), &tmp) && tmp)
                dnd[dndCount++] = i;
            else
                dl[dlCount++] = i;
        }

        if (dndCount)
        {
            tr_torrentInitFileDLs (tor, dnd, dndCount, false);
            tr_logAddTorDbg (tor, "Resume file found %d files listed as dnd",
                       dndCount);
        }
        if (dlCount)
        {
            tr_torrentInitFileDLs (tor, dl, dlCount, true);
            tr_logAddTorDbg (tor,
                       "Resume file found %d files marked for download",
                       dlCount);
        }

        tr_free (dnd);
        tr_free (dl);
        ret = TR_FR_DND;
    }
    else
    {
        tr_logAddTorDbg (
            tor,
            "Couldn't load DND flags. DND list (%p) has %zu children; torrent has %d files",
            list, tr_variantListSize (list), (int)n);
    }

    return ret;
}
コード例 #9
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;
}
コード例 #10
0
ファイル: resume.c プロジェクト: DerFlatulator/transmission
static uint64_t
loadFilePriorities (tr_variant * dict, tr_torrent * tor)
{
    tr_variant * list;
    uint64_t ret = 0;
    const tr_file_index_t n = tor->info.fileCount;

    if (tr_variantDictFindList (dict, TR_KEY_priority, &list)
      && (tr_variantListSize (list) == n))
    {
        int64_t priority;
        tr_file_index_t i;
        for (i = 0; i < n; ++i)
            if (tr_variantGetInt (tr_variantListChild (list, i), &priority))
                tr_torrentInitFilePriority (tor, i, priority);
        ret = TR_FR_FILE_PRIORITIES;
    }

    return ret;
}
コード例 #11
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;
}
コード例 #12
0
static tr_pex*
listToPex (tr_variant * peerList, size_t * setme_len)
{
    size_t i;
    size_t n;
    const size_t len = tr_variantListSize (peerList);
    tr_pex * pex = tr_new0 (tr_pex, len);

    for (i=n=0; i<len; ++i)
    {
        int64_t port;
        const char * ip;
        tr_address addr;
        tr_variant * peer = tr_variantListChild (peerList, i);

        if (peer == NULL)
            continue;
        if (!tr_variantDictFindStr (peer, TR_KEY_ip, &ip, NULL))
            continue;
        if (!tr_address_from_string (&addr, ip))
            continue;
        if (!tr_variantDictFindInt (peer, TR_KEY_port, &port))
            continue;
        if ((port < 0) || (port > USHRT_MAX))
            continue;
        if (!tr_address_is_valid_for_peers (&addr, port))
            continue;

        pex[n].addr = addr;
        pex[n].port = htons ((uint16_t)port);
        ++n;
    }

    *setme_len = n;
    return pex;
}
コード例 #13
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;
}
コード例 #14
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;
}
コード例 #15
0
ファイル: edit.c プロジェクト: Kengi/Transmission
static bool
removeURL (tr_variant * metainfo, const char * url)
{
  const char * str;
  tr_variant * announce_list;
  bool changed = false;

  if (tr_variantDictFindStr (metainfo, TR_KEY_announce, &str, NULL) && !strcmp (str, url))
    {
      printf ("\tRemoved \"%s\" from \"announce\"\n", str);
      tr_variantDictRemove (metainfo, TR_KEY_announce);
      changed = true;
    }

  if (tr_variantDictFindList (metainfo, TR_KEY_announce_list, &announce_list))
    {
      tr_variant * tier;
      int tierIndex = 0;
      while ((tier = tr_variantListChild (announce_list, tierIndex)))
        {
          tr_variant * node;
          int nodeIndex = 0;
          while ((node = tr_variantListChild (tier, nodeIndex)))
            {
              if (tr_variantGetStr (node, &str, NULL) && !strcmp (str, url))
                {
                  printf ("\tRemoved \"%s\" from \"announce-list\" tier #%d\n", str, (tierIndex+1));
                  tr_variantListRemove (tier, nodeIndex);
                  changed = true;
                }
              else ++nodeIndex;
            }

          if (tr_variantListSize (tier) == 0)
            {
              printf ("\tNo URLs left in tier #%d... removing tier\n", (tierIndex+1));
              tr_variantListRemove (announce_list, tierIndex);
            }
          else
            {
              ++tierIndex;
            }
        }

      if (tr_variantListSize (announce_list) == 0)
        {
          printf ("\tNo tiers left... removing announce-list\n");
          tr_variantDictRemove (metainfo, TR_KEY_announce_list);
        }
    }

  /* if we removed the "announce" field and there's still another track left,
   * use it as the "announce" field */
  if (changed && !tr_variantDictFindStr (metainfo, TR_KEY_announce, &str, NULL))
    {
      tr_variant * tier;
      tr_variant * node;

      if ((tier = tr_variantListChild (announce_list, 0)))
        {
          if ((node = tr_variantListChild (tier, 0)))
            {
              if (tr_variantGetStr (node, &str, NULL))
                {
                  tr_variantDictAddStr (metainfo, TR_KEY_announce, str);
                  printf ("\tAdded \"%s\" to announce\n", str);
                }
            }
        }
    }

  return changed;
}