Exemplo n.º 1
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.º 2
0
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;
}
Exemplo n.º 3
0
void
tr_dhtUninit (tr_session *ss)
{
    if (session != ss)
        return;

    tr_logAddNamedDbg ("DHT", "Uninitializing DHT");

    if (dht_timer != NULL) {
        event_free (dht_timer);
        dht_timer = NULL;
    }

    /* Since we only save known good nodes, avoid erasing older data if we
       don't know enough nodes. */
    if ((tr_dhtStatus (ss, AF_INET, NULL) < TR_DHT_FIREWALLED) &&
      (tr_dhtStatus (ss, AF_INET6, NULL) < TR_DHT_FIREWALLED)) {
        tr_logAddNamedInfo ("DHT", "Not saving nodes, DHT not ready");
    } else {
        tr_variant benc;
        struct sockaddr_in sins[300];
        struct sockaddr_in6 sins6[300];
        char compact[300 * 6], compact6[300 * 18];
        char *dat_file;
        int i, j, num = 300, num6 = 300;
        int n = dht_get_nodes (sins, &num, sins6, &num6);

        tr_logAddNamedInfo ("DHT", "Saving %d (%d + %d) nodes", n, num, num6);

        j = 0;
        for (i=0; i<num; ++i) {
            memcpy (compact + j, &sins[i].sin_addr, 4);
            memcpy (compact + j + 4, &sins[i].sin_port, 2);
            j += 6;
        }
        j = 0;
        for (i=0; i<num6; ++i) {
            memcpy (compact6 + j, &sins6[i].sin6_addr, 16);
            memcpy (compact6 + j + 16, &sins6[i].sin6_port, 2);
            j += 18;
        }
        tr_variantInitDict (&benc, 3);
        tr_variantDictAddRaw (&benc, TR_KEY_id, myid, 20);
        if (num > 0)
            tr_variantDictAddRaw (&benc, TR_KEY_nodes, compact, num * 6);
        if (num6 > 0)
            tr_variantDictAddRaw (&benc, TR_KEY_nodes6, compact6, num6 * 18);
        dat_file = tr_buildPath (ss->configDir, "dht.dat", NULL);
        tr_variantToFile (&benc, TR_VARIANT_FMT_BENC, dat_file);
        tr_variantFree (&benc);
        tr_free (dat_file);
    }

    dht_uninit ();
    tr_logAddNamedDbg ("DHT", "Done uninitializing DHT");

    session = NULL;
}
Exemplo n.º 4
0
void tr_torrentSaveResume(tr_torrent* tor)
{
    int err;
    tr_variant top;
    char* filename;

    if (!tr_isTorrent(tor))
    {
        return;
    }

    tr_variantInitDict(&top, 50); /* arbitrary "big enough" number */
    tr_variantDictAddInt(&top, TR_KEY_seeding_time_seconds, tor->secondsSeeding);
    tr_variantDictAddInt(&top, TR_KEY_downloading_time_seconds, tor->secondsDownloading);
    tr_variantDictAddInt(&top, TR_KEY_activity_date, tor->activityDate);
    tr_variantDictAddInt(&top, TR_KEY_added_date, tor->addedDate);
    tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->corruptPrev + tor->corruptCur);
    tr_variantDictAddInt(&top, TR_KEY_done_date, tor->doneDate);
    tr_variantDictAddStr(&top, TR_KEY_destination, tor->downloadDir);

    if (tor->incompleteDir != NULL)
    {
        tr_variantDictAddStr(&top, TR_KEY_incomplete_dir, tor->incompleteDir);
    }

    tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->downloadedPrev + tor->downloadedCur);
    tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur);
    tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->maxConnectedPeers);
    tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tr_torrentGetPriority(tor));
    tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued);
    savePeers(&top, tor);

    if (tr_torrentHasMetadata(tor))
    {
        saveFilePriorities(&top, tor);
        saveDND(&top, tor);
        saveProgress(&top, tor);
    }

    saveSpeedLimits(&top, tor);
    saveRatioLimits(&top, tor);
    saveIdleLimits(&top, tor);
    saveFilenames(&top, tor);
    saveName(&top, tor);

    filename = getResumeFilename(tor);

    if ((err = tr_variantToFile(&top, TR_VARIANT_FMT_BENC, filename)) != 0)
    {
        tr_torrentSetLocalError(tor, "Unable to save resume file: %s", tr_strerror(err));
    }

    tr_free(filename);

    tr_variantFree(&top);
}
Exemplo n.º 5
0
static void
clearMetainfo (tr_ctor * ctor)
{
    if (ctor->isSet_metainfo)
    {
        ctor->isSet_metainfo = false;
        tr_variantFree (&ctor->metainfo);
    }

    setSourceFile (ctor, NULL);
}
Exemplo n.º 6
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.º 7
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.º 8
0
static void loadCumulativeStats(tr_session const* session, tr_session_stats* setme)
{
    tr_variant top;
    char* filename;
    bool loaded = false;

    filename = getFilename(session);
    loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_JSON, filename, NULL);
    tr_free(filename);

    if (!loaded)
    {
        filename = getOldFilename(session);
        loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename, NULL);
        tr_free(filename);
    }

    if (loaded)
    {
        int64_t i;

        if (tr_variantDictFindInt(&top, TR_KEY_downloaded_bytes, &i))
        {
            setme->downloadedBytes = (uint64_t)i;
        }

        if (tr_variantDictFindInt(&top, TR_KEY_files_added, &i))
        {
            setme->filesAdded = (uint64_t)i;
        }

        if (tr_variantDictFindInt(&top, TR_KEY_seconds_active, &i))
        {
            setme->secondsActive = (uint64_t)i;
        }

        if (tr_variantDictFindInt(&top, TR_KEY_session_count, &i))
        {
            setme->sessionCount = (uint64_t)i;
        }

        if (tr_variantDictFindInt(&top, TR_KEY_uploaded_bytes, &i))
        {
            setme->uploadedBytes = (uint64_t)i;
        }

        tr_variantFree(&top);
    }
}
Exemplo n.º 9
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.º 10
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.º 11
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.º 12
0
static void
gotsig (int sig)
{
    switch (sig)
    {
        case SIGHUP:
        {
            if (!mySession)
            {
                tr_logAddInfo ("Deferring reload until session is fully started.");
                seenHUP = true;
            }
            else
            {
                tr_variant settings;
                const char * configDir;

                /* reopen the logfile to allow for log rotation */
                if (logfileName) {
                    logfile = freopen (logfileName, LOGFILE_MODE_STR, logfile);
                    if (!logfile)
                        fprintf (stderr, "Couldn't reopen \"%s\": %s\n", logfileName, tr_strerror (errno));
                }

                configDir = tr_sessionGetConfigDir (mySession);
                tr_logAddInfo ("Reloading settings from \"%s\"", configDir);
                tr_variantInitDict (&settings, 0);
                tr_variantDictAddBool (&settings, TR_KEY_rpc_enabled, true);
                tr_sessionLoadSettings (&settings, configDir, MY_NAME);
                tr_sessionSet (mySession, &settings);
                tr_variantFree (&settings);
                tr_sessionReloadBlocklists (mySession);
            }
            break;
        }

        default:
            tr_logAddError ("Unexpected signal (%d) in daemon, closing.", sig);
            /* no break */

        case SIGINT:
        case SIGTERM:
            event_base_loopexit(ev_base, NULL);
            break;
    }
}
Exemplo n.º 13
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.º 14
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.º 15
0
static void saveCumulativeStats(tr_session const* session, tr_session_stats const* s)
{
    char* filename;
    tr_variant top;

    tr_variantInitDict(&top, 5);
    tr_variantDictAddInt(&top, TR_KEY_downloaded_bytes, s->downloadedBytes);
    tr_variantDictAddInt(&top, TR_KEY_files_added, s->filesAdded);
    tr_variantDictAddInt(&top, TR_KEY_seconds_active, s->secondsActive);
    tr_variantDictAddInt(&top, TR_KEY_session_count, s->sessionCount);
    tr_variantDictAddInt(&top, TR_KEY_uploaded_bytes, s->uploadedBytes);

    filename = getFilename(session);
    tr_logAddDeep(__FILE__, __LINE__, NULL, "Saving stats to \"%s\"", filename);
    tr_variantToFile(&top, TR_VARIANT_FMT_JSON, filename);

    tr_free(filename);
    tr_variantFree(&top);
}
Exemplo n.º 16
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.º 17
0
int
tr_ctorSetMetainfoFromMagnetLink (tr_ctor * ctor, const char * magnet_link)
{
    int err;
    tr_magnet_info * magnet_info = tr_magnetParse (magnet_link);

    if (magnet_info == NULL)
        err = -1;
    else {
        int len;
        tr_variant tmp;
        char * str;

        tr_magnetCreateMetainfo (magnet_info, &tmp);
        str = tr_variantToStr (&tmp, TR_VARIANT_FMT_BENC, &len);
        err = tr_ctorSetMetainfo (ctor, (const uint8_t*)str, len);

        tr_free (str);
        tr_variantFree (&tmp);
        tr_magnetFree (magnet_info);
    }

    return err;
}
Exemplo n.º 18
0
static void
handle_upload (struct evhttp_request * req,
               struct tr_rpc_server  * server)
{
  if (req->type != EVHTTP_REQ_POST)
    {
      send_simple_response (req, 405, NULL);
    }
  else
    {
      int i;
      int n;
      bool hasSessionId = false;
      tr_ptrArray parts = TR_PTR_ARRAY_INIT;

      const char * query = strchr (req->uri, '?');
      const bool paused = query && strstr (query + 1, "paused=true");

      extract_parts_from_multipart (req->input_headers, req->input_buffer, &parts);
      n = tr_ptrArraySize (&parts);

      /* first look for the session id */
      for (i=0; i<n; ++i)
        {
          struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
          if (tr_memmem (p->headers, p->headers_len, TR_RPC_SESSION_ID_HEADER, strlen (TR_RPC_SESSION_ID_HEADER)))
            break;
        }

      if (i<n)
        {
          const struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
          const char * ours = get_current_session_id (server);
          const size_t ourlen = strlen (ours);
          hasSessionId = ourlen <= p->body_len && memcmp (p->body, ours, ourlen) == 0;
        }

      if (!hasSessionId)
        {
          int code = 409;
          const char * codetext = tr_webGetResponseStr (code);
          struct evbuffer * body = evbuffer_new ();
          evbuffer_add_printf (body, "%s", "{ \"success\": false, \"msg\": \"Bad Session-Id\" }");;
          evhttp_send_reply (req, code, codetext, body);
          evbuffer_free (body);
        }
      else for (i=0; i<n; ++i)
        {
          struct tr_mimepart * p = tr_ptrArrayNth (&parts, i);
          size_t body_len = p->body_len;
          tr_variant top, *args;
          tr_variant test;
          bool have_source = false;
          char * body = p->body;

          if (body_len >= 2 && memcmp (&body[body_len - 2], "\r\n", 2) == 0)
            body_len -= 2;

          tr_variantInitDict (&top, 2);
          tr_variantDictAddStr (&top, TR_KEY_method, "torrent-add");
          args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2);
          tr_variantDictAddBool (args, TR_KEY_paused, paused);

          if (tr_urlIsValid (body, body_len))
            {
              tr_variantDictAddRaw (args, TR_KEY_filename, body, body_len);
              have_source = true;
            }
          else if (!tr_variantFromBenc (&test, body, body_len))
            {
              char * b64 = tr_base64_encode (body, body_len, NULL);
              tr_variantDictAddStr (args, TR_KEY_metainfo, b64);
              tr_free (b64);
              have_source = true;
            }

          if (have_source)
            tr_rpc_request_exec_json (server->session, &top, NULL, NULL);

          tr_variantFree (&top);
        }

