source: trunk/libtransmission/torrent-ctor.c

Last change on this file was 14717, checked in by mikedld, 5 years ago

Handle potential dirname/basename errors where needed

  • Property svn:keywords set to Date Rev Author Id
File size: 11.3 KB
Line 
1/*
2 * This file Copyright (C) 2009-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: torrent-ctor.c 14717 2016-03-13 10:41:52Z mikedld $
8 */
9
10#include <errno.h> /* EINVAL */
11
12#include "transmission.h"
13#include "file.h"
14#include "magnet.h"
15#include "session.h" /* tr_sessionFindTorrentFile () */
16#include "torrent.h" /* tr_ctorGetSave () */
17#include "utils.h" /* tr_new0 */
18#include "variant.h"
19
20struct optional_args
21{
22    bool            isSet_paused;
23    bool            isSet_connected;
24    bool            isSet_downloadDir;
25
26    bool            isPaused;
27    uint16_t        peerLimit;
28    char          * downloadDir;
29};
30
31/** Opaque class used when instantiating torrents.
32 * @ingroup tr_ctor */
33struct tr_ctor
34{
35    const tr_session *      session;
36    bool                    saveInOurTorrentsDir;
37    bool                    doDelete;
38
39    tr_priority_t           bandwidthPriority;
40    bool                    isSet_metainfo;
41    bool                    isSet_delete;
42    tr_variant              metainfo;
43    char *                  sourceFile;
44
45    struct optional_args    optionalArgs[2];
46
47    char                  * cookies;
48    char                  * incompleteDir;
49
50    tr_file_index_t       * want;
51    tr_file_index_t         wantSize;
52    tr_file_index_t       * notWant;
53    tr_file_index_t         notWantSize;
54    tr_file_index_t       * low;
55    tr_file_index_t         lowSize;
56    tr_file_index_t       * normal;
57    tr_file_index_t         normalSize;
58    tr_file_index_t       * high;
59    tr_file_index_t         highSize;
60};
61
62/***
63****
64***/
65
66static void
67setSourceFile (tr_ctor *    ctor,
68               const char * sourceFile)
69{
70    tr_free (ctor->sourceFile);
71    ctor->sourceFile = tr_strdup (sourceFile);
72}
73
74static void
75clearMetainfo (tr_ctor * ctor)
76{
77    if (ctor->isSet_metainfo)
78    {
79        ctor->isSet_metainfo = false;
80        tr_variantFree (&ctor->metainfo);
81    }
82
83    setSourceFile (ctor, NULL);
84}
85
86int
87tr_ctorSetMetainfo (tr_ctor *       ctor,
88                    const uint8_t * metainfo,
89                    size_t          len)
90{
91    int err;
92
93    clearMetainfo (ctor);
94    err = tr_variantFromBenc (&ctor->metainfo, metainfo, len);
95    ctor->isSet_metainfo = !err;
96    return err;
97}
98
99const char*
100tr_ctorGetSourceFile (const tr_ctor * ctor)
101{
102    return ctor->sourceFile;
103}
104
105int
106tr_ctorSetMetainfoFromMagnetLink (tr_ctor * ctor, const char * magnet_link)
107{
108    int err;
109    tr_magnet_info * magnet_info = tr_magnetParse (magnet_link);
110
111    if (magnet_info == NULL)
112        err = -1;
113    else {
114        size_t len;
115        tr_variant tmp;
116        char * str;
117
118        tr_magnetCreateMetainfo (magnet_info, &tmp);
119        str = tr_variantToStr (&tmp, TR_VARIANT_FMT_BENC, &len);
120        err = tr_ctorSetMetainfo (ctor, (const uint8_t*)str, len);
121
122        tr_free (str);
123        tr_variantFree (&tmp);
124        tr_magnetFree (magnet_info);
125    }
126
127    return err;
128}
129
130int
131tr_ctorSetMetainfoFromFile (tr_ctor *    ctor,
132                            const char * filename)
133{
134    uint8_t * metainfo;
135    size_t    len;
136    int       err;
137
138    metainfo = tr_loadFile (filename, &len, NULL);
139    if (metainfo && len)
140        err = tr_ctorSetMetainfo (ctor, metainfo, len);
141    else
142    {
143        clearMetainfo (ctor);
144        err = 1;
145    }
146
147    setSourceFile (ctor, filename);
148
149    /* if no `name' field was set, then set it from the filename */
150    if (ctor->isSet_metainfo)
151    {
152        tr_variant * info;
153        if (tr_variantDictFindDict (&ctor->metainfo, TR_KEY_info, &info))
154        {
155            const char * name;
156            if (!tr_variantDictFindStr (info, TR_KEY_name_utf_8, &name, NULL))
157                if (!tr_variantDictFindStr (info, TR_KEY_name, &name, NULL))
158                    name = NULL;
159            if (!name || !*name)
160            {
161                char * base = tr_sys_path_basename (filename, NULL);
162                if (base != NULL)
163                  {
164                    tr_variantDictAddStr (info, TR_KEY_name, base);
165                    tr_free (base);
166                  }
167            }
168        }
169    }
170
171    tr_free (metainfo);
172    return err;
173}
174
175int
176tr_ctorSetMetainfoFromHash (tr_ctor *    ctor,
177                            const char * hashString)
178{
179    int          err;
180    const char * filename;
181
182    filename = tr_sessionFindTorrentFile (ctor->session, hashString);
183    if (!filename)
184        err = EINVAL;
185    else
186        err = tr_ctorSetMetainfoFromFile (ctor, filename);
187
188    return err;
189}
190
191/***
192****
193***/
194
195void
196tr_ctorSetFilePriorities (tr_ctor                * ctor,
197                          const tr_file_index_t  * files,
198                          tr_file_index_t          fileCount,
199                          tr_priority_t            priority)
200{
201    tr_file_index_t ** myfiles;
202    tr_file_index_t * mycount;
203
204    switch (priority) {
205        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
206        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
207        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
208    }
209
210    tr_free (*myfiles);
211    *myfiles = tr_memdup (files, sizeof (tr_file_index_t)*fileCount);
212    *mycount = fileCount;
213}
214
215void
216tr_ctorInitTorrentPriorities (const tr_ctor * ctor, tr_torrent * tor)
217{
218    tr_file_index_t i;
219
220    for (i=0; i<ctor->lowSize; ++i)
221        tr_torrentInitFilePriority (tor, ctor->low[i], TR_PRI_LOW);
222    for (i=0; i<ctor->normalSize; ++i)
223        tr_torrentInitFilePriority (tor, ctor->normal[i], TR_PRI_NORMAL);
224    for (i=0; i<ctor->highSize; ++i)
225        tr_torrentInitFilePriority (tor, ctor->high[i], TR_PRI_HIGH);
226}
227
228void
229tr_ctorSetFilesWanted (tr_ctor                * ctor,
230                       const tr_file_index_t  * files,
231                       tr_file_index_t          fileCount,
232                       bool                     wanted)
233{
234    tr_file_index_t ** myfiles = wanted ? &ctor->want : &ctor->notWant;
235    tr_file_index_t * mycount = wanted ? &ctor->wantSize : &ctor->notWantSize;
236
237    tr_free (*myfiles);
238    *myfiles = tr_memdup (files, sizeof (tr_file_index_t)*fileCount);
239    *mycount = fileCount;
240}
241
242void
243tr_ctorInitTorrentWanted (const tr_ctor * ctor, tr_torrent * tor)
244{
245    if (ctor->notWantSize)
246        tr_torrentInitFileDLs (tor, ctor->notWant, ctor->notWantSize, false);
247    if (ctor->wantSize)
248        tr_torrentInitFileDLs (tor, ctor->want, ctor->wantSize, true);
249}
250
251/***
252****
253***/
254
255void
256tr_ctorSetDeleteSource (tr_ctor * ctor, bool deleteSource)
257{
258    assert (tr_isBool (deleteSource));
259
260    ctor->doDelete = deleteSource;
261    ctor->isSet_delete = true;
262}
263
264bool
265tr_ctorGetDeleteSource (const tr_ctor * ctor, bool * setme)
266{
267    bool ret = true;
268
269    if (!ctor->isSet_delete)
270        ret = false;
271    else if (setme)
272        *setme = ctor->doDelete;
273
274    return ret;
275}
276
277/***
278****
279***/
280
281void
282tr_ctorSetSave (tr_ctor * ctor, bool saveInOurTorrentsDir)
283{
284    assert (tr_isBool (saveInOurTorrentsDir));
285
286    ctor->saveInOurTorrentsDir = saveInOurTorrentsDir;
287}
288
289bool
290tr_ctorGetSave (const tr_ctor * ctor)
291{
292    return ctor && ctor->saveInOurTorrentsDir;
293}
294
295void
296tr_ctorSetPaused (tr_ctor *   ctor,
297                  tr_ctorMode mode,
298                  bool        isPaused)
299{
300    struct optional_args * args;
301
302    assert (ctor != NULL);
303    assert ((mode == TR_FALLBACK) || (mode == TR_FORCE));
304    assert (tr_isBool (isPaused));
305
306    args = &ctor->optionalArgs[mode];
307    args->isSet_paused = true;
308    args->isPaused = isPaused;
309}
310
311void
312tr_ctorSetPeerLimit (tr_ctor *   ctor,
313                     tr_ctorMode mode,
314                     uint16_t    peerLimit)
315{
316    struct optional_args * args;
317
318    assert (ctor != NULL);
319    assert ((mode == TR_FALLBACK) || (mode == TR_FORCE));
320
321    args = &ctor->optionalArgs[mode];
322    args->isSet_connected = true;
323    args->peerLimit = peerLimit;
324}
325
326void
327tr_ctorSetDownloadDir (tr_ctor *    ctor,
328                       tr_ctorMode  mode,
329                       const char * directory)
330{
331    struct optional_args * args;
332
333    assert (ctor != NULL);
334    assert ((mode == TR_FALLBACK) || (mode == TR_FORCE));
335
336    args = &ctor->optionalArgs[mode];
337    tr_free (args->downloadDir);
338    args->downloadDir = NULL;
339    args->isSet_downloadDir = false;
340
341    if (directory && *directory)
342    {
343        args->isSet_downloadDir = true;
344        args->downloadDir = tr_strdup (directory);
345    }
346}
347
348void
349tr_ctorSetIncompleteDir (tr_ctor * ctor, const char * directory)
350{
351    tr_free (ctor->incompleteDir);
352    ctor->incompleteDir = tr_strdup (directory);
353}
354
355bool
356tr_ctorGetPeerLimit (const tr_ctor * ctor,
357                     tr_ctorMode     mode,
358                     uint16_t *      setmeCount)
359{
360    bool ret = true;
361    const struct optional_args * args = &ctor->optionalArgs[mode];
362
363    if (!args->isSet_connected)
364        ret = false;
365    else if (setmeCount)
366        *setmeCount = args->peerLimit;
367
368    return ret;
369}
370
371bool
372tr_ctorGetPaused (const tr_ctor * ctor, tr_ctorMode mode, bool * setmeIsPaused)
373{
374    bool ret = true;
375    const struct optional_args * args = &ctor->optionalArgs[mode];
376
377    if (!args->isSet_paused)
378        ret = false;
379    else if (setmeIsPaused)
380        *setmeIsPaused = args->isPaused;
381
382    return ret;
383}
384
385bool
386tr_ctorGetDownloadDir (const tr_ctor * ctor,
387                       tr_ctorMode     mode,
388                       const char **   setmeDownloadDir)
389{
390    bool ret = true;
391    const struct optional_args * args = &ctor->optionalArgs[mode];
392
393    if (!args->isSet_downloadDir)
394        ret = false;
395    else if (setmeDownloadDir)
396        *setmeDownloadDir = args->downloadDir;
397
398    return ret;
399}
400
401bool
402tr_ctorGetIncompleteDir (const tr_ctor  * ctor,
403                         const char    ** setmeIncompleteDir)
404{
405    bool ret = true;
406
407    if (ctor->incompleteDir == NULL)
408        ret = false;
409    else
410        *setmeIncompleteDir = ctor->incompleteDir;
411
412    return ret;
413}
414
415bool
416tr_ctorGetMetainfo (const tr_ctor *  ctor,
417                    const tr_variant ** setme)
418{
419    bool ret = true;
420
421    if (!ctor->isSet_metainfo)
422        ret = false;
423    else if (setme)
424        *setme = &ctor->metainfo;
425
426    return ret;
427}
428
429tr_session*
430tr_ctorGetSession (const tr_ctor * ctor)
431{
432    return (tr_session*) ctor->session;
433}
434
435/***
436****
437***/
438
439static bool
440isPriority (int i)
441{
442    return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
443}
444
445void
446tr_ctorSetBandwidthPriority (tr_ctor * ctor, tr_priority_t priority)
447{
448    if (isPriority (priority))
449        ctor->bandwidthPriority = priority;
450}
451
452tr_priority_t
453tr_ctorGetBandwidthPriority (const tr_ctor * ctor)
454{
455    return ctor->bandwidthPriority;
456}
457
458/***
459****
460***/
461
462tr_ctor*
463tr_ctorNew (const tr_session * session)
464{
465    tr_ctor * ctor = tr_new0 (struct tr_ctor, 1);
466
467    ctor->session = session;
468    ctor->bandwidthPriority = TR_PRI_NORMAL;
469    if (session != NULL)
470    {
471        tr_ctorSetDeleteSource (ctor, tr_sessionGetDeleteSource (session));
472        tr_ctorSetPaused (ctor, TR_FALLBACK, tr_sessionGetPaused (session));
473        tr_ctorSetPeerLimit (ctor, TR_FALLBACK, session->peerLimitPerTorrent);
474        tr_ctorSetDownloadDir (ctor, TR_FALLBACK, tr_sessionGetDownloadDir(session));
475    }
476    tr_ctorSetSave (ctor, true);
477    return ctor;
478}
479
480void
481tr_ctorFree (tr_ctor * ctor)
482{
483    clearMetainfo (ctor);
484    tr_free (ctor->optionalArgs[1].downloadDir);
485    tr_free (ctor->optionalArgs[0].downloadDir);
486    tr_free (ctor->incompleteDir);
487    tr_free (ctor->want);
488    tr_free (ctor->notWant);
489    tr_free (ctor->low);
490    tr_free (ctor->high);
491    tr_free (ctor->normal);
492    tr_free (ctor);
493}
Note: See TracBrowser for help on using the repository browser.