int
main (int argc, char ** argv)
{
- int error;
tr_session * h;
tr_ctor * ctor;
tr_torrent * tor = NULL;
tr_free (fileContents);
- tor = tr_torrentNew (ctor, &error);
+ tor = tr_torrentNew (ctor, NULL, NULL);
tr_ctorFree (ctor);
if (!tor)
{
if (!err)
{
- tr_torrentNew (ctor, &err);
+ tr_torrentNew (ctor, &err, NULL);
if (err == TR_PARSE_ERR)
tr_logAddError ("Error parsing .torrent file \"%s\"", file);
Set multiple cookies like this: "name1=content1; name2=content2;" etc.
<http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTCOOKIE>
- Response arguments: on success, a "torrent-added" object in the
+ Response arguments: On success, a "torrent-added" object in the
form of one of 3.3's tr_info objects with the
fields for id, name, and hashString.
+ On failure due to a duplicate torrent existing,
+ a "torrent-duplicate" object in the same form.
+
3.5. Removing a Torrent
Method name: "torrent-remove"
15 | 2.80 | yes | torrent-get | new arg "etaIdle"
| | yes | torrent-rename-path | new method
| | yes | free-space | new method
+ | | yes | torrent-add | new return return arg "torrent-duplicate"
5.1. Upcoming Breakage
{
int err = 0;
int new_file = 0;
+ int duplicate_id = 0;
tr_torrent * torrent;
if (filename && (!o->filename || !tr_is_same_file (filename, o->filename)))
tr_ctorSetPaused (o->ctor, TR_FORCE, TRUE);
tr_ctorSetDeleteSource (o->ctor, FALSE);
- if ((torrent = tr_torrentNew (o->ctor, &err)))
+ if ((torrent = tr_torrentNew (o->ctor, &err, &duplicate_id)))
{
removeOldTorrent (o);
o->tor = torrent;
}
else if (new_file)
{
- gtr_add_torrent_error_dialog (GTK_WIDGET (b), err, o->filename);
+ tr_torrent * tor;
+
+ if (duplicate_id)
+ tor = gtr_core_find_torrent (o->core, duplicate_id);
+ else
+ tor = NULL;
+
+ gtr_add_torrent_error_dialog (GTK_WIDGET (b), err, tor, o->filename);
}
updateTorrent (o);
static tr_torrent *
core_create_new_torrent (TrCore * core, tr_ctor * ctor)
{
- int errcode = 0;
tr_torrent * tor;
bool do_trash = false;
tr_session * session = gtr_core_session (core);
* doesn't have any concept of the glib trash API */
tr_ctorGetDeleteSource (ctor, &do_trash);
tr_ctorSetDeleteSource (ctor, FALSE);
- tor = tr_torrentNew (ctor, &errcode);
+ tor = tr_torrentNew (ctor, NULL, NULL);
if (tor && do_trash)
{
}
}
- return tor;
+ return tor;
}
static int
}
void
-gtr_add_torrent_error_dialog (GtkWidget * child, int err, const char * file)
+gtr_add_torrent_error_dialog (GtkWidget * child,
+ int err,
+ tr_torrent * duplicate_torrent,
+ const char * filename)
{
char * secondary;
- const char * fmt;
GtkWidget * w;
GtkWindow * win = getWindow (child);
- switch (err)
- {
- case TR_PARSE_ERR: fmt = _("The torrent file \"%s\" contains invalid data."); break;
- case TR_PARSE_DUPLICATE: fmt = _("The torrent file \"%s\" is already in use."); break;
- default: fmt = _("The torrent file \"%s\" encountered an unknown error."); break;
- }
-
- secondary = g_strdup_printf (fmt, file);
+ if (err == TR_PARSE_ERR)
+ secondary = g_strdup_printf (_("The torrent file \"%s\" contains invalid data."), filename);
+ else if (err == TR_PARSE_DUPLICATE)
+ secondary = g_strdup_printf (_("The torrent file \"%s\" is already in use by \"%s.\""), filename, tr_torrentName (duplicate_torrent));
+ else
+ secondary = g_strdup_printf (_("The torrent file \"%s\" encountered an unknown error."), filename);
w = gtk_message_dialog_new (win,
GTK_DIALOG_DESTROY_WITH_PARENT,
void gtr_add_torrent_error_dialog (GtkWidget * window_or_child,
int err,
+ tr_torrent * duplicate_torrent,
const char * filename);
/* pop up the context menu if a user right-clicks.
/* create the torrent */
err = 0;
- tor = tr_torrentNew (ctor, &err);
+ tor = tr_torrentNew (ctor, &err, NULL);
assert (!err);
/* cleanup */
{ "torrent-complete-notification-enabled", 37 },
{ "torrent-complete-sound-command", 30 },
{ "torrent-complete-sound-enabled", 30 },
+ { "torrent-duplicate", 17 },
{ "torrent-get", 11 },
{ "torrent-set", 11 },
{ "torrent-set-location", 20 },
TR_KEY_torrent_complete_notification_enabled,
TR_KEY_torrent_complete_sound_command,
TR_KEY_torrent_complete_sound_enabled,
+ TR_KEY_torrent_duplicate,
TR_KEY_torrent_get,
TR_KEY_torrent_set,
TR_KEY_torrent_set_location,
/* create the torrent */
err = 0;
- tor = tr_torrentNew (ctor, &err);
+ tor = tr_torrentNew (ctor, &err, NULL);
assert (!err);
/* cleanup */
static void
addTorrentImpl (struct tr_rpc_idle_data * data, tr_ctor * ctor)
{
- int err = 0;
- const char * result = NULL;
- tr_torrent * tor = tr_torrentNew (ctor, &err);
+ int err;
+ int duplicate_id;
+ const char * result;
+ tr_torrent * tor;
+ tr_quark key;
- tr_ctorFree (ctor);
+ err = 0;
+ duplicate_id = 0;
+ tor = tr_torrentNew (ctor, &err, &duplicate_id);
+ tr_ctorFree (ctor);
- if (tor)
+ if (!err)
{
- tr_variant fields;
- tr_variantInitList (&fields, 3);
- tr_variantListAddStr (&fields, "id");
- tr_variantListAddStr (&fields, "name");
- tr_variantListAddStr (&fields, "hashString");
- addInfo (tor, tr_variantDictAdd (data->args_out, TR_KEY_torrent_added), &fields);
- notify (data->session, TR_RPC_TORRENT_ADDED, tor);
- tr_variantFree (&fields);
+ key = TR_KEY_torrent_added;
+ result = NULL;
}
- else if (err == TR_PARSE_DUPLICATE)
+ else if (err == TR_PARSE_ERR)
{
- result = "duplicate torrent";
+ result = "invalid or corrupt torrent file";
}
- else if (err == TR_PARSE_ERR)
+ else if (err == TR_PARSE_DUPLICATE)
{
- result = "invalid or corrupt torrent file";
+ tor = tr_torrentFindFromId (data->session, duplicate_id);
+ key = TR_KEY_torrent_duplicate;
+ result = "duplicate torrent";
}
- tr_idle_function_done (data, result);
+ if (tor != NULL)
+ {
+ tr_variant fields;
+ tr_variantInitList (&fields, 3);
+ tr_variantListAddStr (&fields, "id");
+ tr_variantListAddStr (&fields, "name");
+ tr_variantListAddStr (&fields, "hashString");
+ addInfo (tor, tr_variantDictAdd (data->args_out, key), &fields);
+ notify (data->session, TR_RPC_TORRENT_ADDED, tor);
+ tr_variantFree (&fields);
+ }
+
+ tr_idle_function_done (data, result);
}
tr_torrent * tor;
char * path = tr_buildPath (dirname, d->d_name, NULL);
tr_ctorSetMetainfoFromFile (data->ctor, path);
- if ((tor = tr_torrentNew (data->ctor, NULL)))
+ if ((tor = tr_torrentNew (data->ctor, NULL, NULL)))
{
tr_list_prepend (&list, tor);
++n;
}
static tr_parse_result
-torrentParseImpl (const tr_ctor * ctor, tr_info * setmeInfo,
- bool * setmeHasInfo, int * dictLength)
-{
- int doFree;
- bool didParse;
- bool hasInfo = false;
- tr_info tmp;
+torrentParseImpl (const tr_ctor * ctor,
+ tr_info * setmeInfo,
+ bool * setmeHasInfo,
+ int * dictLength,
+ int * setme_duplicate_id)
+{
+ bool doFree;
+ bool didParse;
+ bool hasInfo = false;
+ tr_info tmp;
const tr_variant * metainfo;
- tr_session * session = tr_ctorGetSession (ctor);
+ tr_session * session = tr_ctorGetSession (ctor);
tr_parse_result result = TR_PARSE_OK;
if (setmeInfo == NULL)
if (didParse && hasInfo && !tr_getBlockSize (setmeInfo->pieceSize))
result = TR_PARSE_ERR;
- if (didParse && session && tr_torrentExists (session, setmeInfo->hash))
- result = TR_PARSE_DUPLICATE;
+ if (didParse && session && (result == TR_PARSE_OK))
+ {
+ const tr_torrent * const tor = tr_torrentFindFromHash (session, setmeInfo->hash);
+
+ if (tor != NULL)
+ {
+ result = TR_PARSE_DUPLICATE;
+
+ if (setme_duplicate_id != NULL)
+ *setme_duplicate_id = tr_torrentId (tor);
+ }
+ }
if (doFree)
tr_metainfoFree (setmeInfo);
tr_parse_result
tr_torrentParse (const tr_ctor * ctor, tr_info * setmeInfo)
{
- return torrentParseImpl (ctor, setmeInfo, NULL, NULL);
+ return torrentParseImpl (ctor, setmeInfo, NULL, NULL, NULL);
}
tr_torrent *
-tr_torrentNew (const tr_ctor * ctor, int * setmeError)
+tr_torrentNew (const tr_ctor * ctor, int * setme_error, int * setme_duplicate_id)
{
- int len;
- bool hasInfo;
- tr_info tmpInfo;
- tr_parse_result r;
- tr_torrent * tor = NULL;
+ int len;
+ bool hasInfo;
+ tr_info tmpInfo;
+ tr_parse_result r;
+ tr_torrent * tor = NULL;
- assert (ctor != NULL);
- assert (tr_isSession (tr_ctorGetSession (ctor)));
+ assert (ctor != NULL);
+ assert (tr_isSession (tr_ctorGetSession (ctor)));
- r = torrentParseImpl (ctor, &tmpInfo, &hasInfo, &len);
- if (r == TR_PARSE_OK)
+ r = torrentParseImpl (ctor, &tmpInfo, &hasInfo, &len, setme_duplicate_id);
+ if (r == TR_PARSE_OK)
{
- tor = tr_new0 (tr_torrent, 1);
- tor->info = tmpInfo;
- if (hasInfo)
- tor->infoDictLength = len;
- torrentInit (tor, ctor);
+ tor = tr_new0 (tr_torrent, 1);
+ tor->info = tmpInfo;
+
+ if (hasInfo)
+ tor->infoDictLength = len;
+
+ torrentInit (tor, ctor);
}
else
{
- if (r == TR_PARSE_DUPLICATE)
- tr_metainfoFree (&tmpInfo);
+ if (r == TR_PARSE_DUPLICATE)
+ tr_metainfoFree (&tmpInfo);
- if (setmeError)
- *setmeError = r;
+ if (setme_error != NULL)
+ *setme_error = r;
}
- return tor;
+ return tor;
}
/**
void tr_metainfoFree (tr_info * inf);
-/** Instantiate a single torrent.
- @return 0 on success,
- TR_EINVALID if the torrent couldn't be parsed, or
- TR_EDUPLICATE if there's already a matching torrent object. */
+/**
+ * Instantiate a single torrent.
+ *
+ * Returns a pointer to the torrent on success, or NULL on failure.
+ *
+ * @param setme_error: TR_PARSE_ERR if the parsing failed;
+ * TR_PARSE_OK if parsing succeeded and it's not a duplicate;
+ * TR_PARSE_DUPLICATE if parsing succeeded but it's a duplicate.
+ *
+ * @param setme_duplicate_id: when setmeError is TR_PARSE_DUPLICATE,
+ * this field is set to the duplicate torrent's id.
+ */
tr_torrent * tr_torrentNew (const tr_ctor * ctor,
- int * setmeError);
+ int * setme_error,
+ int * setme_duplicate_id);
/** @} */
result = tr_ctorSetMetainfoFromHash(ctor, [hashString UTF8String]);
if (result == TR_PARSE_OK)
- fHandle = tr_torrentNew(ctor, NULL);
+ fHandle = tr_torrentNew(ctor, NULL, NULL);
tr_ctorFree(ctor);