Exemplo n.º 1
0
static void on_announce_done(tr_session * session, bool did_connect, bool did_timeout,
    long response_code, const void * msg, size_t msglen, void * vdata) {
    tr_announce_response * response;
    struct announce_data * data = vdata;
    response = &data->response;
    (...)

    // lê os dados da resposta do tracker
    if (variant_loaded && tr_variantIsDict(&benc)) {
        int64_t i; size_t len; tr_variant * tmp; // variáveis ...
        const char * str; const uint8_t * raw;   // ... temporárias

        if (tr_variantDictFindStr(&benc, TR_KEY_failure_reason, &str, &len))
            response->errmsg = tr_strndup(str, len);

        if (tr_variantDictFindStr(&benc, TR_KEY_tracker_id, &str, &len))
            response->tracker_id_str = tr_strndup(str, len);

        if (tr_variantDictFindInt(&benc, TR_KEY_complete, &i))
            response->seeders = i;

        (...)

        if (tr_variantDictFindRaw(&benc, TR_KEY_peers, &raw, &len)) {
            response->pex = tr_peerMgrCompactToPex(raw, len,
            NULL, 0, &response->pex_count);
        }
        else if (tr_variantDictFindList(&benc, TR_KEY_peers, &tmp)) {
            response->pex = listToPex(tmp, &response->pex_count);
        }
    }
Exemplo n.º 2
0
static int
test_utf8 (void)
{
    const char      * in = "{ \"key\": \"Letöltések\" }";
    tr_variant           top;
    const char      * str;
    char            * json;
    int               err;
    const tr_quark key = tr_quark_new ("key", 3);

    err = tr_variantFromJson (&top, in, strlen(in));
    check (!err);
    check (tr_variantIsDict (&top));
    check (tr_variantDictFindStr (&top, key, &str, NULL));
    check_streq ("Letöltések", str);
    if (!err)
        tr_variantFree (&top);

    in = "{ \"key\": \"\\u005C\" }";
    err = tr_variantFromJson (&top, in, strlen(in));
    check (!err);
    check (tr_variantIsDict (&top));
    check (tr_variantDictFindStr (&top, key, &str, NULL));
    check_streq ("\\", str);
    if (!err)
        tr_variantFree (&top);

    /**
     * 1. Feed it JSON-escaped nonascii to the JSON decoder.
     * 2. Confirm that the result is UTF-8.
     * 3. Feed the same UTF-8 back into the JSON encoder.
     * 4. Confirm that the result is JSON-escaped.
     * 5. Dogfood that result back into the parser.
     * 6. Confirm that the result is UTF-8.
     */
    in = "{ \"key\": \"Let\\u00f6lt\\u00e9sek\" }";
    err = tr_variantFromJson (&top, in, strlen(in));
    check (!err);
    check (tr_variantIsDict (&top));
    check (tr_variantDictFindStr (&top, key, &str, NULL));
    check_streq ("Letöltések", str);
    json = tr_variantToStr (&top, TR_VARIANT_FMT_JSON, NULL);
    if (!err)
        tr_variantFree (&top);
    check (json);
    check (strstr (json, "\\u00f6") != NULL);
    check (strstr (json, "\\u00e9") != NULL);
    err = tr_variantFromJson (&top, json, strlen(json));
    check (!err);
    check (tr_variantIsDict (&top));
    check (tr_variantDictFindStr (&top, key, &str, NULL));
    check_streq ("Letöltések", str);
    if (!err)
        tr_variantFree (&top);
    tr_free (json);

    return 0;
}
Exemplo n.º 3
0
static int test_elements(void)
{
    char const* in;
    tr_variant top;
    char const* str;
    bool f;
    double d;
    int64_t i;
    int err = 0;
    tr_quark key;

    in =
        "{ \"string\": \"hello world\","
        "  \"escaped\": \"bell \\b formfeed \\f linefeed \\n carriage return \\r tab \\t\","
        "  \"int\": 5, "
        "  \"float\": 6.5, "
        "  \"true\": true, "
        "  \"false\": false, "
        "  \"null\": null }";

    err = tr_variantFromJson(&top, in, strlen(in));
    check_int(err, ==, 0);
    check(tr_variantIsDict(&top));
    str = NULL;
    key = tr_quark_new("string", 6);
    check(tr_variantDictFindStr(&top, key, &str, NULL));
    check_str(str, ==, "hello world");
    check(tr_variantDictFindStr(&top, tr_quark_new("escaped", 7), &str, NULL));
    check_str(str, ==, "bell \b formfeed \f linefeed \n carriage return \r tab \t");
    i = 0;
    check(tr_variantDictFindInt(&top, tr_quark_new("int", 3), &i));
    check_int(i, ==, 5);
    d = 0;
    check(tr_variantDictFindReal(&top, tr_quark_new("float", 5), &d));
    check_int(((int)(d * 10)), ==, 65);
    f = false;
    check(tr_variantDictFindBool(&top, tr_quark_new("true", 4), &f));
    check_int(f, ==, true);
    check(tr_variantDictFindBool(&top, tr_quark_new("false", 5), &f));
    check_int(f, ==, false);
    check(tr_variantDictFindStr(&top, tr_quark_new("null", 4), &str, NULL));
    check_str(str, ==, "");

    if (err == 0)
    {
        tr_variantFree(&top);
    }

    return 0;
}
Exemplo n.º 4
0
static int
test_elements (void)
{
    const char * in;
    tr_variant top;
    const char * str;
    bool f;
    double d;
    int64_t i;
    int err = 0;
    tr_quark key;

    in = "{ \"string\": \"hello world\","
         "  \"escaped\": \"bell \\b formfeed \\f linefeed \\n carriage return \\r tab \\t\","
         "  \"int\": 5, "
         "  \"float\": 6.5, "
         "  \"true\": true, "
         "  \"false\": false, "
         "  \"null\": null }";

    err = tr_variantFromJson (&top, in, strlen(in));
    check_int_eq (0, err);
    check (tr_variantIsDict (&top));
    str = NULL;
    key = tr_quark_new ("string", 6);
    check (tr_variantDictFindStr (&top, key, &str, NULL));
    check_streq ("hello world", str);
    check (tr_variantDictFindStr (&top, tr_quark_new("escaped",7), &str, NULL));
    check_streq ("bell \b formfeed \f linefeed \n carriage return \r tab \t", str);
    i = 0;
    check (tr_variantDictFindInt (&top, tr_quark_new("int",3), &i));
    check_int_eq (5, i);
    d = 0;
    check (tr_variantDictFindReal (&top, tr_quark_new("float",5), &d));
    check_int_eq (65, ((int)(d*10)));
    f = false;
    check (tr_variantDictFindBool (&top, tr_quark_new("true",4), &f));
    check_int_eq (true, f);
    check (tr_variantDictFindBool (&top, tr_quark_new("false",5), &f));
    check_int_eq (false, f);
    check (tr_variantDictFindStr (&top, tr_quark_new("null",4), &str, NULL));
    check_streq ("", str);

    if (!err)
        tr_variantFree (&top);

    return 0;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
const char*
gtr_pref_string_get (const tr_quark key)
{
  const char * str = NULL;

  tr_variantDictFindStr (getPrefs (), key, &str, NULL);

  return str;
}
Exemplo n.º 8
0
int
tr_ctorSetMetainfoFromFile (tr_ctor *    ctor,
                            const char * filename)
{
    uint8_t * metainfo;
    size_t    len;
    int       err;

    metainfo = tr_loadFile (filename, &len);
    if (metainfo && len)
        err = tr_ctorSetMetainfo (ctor, metainfo, len);
    else
    {
        clearMetainfo (ctor);
        err = 1;
    }

    setSourceFile (ctor, filename);

    /* if no `name' field was set, then set it from the filename */
    if (ctor->isSet_metainfo)
    {
        tr_variant * info;
        if (tr_variantDictFindDict (&ctor->metainfo, TR_KEY_info, &info))
        {
            const char * name;
            if (!tr_variantDictFindStr (info, TR_KEY_name_utf_8, &name, NULL))
                if (!tr_variantDictFindStr (info, TR_KEY_name, &name, NULL))
                    name = NULL;
            if (!name || !*name)
            {
                char * base = tr_sys_path_basename (filename, NULL);
                tr_variantDictAddStr (info, TR_KEY_name, base);
                tr_free (base);
            }
        }
    }

    tr_free (metainfo);
    return err;
}
Exemplo n.º 9
0
static int test_unescape(void)
{
    char const* in = "{ \"string-1\": \"\\/usr\\/lib\" }";
    tr_variant top;
    char const* str;

    int const err = tr_variantFromJson(&top, in, strlen(in));
    check_int(err, ==, 0);
    check(tr_variantDictFindStr(&top, tr_quark_new("string-1", 8), &str, NULL));
    check_str(str, ==, "/usr/lib");

    tr_variantFree(&top);
    return 0;
}
Exemplo n.º 10
0
static int
test_unescape (void)
{
    const char * in = "{ \"string-1\": \"\\/usr\\/lib\" }";
    tr_variant top;
    const char * str;

    const int err = tr_variantFromJson (&top, in, strlen(in));
    check_int_eq (0, err);
    check (tr_variantDictFindStr (&top, tr_quark_new("string-1",8), &str, NULL));
    check_streq ("/usr/lib", str);

    tr_variantFree (&top);
    return 0;
}
Exemplo n.º 11
0
static uint64_t loadName(tr_variant* dict, tr_torrent* tor)
{
    uint64_t ret = 0;
    char const* name;

    if (tr_variantDictFindStr(dict, TR_KEY_name, &name, NULL))
    {
        ret = TR_FR_NAME;

        if (tr_strcmp0(tr_torrentName(tor), name) != 0)
        {
            tr_free(tor->info.name);
            tor->info.name = tr_strdup(name);
        }
    }

    return ret;
}
Exemplo n.º 12
0
static bool
addURL (tr_variant * metainfo, const char * url)
{
  const char * announce = NULL;
  tr_variant * announce_list = NULL;
  bool changed = false;
  const bool had_announce = tr_variantDictFindStr (metainfo, TR_KEY_announce, &announce, NULL);
  const bool had_announce_list = tr_variantDictFindList (metainfo, TR_KEY_announce_list, &announce_list);

  if (!had_announce && !had_announce_list)
    {
      /* this new tracker is the only one, so add it to "announce"... */
      printf ("\tAdded \"%s\" in \"announce\"\n", url);
      tr_variantDictAddStr (metainfo, TR_KEY_announce, url);
      changed = true;
    }
  else
    {
      if (!had_announce_list)
        {
          announce_list = tr_variantDictAddList (metainfo, TR_KEY_announce_list, 2);

          if (had_announce)
            {
              /* we're moving from an 'announce' to an 'announce-list',
               * so copy the old announce URL to the list */
              tr_variant * tier = tr_variantListAddList (announce_list, 1);
              tr_variantListAddStr (tier, announce);
              changed = true;
            }
        }

      /* If the user-specified URL isn't in the announce list yet, add it */
      if (!announce_list_has_url (announce_list, url))
        {
          tr_variant * tier = tr_variantListAddList (announce_list, 1);
          tr_variantListAddStr (tier, url);
          printf ("\tAdded \"%s\" to \"announce-list\" tier %"TR_PRIuSIZE"\n", url, tr_variantListSize (announce_list));
          changed = true;
        }
    }

  return changed;
}
Exemplo n.º 13
0
static int test3(void)
{
    char const* in =
        "{ \"error\": 2,"
        "  \"errorString\": \"torrent not registered with this tracker 6UHsVW'*C\","
        "  \"eta\": 262792,"
        "  \"id\": 25,"
        "  \"leftUntilDone\": 2275655680 }";
    tr_variant top;
    char const* str;

    int const err = tr_variantFromJson(&top, in, strlen(in));
    check_int(err, ==, 0);
    check(tr_variantDictFindStr(&top, TR_KEY_errorString, &str, NULL));
    check_str(str, ==, "torrent not registered with this tracker 6UHsVW'*C");

    tr_variantFree(&top);
    return 0;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
static void
on_scrape_done (tr_session   * session,
                bool           did_connect,
                bool           did_timeout,
                long           response_code,
                const void   * msg,
                size_t         msglen,
                void         * vdata)
{
    tr_scrape_response * response;
    struct scrape_data * data = vdata;

    response = &data->response;
    response->did_connect = did_connect;
    response->did_timeout = did_timeout;
    dbgmsg (data->log_name, "Got scrape response for \"%s\"", response->url);

    if (response_code != HTTP_OK)
    {
        const char * fmt = _("Tracker gave HTTP response code %1$ld (%2$s)");
        const char * response_str = tr_webGetResponseStr (response_code);
        response->errmsg = tr_strdup_printf (fmt, response_code, response_str);
    }
    else
    {
        tr_variant top;
        int64_t intVal;
        tr_variant * files;
        tr_variant * flags;
        size_t len;
        const char * str;
        const bool variant_loaded = !tr_variantFromBenc (&top, msg, msglen);

        if (getenv ("TR_CURL_VERBOSE") != NULL)
        {
            if (!variant_loaded)
                fprintf (stderr, "%s", "Scrape response was not in benc format\n");
            else {
                int i, len;
                char * str = tr_variantToStr (&top, TR_VARIANT_FMT_JSON, &len);
                fprintf (stderr, "%s", "Scrape response:\n< ");
                for (i=0; i<len; ++i)
                    fputc (str[i], stderr);
                fputc ('\n', stderr);
                tr_free (str);
            }
        }

        if (variant_loaded)
        {
            if (tr_variantDictFindStr (&top, TR_KEY_failure_reason, &str, &len))
                response->errmsg = tr_strndup (str, len);

            if (tr_variantDictFindDict (&top, TR_KEY_flags, &flags))
                if (tr_variantDictFindInt (flags, TR_KEY_min_request_interval, &intVal))
                    response->min_request_interval = intVal;

            if (tr_variantDictFindDict (&top, TR_KEY_files, &files))
            {
                int i = 0;

                for (;;)
                {
                    int j;
                    tr_quark key;
                    tr_variant * val;

                    /* get the next "file" */
                    if (!tr_variantDictChild (files, i++, &key, &val))
                        break;

                    /* populate the corresponding row in our response array */
                    for (j=0; j<response->row_count; ++j)
                    {
                        struct tr_scrape_response_row * row = &response->rows[j];
                        if (!memcmp (tr_quark_get_string(key,NULL), row->info_hash, SHA_DIGEST_LENGTH))
                        {
                            if (tr_variantDictFindInt (val, TR_KEY_complete, &intVal))
                                row->seeders = intVal;
                            if (tr_variantDictFindInt (val, TR_KEY_incomplete, &intVal))
                                row->leechers = intVal;
                            if (tr_variantDictFindInt (val, TR_KEY_downloaded, &intVal))
                                row->downloads = intVal;
                            if (tr_variantDictFindInt (val, TR_KEY_downloaders, &intVal))
                                row->downloaders = intVal;
                            break;
                        }
                    }
                }
            }

            tr_variantFree (&top);
        }
    }

    tr_runInEventThread (session, on_scrape_done_eventthread, data);
}
Exemplo n.º 17
0
static void
on_announce_done (tr_session   * session,
                  bool           did_connect,
                  bool           did_timeout,
                  long           response_code,
                  const void   * msg,
                  size_t         msglen,
                  void         * vdata)
{
    tr_announce_response * response;
    struct announce_data * data = vdata;

    response = &data->response;
    response->did_connect = did_connect;
    response->did_timeout = did_timeout;
    dbgmsg (data->log_name, "Got announce response");

    if (response_code != HTTP_OK)
    {
        const char * fmt = _("Tracker gave HTTP response code %1$ld (%2$s)");
        const char * response_str = tr_webGetResponseStr (response_code);
        response->errmsg = tr_strdup_printf (fmt, response_code, response_str);
    }
    else
    {
        tr_variant benc;
        const bool variant_loaded = !tr_variantFromBenc (&benc, msg, msglen);

        if (getenv ("TR_CURL_VERBOSE") != NULL)
        {
            if (!variant_loaded)
                fprintf (stderr, "%s", "Announce response was not in benc format\n");
            else {
                int i, len;
                char * str = tr_variantToStr (&benc, TR_VARIANT_FMT_JSON, &len);
                fprintf (stderr, "%s", "Announce response:\n< ");
                for (i=0; i<len; ++i)
                    fputc (str[i], stderr);
                fputc ('\n', stderr);
                tr_free (str);
            }
        }

        if (variant_loaded && tr_variantIsDict (&benc))
        {
            int64_t i;
            size_t len;
            tr_variant * tmp;
            const char * str;
            const uint8_t * raw;

            if (tr_variantDictFindStr (&benc, TR_KEY_failure_reason, &str, &len))
                response->errmsg = tr_strndup (str, len);

            if (tr_variantDictFindStr (&benc, TR_KEY_warning_message, &str, &len))
                response->warning = tr_strndup (str, len);

            if (tr_variantDictFindInt (&benc, TR_KEY_interval, &i))
                response->interval = i;

            if (tr_variantDictFindInt (&benc, TR_KEY_min_interval, &i))
                response->min_interval = i;

            if (tr_variantDictFindStr (&benc, TR_KEY_tracker_id, &str, &len))
                response->tracker_id_str = tr_strndup (str, len);

            if (tr_variantDictFindInt (&benc, TR_KEY_complete, &i))
                response->seeders = i;

            if (tr_variantDictFindInt (&benc, TR_KEY_incomplete, &i))
                response->leechers = i;

            if (tr_variantDictFindInt (&benc, TR_KEY_downloaded, &i))
                response->downloads = i;

            if (tr_variantDictFindRaw (&benc, TR_KEY_peers6, &raw, &len)) {
                dbgmsg (data->log_name, "got a peers6 length of %zu", len);
                response->pex6 = tr_peerMgrCompact6ToPex (raw, len,
                                              NULL, 0, &response->pex6_count);
            }

            if (tr_variantDictFindRaw (&benc, TR_KEY_peers, &raw, &len)) {
                dbgmsg (data->log_name, "got a compact peers length of %zu", len);
                response->pex = tr_peerMgrCompactToPex (raw, len,
                                               NULL, 0, &response->pex_count);
            } else if (tr_variantDictFindList (&benc, TR_KEY_peers, &tmp)) {
                response->pex = listToPex (tmp, &response->pex_count);
                dbgmsg (data->log_name, "got a peers list with %zu entries",
                        response->pex_count);
            }
        }

        if (variant_loaded)
            tr_variantFree (&benc);
    }

    tr_runInEventThread (session, on_announce_done_eventthread, data);
}
Exemplo n.º 18
0
static uint64_t loadFromFile(tr_torrent* tor, uint64_t fieldsToLoad)
{
    TR_ASSERT(tr_isTorrent(tor));

    size_t len;
    int64_t i;
    char const* str;
    char* filename;
    tr_variant top;
    bool boolVal;
    uint64_t fieldsLoaded = 0;
    bool const wasDirty = tor->isDirty;
    tr_error* error = NULL;

    filename = getResumeFilename(tor);

    if (!tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename, &error))
    {
        tr_logAddTorDbg(tor, "Couldn't read \"%s\": %s", filename, error->message);
        tr_error_free(error);

        tr_free(filename);
        return fieldsLoaded;
    }

    tr_logAddTorDbg(tor, "Read resume file \"%s\"", filename);

    if ((fieldsToLoad & TR_FR_CORRUPT) != 0 && tr_variantDictFindInt(&top, TR_KEY_corrupt, &i))
    {
        tor->corruptPrev = i;
        fieldsLoaded |= TR_FR_CORRUPT;
    }

    if ((fieldsToLoad & (TR_FR_PROGRESS | TR_FR_DOWNLOAD_DIR)) != 0 &&
        tr_variantDictFindStr(&top, TR_KEY_destination, &str, &len) && str != NULL && *str != '\0')
    {
        bool const is_current_dir = tor->currentDir == tor->downloadDir;
        tr_free(tor->downloadDir);
        tor->downloadDir = tr_strndup(str, len);

        if (is_current_dir)
        {
            tor->currentDir = tor->downloadDir;
        }

        fieldsLoaded |= TR_FR_DOWNLOAD_DIR;
    }

    if ((fieldsToLoad & (TR_FR_PROGRESS | TR_FR_INCOMPLETE_DIR)) != 0 &&
        tr_variantDictFindStr(&top, TR_KEY_incomplete_dir, &str, &len) && str != NULL && *str != '\0')
    {
        bool const is_current_dir = tor->currentDir == tor->incompleteDir;
        tr_free(tor->incompleteDir);
        tor->incompleteDir = tr_strndup(str, len);

        if (is_current_dir)
        {
            tor->currentDir = tor->incompleteDir;
        }

        fieldsLoaded |= TR_FR_INCOMPLETE_DIR;
    }

    if ((fieldsToLoad & TR_FR_DOWNLOADED) != 0 && tr_variantDictFindInt(&top, TR_KEY_downloaded, &i))
    {
        tor->downloadedPrev = i;
        fieldsLoaded |= TR_FR_DOWNLOADED;
    }

    if ((fieldsToLoad & TR_FR_UPLOADED) != 0 && tr_variantDictFindInt(&top, TR_KEY_uploaded, &i))
    {
        tor->uploadedPrev = i;
        fieldsLoaded |= TR_FR_UPLOADED;
    }

    if ((fieldsToLoad & TR_FR_MAX_PEERS) != 0 && tr_variantDictFindInt(&top, TR_KEY_max_peers, &i))
    {
        tor->maxConnectedPeers = i;
        fieldsLoaded |= TR_FR_MAX_PEERS;
    }

    if ((fieldsToLoad & TR_FR_RUN) != 0 && tr_variantDictFindBool(&top, TR_KEY_paused, &boolVal))
    {
        tor->isRunning = !boolVal;
        fieldsLoaded |= TR_FR_RUN;
    }

    if ((fieldsToLoad & TR_FR_ADDED_DATE) != 0 && tr_variantDictFindInt(&top, TR_KEY_added_date, &i))
    {
        tor->addedDate = i;
        fieldsLoaded |= TR_FR_ADDED_DATE;
    }

    if ((fieldsToLoad & TR_FR_DONE_DATE) != 0 && tr_variantDictFindInt(&top, TR_KEY_done_date, &i))
    {
        tor->doneDate = i;
        fieldsLoaded |= TR_FR_DONE_DATE;
    }

    if ((fieldsToLoad & TR_FR_ACTIVITY_DATE) != 0 && tr_variantDictFindInt(&top, TR_KEY_activity_date, &i))
    {
        tr_torrentSetActivityDate(tor, i);
        fieldsLoaded |= TR_FR_ACTIVITY_DATE;
    }

    if ((fieldsToLoad & TR_FR_TIME_SEEDING) != 0 && tr_variantDictFindInt(&top, TR_KEY_seeding_time_seconds, &i))
    {
        tor->secondsSeeding = i;
        fieldsLoaded |= TR_FR_TIME_SEEDING;
    }

    if ((fieldsToLoad & TR_FR_TIME_DOWNLOADING) != 0 && tr_variantDictFindInt(&top, TR_KEY_downloading_time_seconds, &i))
    {
        tor->secondsDownloading = i;
        fieldsLoaded |= TR_FR_TIME_DOWNLOADING;
    }

    if ((fieldsToLoad & TR_FR_BANDWIDTH_PRIORITY) != 0 &&
        tr_variantDictFindInt(&top, TR_KEY_bandwidth_priority, &i) && tr_isPriority(i))
    {
        tr_torrentSetPriority(tor, i);
        fieldsLoaded |= TR_FR_BANDWIDTH_PRIORITY;
    }

    if ((fieldsToLoad & TR_FR_PEERS) != 0)
    {
        fieldsLoaded |= loadPeers(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_FILE_PRIORITIES) != 0)
    {
        fieldsLoaded |= loadFilePriorities(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_PROGRESS) != 0)
    {
        fieldsLoaded |= loadProgress(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_DND) != 0)
    {
        fieldsLoaded |= loadDND(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_SPEEDLIMIT) != 0)
    {
        fieldsLoaded |= loadSpeedLimits(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_RATIOLIMIT) != 0)
    {
        fieldsLoaded |= loadRatioLimits(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_IDLELIMIT) != 0)
    {
        fieldsLoaded |= loadIdleLimits(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_FILENAMES) != 0)
    {
        fieldsLoaded |= loadFilenames(&top, tor);
    }

    if ((fieldsToLoad & TR_FR_NAME) != 0)
    {
        fieldsLoaded |= loadName(&top, tor);
    }

    /* loading the resume file triggers of a lot of changes,
     * but none of them needs to trigger a re-saving of the
     * same resume information... */
    tor->isDirty = wasDirty;

    tr_variantFree(&top);
    tr_free(filename);
    return fieldsLoaded;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
tr_session *
libttest_session_init (tr_variant * settings)
{
  size_t len;
  const char * str;
  char * sandbox;
  char * path;
  tr_quark q;
  static bool formatters_inited = false;
  tr_session * session;
  tr_variant local_settings;

  tr_variantInitDict (&local_settings, 10);

  if (settings == NULL)
    settings = &local_settings;

  sandbox = libtest_sandbox_create ();

  if (!formatters_inited)
    {
      formatters_inited = true;
      tr_formatter_mem_init (MEM_K, MEM_K_STR, MEM_M_STR, MEM_G_STR, MEM_T_STR);
      tr_formatter_size_init (DISK_K,DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR);
      tr_formatter_speed_init (SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR);
    }

  /* download dir */
  q = TR_KEY_download_dir;
  if (tr_variantDictFindStr (settings, q, &str, &len))
    path = tr_strdup_printf ("%s/%*.*s", sandbox, (int)len, (int)len, str);
  else
    path = tr_buildPath (sandbox, "Downloads", NULL);
  tr_mkdirp (path, 0700);
  tr_variantDictAddStr (settings, q, path);
  tr_free (path);

  /* incomplete dir */
  q = TR_KEY_incomplete_dir;
  if (tr_variantDictFindStr (settings, q, &str, &len))
    path = tr_strdup_printf ("%s/%*.*s", sandbox, (int)len, (int)len, str);
  else
    path = tr_buildPath (sandbox, "Incomplete", NULL);
  tr_variantDictAddStr (settings, q, path);
  tr_free (path);

  path = tr_buildPath (sandbox, "blocklists", NULL);
  tr_mkdirp (path, 0700);
  tr_free (path);

  q = TR_KEY_port_forwarding_enabled;
  if (!tr_variantDictFind (settings, q))
    tr_variantDictAddBool (settings, q, false);

  q = TR_KEY_dht_enabled;
  if (!tr_variantDictFind (settings, q))
    tr_variantDictAddBool (settings, q, false);

  q = TR_KEY_message_level;
  if (!tr_variantDictFind (settings, q))
    tr_variantDictAddInt (settings, q, verbose ? TR_LOG_DEBUG : TR_LOG_ERROR);

  session = tr_sessionInit ("libtransmission-test", sandbox, !verbose, settings);

  tr_free (sandbox);
  tr_variantFree (&local_settings);
  return session;
}