Exemplo n.º 1
0
void
tr_magnetCreateMetainfo (const tr_magnet_info * info, tr_variant * top)
{
  int i;
  tr_variant * d;
  tr_variantInitDict (top, 4);

  /* announce list */
  if (info->trackerCount == 1)
    {
      tr_variantDictAddStr (top, TR_KEY_announce, info->trackers[0]);
    }
  else
    {
      tr_variant * trackers = tr_variantDictAddList (top, TR_KEY_announce_list, info->trackerCount);
      for (i=0; i<info->trackerCount; ++i)
        tr_variantListAddStr (tr_variantListAddList (trackers, 1), info->trackers[i]);
    }

  /* webseeds */
  if (info->webseedCount > 0)
    {
      tr_variant * urls = tr_variantDictAddList (top, TR_KEY_url_list, info->webseedCount);
      for (i=0; i<info->webseedCount; ++i)
        tr_variantListAddStr (urls, info->webseeds[i]);
    }

  /* nonstandard keys */
  d = tr_variantDictAddDict (top, TR_KEY_magnet_info, 2);
  tr_variantDictAddRaw (d, TR_KEY_info_hash, info->hash, 20);
  if (info->displayName != NULL)
    tr_variantDictAddStr (d, TR_KEY_display_name, info->displayName);
}
Exemplo n.º 2
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.º 3
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.º 4
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.º 5
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.º 6
0
/**
 * This is where we initialize the preferences file with the default values.
 * If you add a new preferences key, you /must/ add a default value here.
 */
static void
tr_prefs_init_defaults (tr_variant * d)
{
  const char * dir;

  dir = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD);
  if (dir == NULL)
    dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
  if (dir == NULL)
    dir = tr_getDefaultDownloadDir ();

  tr_variantDictReserve (d, 29);
  tr_variantDictAddStr  (d, TR_KEY_watch_dir, dir);
  tr_variantDictAddBool (d, TR_KEY_watch_dir_enabled, FALSE);
  tr_variantDictAddBool (d, TR_KEY_user_has_given_informed_consent, FALSE);
  tr_variantDictAddBool (d, TR_KEY_inhibit_desktop_hibernation, FALSE);
  tr_variantDictAddBool (d, TR_KEY_blocklist_updates_enabled, TRUE);
  tr_variantDictAddStr  (d, TR_KEY_open_dialog_dir, g_get_home_dir ());
  tr_variantDictAddBool (d, TR_KEY_show_toolbar, TRUE);
  tr_variantDictAddBool (d, TR_KEY_show_filterbar, TRUE);
  tr_variantDictAddBool (d, TR_KEY_show_statusbar, TRUE);
  tr_variantDictAddBool (d, TR_KEY_trash_can_enabled, TRUE);
  tr_variantDictAddBool (d, TR_KEY_show_notification_area_icon, FALSE);
  tr_variantDictAddBool (d, TR_KEY_show_tracker_scrapes, FALSE);
  tr_variantDictAddBool (d, TR_KEY_show_extra_peer_details, FALSE);
  tr_variantDictAddBool (d, TR_KEY_show_backup_trackers, FALSE);
  tr_variantDictAddStr  (d, TR_KEY_statusbar_stats, "total-ratio");
  tr_variantDictAddBool (d, TR_KEY_torrent_added_notification_enabled, true);
  tr_variantDictAddBool (d, TR_KEY_torrent_complete_notification_enabled, true);
  tr_variantDictAddStr  (d, TR_KEY_torrent_complete_sound_command, "canberra-gtk-play -i complete-download -d 'transmission torrent downloaded'");
  tr_variantDictAddBool (d, TR_KEY_torrent_complete_sound_enabled, true);
  tr_variantDictAddBool (d, TR_KEY_show_options_window, TRUE);
  tr_variantDictAddBool (d, TR_KEY_main_window_is_maximized, FALSE);
  tr_variantDictAddInt  (d, TR_KEY_main_window_height, 500);
  tr_variantDictAddInt  (d, TR_KEY_main_window_width, 300);
  tr_variantDictAddInt  (d, TR_KEY_main_window_x, 50);
  tr_variantDictAddInt  (d, TR_KEY_main_window_y, 50);
  tr_variantDictAddStr  (d, TR_KEY_download_dir, dir);
  tr_variantDictAddStr  (d, TR_KEY_sort_mode, "sort-by-name");
  tr_variantDictAddBool (d, TR_KEY_sort_reversed, FALSE);
  tr_variantDictAddBool (d, TR_KEY_compact_view, FALSE);
}
Exemplo n.º 7
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.º 8
0
static void saveProgress(tr_variant* dict, tr_torrent* tor)
{
    tr_variant* l;
    tr_variant* prog;
    tr_info const* inf = tr_torrentInfo(tor);
    time_t const now = tr_time();

    prog = tr_variantDictAddDict(dict, TR_KEY_progress, 3);

    /* add the file/piece check timestamps... */
    l = tr_variantDictAddList(prog, TR_KEY_time_checked, inf->fileCount);

    for (tr_file_index_t fi = 0; fi < inf->fileCount; ++fi)
    {
        time_t oldest_nonzero = now;
        time_t newest = 0;
        bool has_zero = false;
        time_t const mtime = tr_torrentGetFileMTime(tor, fi);
        tr_file const* f = &inf->files[fi];

        /* get the oldest and newest nonzero timestamps for pieces in this file */
        for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
        {
            tr_piece const* const p = &inf->pieces[i];

            if (p->timeChecked == 0)
            {
                has_zero = true;
            }
            else if (oldest_nonzero > p->timeChecked)
            {
                oldest_nonzero = p->timeChecked;
            }

            if (newest < p->timeChecked)
            {
                newest = p->timeChecked;
            }
        }

        /* If some of a file's pieces have been checked more recently than
           the file's mtime, and some less 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. */

        if (!has_zero && mtime <= oldest_nonzero) /* all checked */
        {
            tr_variantListAddInt(l, oldest_nonzero);
        }
        else if (newest < mtime) /* none checked */
        {
            tr_variantListAddInt(l, newest);
        }
        else /* some are checked, some aren't... so list piece by piece */
        {
            int const offset = oldest_nonzero - 1;
            tr_variant* ll = tr_variantListAddList(l, 2 + f->lastPiece - f->firstPiece);
            tr_variantListAddInt(ll, offset);

            for (tr_piece_index_t i = f->firstPiece; i <= f->lastPiece; ++i)
            {
                tr_piece const* const p = &inf->pieces[i];

                tr_variantListAddInt(ll, p->timeChecked != 0 ? p->timeChecked - offset : 0);
            }
        }
    }

    /* add the progress */
    if (tor->completeness == TR_SEED)
    {
        tr_variantDictAddStr(prog, TR_KEY_have, "all");
    }

    /* add the blocks bitfield */
    bitfieldToBenc(&tor->completion.blockBitfield, tr_variantDictAdd(prog, TR_KEY_blocks));
}
Exemplo n.º 9
0
static void saveName(tr_variant* dict, tr_torrent const* tor)
{
    tr_variantDictAddStr(dict, TR_KEY_name, tr_torrentName(tor));
}
Exemplo n.º 10
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.º 11
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;
}
Exemplo n.º 12
0
void
gtr_pref_string_set (const tr_quark key, const char * value)
{
  tr_variantDictAddStr (getPrefs (), key, value);
}