Skip to content

Commit e473667

Browse files
initial project version 1.30
ADD: Tab page Files/trackers/info ADD: Optional start program from console. (See readme.txt file) ADD: remove_trackers.txt will remove specific trackers form torrent. ADD: export_trackers.txt is created after updating the torrent. ADD: drag and drop of trackers file (with '*.txt' file extention) Fix: tab page Data/info 'Total size' sort functionality. Fix: tab page Data/info 'Piece Length' sort functionality. Fix: tab page Data/info 'info hash' must be uppercase. FIX: issue 4 + 5 (see website) Compiler Lazarus: v1.24
0 parents  commit e473667

17 files changed

+4045
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/export_trackers.txt
2+
/console_log.txt
3+
/*.txt

MIT_License.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Copyright (c) 2013 Gerry Ferdinandus
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4+
and associated documentation files (the "Software"), to deal in the Software without restriction,
5+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7+
subject to the following conditions:
8+
9+
The above copyright notice and this permission notice shall be included in all copies or substantial portions
10+
of the Software.
11+
12+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
14+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
15+
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
16+
DEALINGS IN THE SOFTWARE.

SourceCodeBuild.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Build from source.
2+
3+
Install latest Lazarus IDE
4+
http://www.lazarus.freepascal.org/
5+
6+
Open project file:
7+
menu Project -> open project
8+
select 'trackereditor.lpi' file
9+
10+
Build:
11+
Menu Run -> Build
12+
Executable file is created in the same dir as the trackereditor.lpi

add_trackers.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
udp://tracker.openbittorrent.com:80/announce
2+
udp://tracker.publicbt.com:80/announce
3+
udp://tracker.istole.it:80/announce
4+
udp://open.demonii.com:1337/announce

bencode.pas

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
{
2+
Decode and encode the Bencode format used in torrent files
3+
4+
public domain code?
5+
Source code from:
6+
http://www.torry.net/quicksearchd.php?String=bencode&Title=Yes
7+
8+
With some minor modification made by Gerry Ferdinandus
9+
}
10+
11+
{
12+
Bug fix 2014-10-09
13+
'i' integer now accept negative number
14+
if not ((X in ['0'..'9' , '-']) or (X = 'e')) then
15+
raise Exception.Create('');
16+
17+
}
18+
19+
unit BEncode;
20+
{$mode objfpc}{$H+}
21+
interface
22+
23+
24+
uses
25+
Classes, Contnrs, SysUtils;
26+
27+
type
28+
TBEncodedFormat = (befEmpty, befString, befInteger, befList, befDictionary);
29+
30+
TBEncoded = class;
31+
32+
TBEncodedData = class
33+
public
34+
Header: string;
35+
Data: TBEncoded;
36+
destructor Destroy; override;
37+
public
38+
constructor Create(Data_: TBEncoded);
39+
end;
40+
41+
{ TBEncodedDataList }
42+
43+
TBEncodedDataList = class(TObjectList)
44+
protected
45+
function GetItems(Index: Integer): TBEncodedData;
46+
procedure SetItems(Index: Integer; AClass: TBEncodedData);
47+
public
48+
function FindElement(Header: string): TBEncoded;
49+
function Add(AClass: TBEncodedData): Integer;
50+
function Extract(Item: TBEncodedData): TBEncodedData;
51+
function Remove(AClass: TBEncodedData): Integer;
52+
function IndexOf(AClass: TBEncodedData): Integer;
53+
54+
function RemoveElement(Header: string): integer;//2011-1030
55+
56+
function First: TBEncodedData;
57+
function Last: TBEncodedData;
58+
procedure Insert(Index: Integer; AClass: TBEncodedData);
59+
property Items[Index: Integer]: TBEncodedData read GetItems write SetItems;
60+
default;
61+
end;
62+
63+
TBEncoded = class(TObject)
64+
private
65+
FFormat: TBEncodedFormat;
66+
procedure SetFormat(Format: TBEncodedFormat);
67+
public
68+
StringData: string;
69+
IntegerData: int64;
70+
ListData: TBEncodedDataList;
71+
property Format: TBEncodedFormat read FFormat write SetFormat;
72+
class procedure Encode(Encoded: TBEncoded; var Output: string);
73+
destructor Destroy; override;
74+
constructor Create(Stream: TStream);
75+
constructor Create;
76+
end;
77+
78+
implementation
79+
80+
destructor TBEncodedData.Destroy;
81+
begin
82+
Data.Free;
83+
inherited Destroy;
84+
end;
85+
86+
constructor TBEncodedData.Create(Data_: TBEncoded);
87+
begin
88+
inherited Create;
89+
Self.Data := Data_;
90+
end;
91+
92+
destructor TBEncoded.Destroy;
93+
begin
94+
if ListData <> nil then
95+
ListData.Free;
96+
97+
inherited Destroy;
98+
end;
99+
100+
constructor TBEncoded.Create(Stream: TStream);
101+
102+
function GetString(Buffer: string): string;
103+
var
104+
X: char;
105+
begin
106+
// loop until we come across it
107+
X := ' ';
108+
repeat
109+
if Stream.Read(X, 1) <> 1 then
110+
raise Exception.Create('');
111+
if not ((X in ['0'..'9']) or (x = ':')) then
112+
raise Exception.Create('');
113+
if X = ':' then
114+
begin
115+
if Buffer = '' then
116+
raise Exception.Create('');
117+
if Length(Buffer) > 6 then
118+
raise Exception.Create('');
119+
SetLength(Result, StrToInt(Buffer));
120+
if Stream.Read(Result[1], Length(Result)) <> Length(Result) then
121+
raise Exception.Create('');
122+
Break;
123+
end
124+
else
125+
Buffer := Buffer + X;
126+
until False;
127+
end;
128+
129+
var
130+
X: char;
131+
Buffer: string;
132+
Data: TBEncodedData;
133+
Encoded: TBEncoded;
134+
begin
135+
inherited Create;
136+
137+
X := ' ';
138+
139+
// get first character to determine the format of the proceeding data
140+
if Stream.Read(X, 1) <> 1 then
141+
raise Exception.Create('');
142+
143+
// is it an integer?
144+
if X = 'i' then
145+
begin
146+
// yes it is, let's read until we come across e
147+
Buffer := '';
148+
repeat
149+
//must be able to read the stream
150+
if Stream.Read(X, 1) <> 1 then
151+
raise Exception.Create('');
152+
153+
//Must be a integer value or 'e'
154+
if not ((X in ['0'..'9' , '-']) or (X = 'e')) then
155+
raise Exception.Create('');
156+
157+
//if found the 'end' then decode it.
158+
if X = 'e' then
159+
begin
160+
if Buffer = '' then
161+
raise Exception.Create('')
162+
else
163+
begin
164+
Format := befInteger;
165+
IntegerData := StrToInt64(Buffer);
166+
Break;
167+
end;
168+
end
169+
else
170+
Buffer := Buffer + X;
171+
until False;
172+
end
173+
// is it a list?
174+
else if X = 'l' then
175+
begin
176+
// its a list
177+
Format := befList;
178+
179+
// loop until we come across e
180+
repeat
181+
// have a peek around and see if theres an e
182+
if Stream.Read(X, 1) <> 1 then
183+
raise Exception.Create('');
184+
// is it an e?
185+
if X = 'e' then
186+
Break;
187+
// otherwise move the cursor back
188+
Stream.Seek(-1, soFromCurrent);
189+
// create the element
190+
Encoded := TBEncoded.Create(Stream);
191+
// add it to the list
192+
ListData.Add(TBEncodedData.Create(Encoded));
193+
until False;
194+
end
195+
// is it a dictionary?
196+
else if X = 'd' then
197+
begin
198+
// its a dictionary :>
199+
Format := befDictionary;
200+
201+
// loop until we come across e
202+
repeat
203+
// have a peek around and see if theres an e
204+
if Stream.Read(X, 1) <> 1 then
205+
raise Exception.Create('');
206+
// is it an e?
207+
if X = 'e' then
208+
Break;
209+
// if it isnt an e it has to be numerical!
210+
if not (X in ['0'..'9']) then
211+
raise Exception.Create('');
212+
// now read the string data
213+
Buffer := GetString(string(X));
214+
// create the element
215+
Encoded := TBEncoded.Create(Stream);
216+
// create the data element
217+
Data := TBEncodedData.Create(Encoded);
218+
Data.Header := Buffer;
219+
// add it to the list
220+
ListData.Add(Data);
221+
until False;
222+
end
223+
// is it a string?
224+
else if X in ['0'..'9'] then
225+
begin
226+
StringData := GetString(string(X));
227+
Format := befString;
228+
end
229+
else
230+
raise Exception.Create('');
231+
end;
232+
233+
constructor TBEncoded.Create;
234+
begin
235+
inherited Create;
236+
end;
237+
238+
class procedure TBEncoded.Encode(Encoded: TBEncoded; var Output: string);
239+
var
240+
i: integer;
241+
begin
242+
with Encoded do
243+
begin
244+
// what type of member is it?
245+
case Format of
246+
befString: Output := Output + IntToStr(Length(StringData)) + ':' +
247+
StringData;
248+
befInteger: Output := Output + 'i' + IntToStr(IntegerData) + 'e';
249+
befList:
250+
begin
251+
Output := Output + 'l';
252+
for i := 0 to ListData.Count - 1 do
253+
Encode(TBEncoded(ListData[i].Data), Output);
254+
Output := Output + 'e';
255+
end;
256+
befDictionary:
257+
begin
258+
Output := Output + 'd';
259+
for i := 0 to ListData.Count - 1 do
260+
begin
261+
Output := Output + IntToStr(Length(ListData[i].Header)) + ':' +
262+
ListData[i].Header;
263+
Encode(TBEncoded(ListData[i].Data), Output);
264+
end;
265+
Output := Output + 'e';
266+
end;
267+
end;
268+
end;
269+
end;
270+
271+
procedure TBEncoded.SetFormat(Format: TBEncodedFormat);
272+
begin
273+
if Format in [befList, befDictionary] then
274+
ListData := TBEncodedDataList.Create;
275+
FFormat := Format;
276+
end;
277+
278+
function TBEncodedDataList.FindElement(Header: string): TBEncoded;
279+
var
280+
i: integer;
281+
begin
282+
Header := LowerCase(Header);
283+
for i := 0 to Count - 1 do
284+
if LowerCase(Items[i].Header) = Header then
285+
begin
286+
Result := Items[i].Data;
287+
Exit;
288+
end;
289+
290+
Result := nil;
291+
end;
292+
293+
function TBEncodedDataList.Add(AClass: TBEncodedData): Integer;
294+
begin
295+
Result := inherited Add(AClass);
296+
end;
297+
298+
function TBEncodedDataList.Extract(Item: TBEncodedData): TBEncodedData;
299+
begin
300+
Result := TBEncodedData(inherited Extract(Item));
301+
end;
302+
303+
function TBEncodedDataList.First: TBEncodedData;
304+
begin
305+
Result := TBEncodedData(inherited First);
306+
end;
307+
308+
function TBEncodedDataList.GetItems(Index: Integer): TBEncodedData;
309+
begin
310+
Result := TBEncodedData(inherited Items[Index]);
311+
end;
312+
313+
function TBEncodedDataList.IndexOf(AClass: TBEncodedData): Integer;
314+
begin
315+
Result := inherited IndexOf(AClass);
316+
end;
317+
318+
function TBEncodedDataList.RemoveElement(Header: string): Integer;
319+
var
320+
i: integer;
321+
begin
322+
Header := LowerCase(Header);
323+
for i := 0 to Count - 1 do
324+
if LowerCase(Items[i].Header) = Header then
325+
begin
326+
Result := i;
327+
Remove(Items[i]);//memory will be released.
328+
Exit;
329+
end;
330+
Result := -1;
331+
end;
332+
333+
procedure TBEncodedDataList.Insert(Index: Integer; AClass: TBEncodedData);
334+
begin
335+
inherited Insert(Index, AClass);
336+
end;
337+
338+
function TBEncodedDataList.Last: TBEncodedData;
339+
begin
340+
Result := TBEncodedData(inherited First);
341+
end;
342+
343+
function TBEncodedDataList.Remove(AClass: TBEncodedData): Integer;
344+
begin
345+
Result := inherited Remove(AClass);
346+
end;
347+
348+
procedure TBEncodedDataList.SetItems(Index: Integer; AClass: TBEncodedData);
349+
begin
350+
inherited Items[Index] := AClass;
351+
end;
352+
353+
end.

0 commit comments

Comments
 (0)