      tr_ptrArrayDestruct (&parts, (PtrArrayForeachFunc)tr_mimepart_free);

      /* send "success" response */
      {
        int code = HTTP_OK;
        const char * codetext = tr_webGetResponseStr (code);
        struct evbuffer * body = evbuffer_new ();
        evbuffer_add_printf (body, "%s", "{ \"success\": true, \"msg\": \"Torrent Added\" }");;
        evhttp_send_reply (req, code, codetext, body);
        evbuffer_free (body);
      }
    }
}
Exemplo n.º 19
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.º 20
0
static void
doScrape (const tr_info * inf)
{
  unsigned int i;

  for (i=0; i<inf->trackerCount; ++i)
    {
      CURL * curl;
      CURLcode res;
      struct evbuffer * buf;
      const char * scrape = inf->trackers[i].scrape;
      char * url;
      char escaped[SHA_DIGEST_LENGTH*3 + 1];

      if (scrape == NULL)
        continue;

      tr_http_escape_sha1 (escaped, inf->hash);

      url = tr_strdup_printf ("%s%cinfo_hash=%s",
                              scrape,
                              strchr (scrape, '?') ? '&' : '?',
                              escaped);

      printf ("%s ... ", url);
      fflush (stdout);

      buf = evbuffer_new ();
      curl = tr_curl_easy_init (buf);
      curl_easy_setopt (curl, CURLOPT_URL, url);
      curl_easy_setopt (curl, CURLOPT_TIMEOUT, TIMEOUT_SECS);

      if ((res = curl_easy_perform (curl)))
        {
          printf ("error: %s\n", curl_easy_strerror (res));
        }
      else
        {
          long response;
          curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response);
          if (response != 200)
            {
              printf ("error: unexpected response %ld \"%s\"\n",
                      response,
                      tr_webGetResponseStr (response));
            }
          else /* HTTP OK */
            {
              tr_variant top;
              tr_variant * files;
              bool matched = false;
              const char * begin = (const char*) evbuffer_pullup (buf, -1);

              if (!tr_variantFromBenc (&top, begin, evbuffer_get_length(buf)))
                {
                  if (tr_variantDictFindDict (&top, TR_KEY_files, &files))
                    {
                      int i = 0;
                      tr_quark key;
                      tr_variant * val;

                      while (tr_variantDictChild (files, i++, &key, &val))
                        {
                          if (memcmp (inf->hash, tr_quark_get_string (key, NULL), SHA_DIGEST_LENGTH) == 0)
                            {
                              int64_t seeders = -1;
                              int64_t leechers = -1;
                              tr_variantDictFindInt (val, TR_KEY_complete, &seeders);
                              tr_variantDictFindInt (val, TR_KEY_incomplete, &leechers);
                              printf ("%d seeders, %d leechers\n", (int)seeders, (int)leechers);
                              matched = true;
                            }
                        }
                    }

                  tr_variantFree (&top);
                }

              if (!matched)
                printf ("no match\n");
            }
        }

      curl_easy_cleanup (curl);
      evbuffer_free (buf);
      tr_free (url);
    }
}
Exemplo n.º 21
0
int
tr_dhtInit (tr_session *ss)
{
    tr_variant benc;
    int rc;
    bool have_id = false;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if (session) /* already initialized */
        return -1;

    tr_logAddNamedDbg ("DHT", "Initializing DHT");

    if (tr_env_key_exists ("TR_DHT_VERBOSE"))
        dht_debug = stderr;

    dat_file = tr_buildPath (ss->configDir, "dht.dat", NULL);
    rc = tr_variantFromFile (&benc, TR_VARIANT_FMT_BENC, dat_file, NULL) ? 0 : -1;
    tr_free (dat_file);
    if (rc == 0) {
        have_id = tr_variantDictFindRaw (&benc, TR_KEY_id, &raw, &len);
        if (have_id && len==20)
            memcpy (myid, raw, len);
        if (ss->udp_socket != TR_BAD_SOCKET &&
            tr_variantDictFindRaw (&benc, TR_KEY_nodes, &raw, &len) && ! (len%6)) {
                nodes = tr_memdup (raw, len);
        }
        if (ss->udp6_socket != TR_BAD_SOCKET &&
            tr_variantDictFindRaw (&benc, TR_KEY_nodes6, &raw, &len6) && ! (len6%18)) {
            nodes6 = tr_memdup (raw, len6);
        }
        tr_variantFree (&benc);
    }

    if (nodes == NULL)
        len = 0;
    if (nodes6 == NULL)
        len6 = 0;

    if (have_id)
        tr_logAddNamedInfo ("DHT", "Reusing old id");
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_logAddNamedInfo ("DHT", "Generating new id");
        tr_rand_buffer (myid, 20);
    }

    rc = dht_init (ss->udp_socket, ss->udp6_socket, myid, NULL);
    if (rc < 0)
        goto fail;

    session = ss;

    cl = tr_new (struct bootstrap_closure, 1);
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew (dht_bootstrap, cl);

    dht_timer = evtimer_new (session->event_base, timer_callback, session);
    tr_timerAdd (dht_timer, 0, tr_rand_int_weak (1000000));

    tr_logAddNamedDbg ("DHT", "DHT initialized");

    return 1;

 fail:
    tr_logAddNamedDbg ("DHT", "DHT initialization failed (errno = %d)", errno);
    session = NULL;
    return -1;
}
Exemplo n.º 22
0
int
main (int argc, char * argv[])
{
  int i;
  int changedCount = 0;

#ifdef _WIN32
  tr_win32_make_args_utf8 (&argc, &argv);
#endif

  files = tr_new0 (const char*, argc);

  tr_logSetLevel (TR_LOG_ERROR);

  if (parseCommandLine (argc, (const char**)argv))
    return EXIT_FAILURE;

  if (showVersion)
    {
      fprintf (stderr, MY_NAME" "LONG_VERSION_STRING"\n");
      return EXIT_SUCCESS;
    }

  if (fileCount < 1)
    {
      fprintf (stderr, "ERROR: No torrent files specified.\n");
      tr_getopt_usage (MY_NAME, getUsage (), options);
      fprintf (stderr, "\n");
      return EXIT_FAILURE;
    }

  if (!add && !deleteme && !replace[0])
    {
      fprintf (stderr, "ERROR: Must specify -a, -d or -r\n");
      tr_getopt_usage (MY_NAME, getUsage (), options);
      fprintf (stderr, "\n");
      return EXIT_FAILURE;
    }

  for (i=0; i<fileCount; ++i)
    {
      tr_variant top;
      bool changed = false;
      const char * filename = files[i];

      printf ("%s\n", filename);

      if (tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename))
        {
          printf ("\tError reading file\n");
          continue;
        }

      if (deleteme != NULL)
        changed |= removeURL (&top, deleteme);

      if (add != NULL)
        changed = addURL (&top, add);

      if (replace[0] && replace[1])
        changed |= replaceURL (&top, replace[0], replace[1]);

      if (changed)
        {
          ++changedCount;
          tr_variantToFile (&top, TR_VARIANT_FMT_BENC, filename);
        }

      tr_variantFree (&top);
    }

  printf ("Changed %d files\n", changedCount);

  tr_free (files);
  return EXIT_SUCCESS;
}
Exemplo n.º 23
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.º 24
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.º 25
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;
}