~ubuntu-branches/ubuntu/raring/transmission/raring

« back to all changes in this revision

Viewing changes to .pc/0110-dont_truncate_string.patch/utils/edit.c

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Klimonda
  • Date: 2011-03-22 18:59:19 UTC
  • Revision ID: james.westby@ubuntu.com-20110322185919-ceizoba779xccx1r
Tags: 2.13-0ubuntu7
* debian/patches/0108-sync_web_interface_turtle_mode_with_gui.patch
  - Keep GUI and web interface in sync when toggling speed limit mode.
    (LP: #727629)
* debian/patches/0109-fix_crash_on_missing_script.patch (LP: #710003)
  - Fix crash when the configured script is not found.
* debian/patches/0110-dont_truncate_string.patch:
  - Don't truncace string when transmission-edit -r option is used. 
* debian/patches/0111-call_guessPacketOverhead_for_reads.patch
  - Fix peer-io code so packet overhead is calculated for socket reads.
* 0112-fix_check_for_result_of_tr_torrentGetMetadataPercent.patch:
  - tr_torrentGetMetadataPercent() may return NULL; fix the check in
    torrent-magnet.c to handle it.
* debian/patches/0113-fix_support_for_ipv6_trackers.patch:
  - Fix support for IPv6-only trackers.
* debian/patches/0114-dont_move_file_if_src_and_dest_are_the_same.patch:
  - Don't move files and directories if the destination path is the same
    as origin.
* debian/patches/0115-fix_tall_argument.patch:
  - Fix the "-tall" argument in transmission-remote.
* debian/patches/0116-fix_segfault_in_gtk_client.patch:
  - Fix crash in the Gtk+ client when adding many torrents remotely.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file Copyright (C) 2010 Mnemosyne LLC
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 2
 
6
 * as published by the Free Software Foundation.
 
7
 *
 
8
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 
9
 *
 
10
 * $Id: edit.c 11160 2010-08-08 22:53:24Z charles $
 
11
 */
 
12
 
 
13
#include <stdio.h>
 
14
 
 
15
#include <event.h> /* evbuffer */
 
16
 
 
17
#include <libtransmission/transmission.h>
 
18
#include <libtransmission/bencode.h>
 
19
#include <libtransmission/tr-getopt.h>
 
20
#include <libtransmission/utils.h>
 
21
#include <libtransmission/version.h>
 
22
 
 
23
#define MY_NAME "transmission-edit"
 
24
 
 
25
static int fileCount = 0;
 
26
static tr_bool showVersion = FALSE;
 
27
static const char ** files = NULL;
 
28
static const char * add = NULL;
 
29
static const char * deleteme = NULL;
 
30
static const char * replace[2] = { NULL, NULL };
 
31
 
 
32
static tr_option options[] =
 
33
{
 
34
  { 'a', "add", "Add a tracker's announce URL", "a", 1, "<url>" },
 
35
  { 'd', "delete", "Delete a tracker's announce URL", "d", 1, "<url>" },
 
36
  { 'r', "replace", "Search and replace a substring in the announce URLs", "r", 1, "<old> <new>" },
 
37
  { 'V', "version", "Show version number and exit", "V", 0, NULL },
 
38
  { 0, NULL, NULL, NULL, 0, NULL }
 
39
};
 
40
 
 
41
static const char *
 
42
getUsage( void )
 
43
{
 
44
    return "Usage: " MY_NAME " [options] torrent-file(s)";
 
45
}
 
46
 
 
47
static int
 
48
parseCommandLine( int argc, const char ** argv )
 
49
{
 
50
    int c;
 
51
    const char * optarg;
 
52
 
 
53
    while(( c = tr_getopt( getUsage( ), argc, argv, options, &optarg )))
 
54
    {
 
55
        switch( c )
 
56
        {
 
57
            case 'a': add = optarg;
 
58
                      break;
 
59
            case 'd': deleteme = optarg;
 
60
                      break;
 
61
            case 'r': replace[0] = optarg;
 
62
                      c = tr_getopt( getUsage( ), argc, argv, options, &optarg );
 
63
                      if( c != TR_OPT_UNK ) return 1;
 
64
                      replace[1] = optarg;
 
65
                      break;
 
66
            case 'V': showVersion = TRUE;
 
67
                      break;
 
68
            case TR_OPT_UNK: files[fileCount++] = optarg; break;
 
69
            default: return 1;
 
70
        }
 
71
    }
 
72
 
 
73
    return 0;
 
74
}
 
75
 
 
76
static tr_bool
 
77
removeURL( tr_benc * metainfo, const char * url )
 
78
{
 
79
    const char * str;
 
80
    tr_benc * announce_list;
 
81
    tr_bool changed = FALSE;
 
82
 
 
83
    if( tr_bencDictFindStr( metainfo, "announce", &str ) && !strcmp( str, url ) )
 
84
    {
 
85
        printf( "\tRemoved \"%s\" from \"announce\"\n", str );
 
86
        tr_bencDictRemove( metainfo, "announce" );
 
87
        changed = TRUE;
 
88
    }
 
89
 
 
90
    if( tr_bencDictFindList( metainfo, "announce-list", &announce_list ) )
 
91
    {
 
92
        tr_benc * tier;
 
93
        int tierIndex = 0;
 
94
        while(( tier = tr_bencListChild( announce_list, tierIndex )))
 
95
        {
 
96
            tr_benc * node;
 
97
            int nodeIndex = 0;
 
98
            while(( node = tr_bencListChild( tier, nodeIndex )))
 
99
            {
 
100
                if( tr_bencGetStr( node, &str ) && !strcmp( str, url ) )
 
101
                {
 
102
                    printf( "\tRemoved \"%s\" from \"announce-list\" tier #%d\n", str, (tierIndex+1) );
 
103
                    tr_bencListRemove( tier, nodeIndex );
 
104
                    changed = TRUE;
 
105
                }
 
106
                else ++nodeIndex;
 
107
            }
 
108
 
 
109
            if( tr_bencListSize( tier ) == 0 )
 
110
            {
 
111
                printf( "\tNo URLs left in tier #%d... removing tier\n", (tierIndex+1) );
 
112
                tr_bencListRemove( announce_list, tierIndex );
 
113
            }
 
114
            else ++tierIndex;
 
115
        }
 
116
 
 
117
        if( tr_bencListSize( announce_list ) == 0 )
 
118
        {
 
119
            printf( "\tNo tiers left... removing announce-list\n" );
 
120
            tr_bencDictRemove( metainfo, "announce-list" );
 
121
        }
 
122
    }
 
123
 
 
124
    /* if we removed the "announce" field and there's still another track left,
 
125
     * use it as the "announce" field */
 
126
    if( changed && !tr_bencDictFindStr( metainfo, "announce", &str ) )
 
127
    {
 
128
        tr_benc * tier;
 
129
        tr_benc * node;
 
130
 
 
131
        if(( tier = tr_bencListChild( announce_list, 0 ))) {
 
132
            if(( node = tr_bencListChild( tier, 0 ))) {
 
133
                if( tr_bencGetStr( node, &str ) ) {
 
134
                    tr_bencDictAddStr( metainfo, "announce", str );
 
135
                    printf( "\tAdded \"%s\" to announce\n", str );
 
136
                }
 
137
            }
 
138
        }
 
139
    }
 
140
        
 
141
 
 
142
    return changed;
 
143
}
 
144
 
 
145
static char*
 
146
replaceSubstr( const char * str, const char * in, const char * out )
 
147
{
 
148
    char * walk;
 
149
    struct evbuffer * buf = evbuffer_new( );
 
150
    const size_t inlen = strlen( in );
 
151
    const size_t outlen = strlen( out );
 
152
 
 
153
    while(( walk = strstr( str, in )))
 
154
    {
 
155
        evbuffer_add( buf, str, walk-str );
 
156
        evbuffer_add( buf, out, outlen );
 
157
        str = walk + inlen;
 
158
    }
 
159
 
 
160
    walk = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
 
161
    evbuffer_free( buf );
 
162
    return walk;
 
163
}
 
164
 
 
165
static tr_bool
 
166
replaceURL( tr_benc * metainfo, const char * in, const char * out )
 
167
{
 
168
    const char * str;
 
169
    tr_benc * announce_list;
 
170
    tr_bool changed = FALSE;
 
171
 
 
172
    if( tr_bencDictFindStr( metainfo, "announce", &str ) && strstr( str, in ) )
 
173
    {
 
174
        char * newstr = replaceSubstr( str, in, out );
 
175
        printf( "\tReplaced in \"announce\": \"%s\" --> \"%s\"\n", str, newstr );
 
176
        tr_bencDictAddStr( metainfo, "announce", newstr );
 
177
        tr_free( newstr );
 
178
        changed = TRUE;
 
179
    }
 
180
 
 
181
    if( tr_bencDictFindList( metainfo, "announce-list", &announce_list ) )
 
182
    {
 
183
        tr_benc * tier;
 
184
        int tierCount = 0;
 
185
        while(( tier = tr_bencListChild( announce_list, tierCount++ )))
 
186
        {
 
187
            tr_benc * node;
 
188
            int nodeCount = 0;
 
189
            while(( node = tr_bencListChild( tier, nodeCount++ )))
 
190
            {
 
191
                if( tr_bencGetStr( node, &str ) && strstr( str, in ) )
 
192
                {
 
193
                    char * newstr = replaceSubstr( str, in, out );
 
194
                    printf( "\tReplaced in \"announce-list\" tier %d: \"%s\" --> \"%s\"\n", tierCount, str, newstr );
 
195
                    tr_bencFree( node );
 
196
                    tr_bencInitStr( node, newstr, -1 );
 
197
                    tr_free( newstr );
 
198
                    changed = TRUE;
 
199
                }
 
200
            }
 
201
        }
 
202
    }
 
203
 
 
204
    return changed;
 
205
}
 
206
 
 
207
static tr_bool
 
208
addURL( tr_benc * metainfo, const char * url )
 
209
{
 
210
    const char * str;
 
211
    tr_benc * announce_list;
 
212
    tr_bool changed = FALSE;
 
213
    tr_bool match = FALSE;
 
214
 
 
215
    /* maybe add it to "announce" */
 
216
    if( !tr_bencDictFindStr( metainfo, "announce", &str ) )
 
217
    {
 
218
        printf( "\tAdded \"%s\" in \"announce\"\n", url );
 
219
        tr_bencDictAddStr( metainfo, "announce", url );
 
220
        changed = TRUE;
 
221
    }
 
222
 
 
223
    /* see if it's already in announce-list */
 
224
    if( tr_bencDictFindList( metainfo, "announce-list", &announce_list ) ) {
 
225
        tr_benc * tier;
 
226
        int tierCount = 0;
 
227
        while(( tier = tr_bencListChild( announce_list, tierCount++ ))) {
 
228
            tr_benc * node;
 
229
            int nodeCount = 0;
 
230
            while(( node = tr_bencListChild( tier, nodeCount++ )))
 
231
                if( tr_bencGetStr( node, &str ) && !strcmp( str, url ) )
 
232
                    match = TRUE;
 
233
        }
 
234
    }
 
235
 
 
236
    /* if it's not in announce-list, add it now */
 
237
    if( !match )
 
238
    {
 
239
        tr_benc * tier;
 
240
 
 
241
        if( !tr_bencDictFindList( metainfo, "announce-list", &announce_list ) )
 
242
            announce_list = tr_bencDictAddList( metainfo, "announce-list", 1 );
 
243
 
 
244
        tier = tr_bencListAddList( announce_list, 1 );
 
245
        tr_bencListAddStr( tier, url );
 
246
        printf( "\tAdded \"%s\" to \"announce-list\" tier %zu\n", url, tr_bencListSize( announce_list ) );
 
247
        changed = TRUE;
 
248
    }
 
249
 
 
250
    return changed;
 
251
}
 
252
 
 
253
int
 
254
main( int argc, char * argv[] )
 
255
{
 
256
    int i;
 
257
    int changedCount = 0;
 
258
 
 
259
    files = tr_new0( const char*, argc );
 
260
 
 
261
    tr_setMessageLevel( TR_MSG_ERR );
 
262
 
 
263
    if( parseCommandLine( argc, (const char**)argv ) )
 
264
        return EXIT_FAILURE;
 
265
 
 
266
    if( showVersion )
 
267
    {
 
268
        fprintf( stderr, MY_NAME" "LONG_VERSION_STRING"\n" );
 
269
        return 0;
 
270
    }
 
271
 
 
272
    if( fileCount < 1 )
 
273
    {
 
274
        fprintf( stderr, "ERROR: No torrent files specified.\n" );
 
275
        tr_getopt_usage( MY_NAME, getUsage( ), options );
 
276
        fprintf( stderr, "\n" );
 
277
        return EXIT_FAILURE;
 
278
    }
 
279
 
 
280
    if( !add && !deleteme && !replace[0] )
 
281
    {
 
282
        fprintf( stderr, "ERROR: Must specify -a, -d or -r\n" );
 
283
        tr_getopt_usage( MY_NAME, getUsage( ), options );
 
284
        fprintf( stderr, "\n" );
 
285
        return EXIT_FAILURE;
 
286
    }
 
287
 
 
288
    for( i=0; i<fileCount; ++i )
 
289
    {
 
290
        tr_benc top;
 
291
        tr_bool changed = FALSE;
 
292
        const char * filename = files[i];
 
293
 
 
294
        printf( "%s\n", filename );
 
295
 
 
296
        if( tr_bencLoadFile( &top, TR_FMT_BENC, filename ) )
 
297
        {
 
298
            printf( "\tError reading file\n" );
 
299
            continue;
 
300
        }
 
301
 
 
302
        if( deleteme != NULL )
 
303
            changed |= removeURL( &top, deleteme );
 
304
 
 
305
        if( add != NULL )
 
306
            changed = addURL( &top, add );
 
307
 
 
308
        if( replace[0] && replace[1] )
 
309
            changed |= replaceURL( &top, replace[0], replace[1] );
 
310
 
 
311
        if( changed )
 
312
        {
 
313
            ++changedCount;
 
314
            tr_bencToFile( &top, TR_FMT_BENC, filename );
 
315
        }
 
316
 
 
317
        tr_bencFree( &top );
 
318
    }
 
319
 
 
320
    printf( "Changed %d files\n", changedCount );
 
321
 
 
322
    tr_free( files );
 
323
    return 0;
 
324
}